File Coverage

lib/Type/Registry.pm
Criterion Covered Total %
statement 139 162 86.4
branch 33 54 61.1
condition 18 39 46.1
subroutine 33 35 94.2
pod 17 17 100.0
total 240 307 78.5


line stmt bran cond sub pod time code
1             package Type::Registry;
2              
3 20     20   19317 use 5.008001;
  20         77  
4 20     20   148 use strict;
  20         40  
  20         448  
5 20     20   100 use warnings;
  20         34  
  20         846  
6              
7             BEGIN {
8 20     20   61 $Type::Registry::AUTHORITY = 'cpan:TOBYINK';
9 20         718 $Type::Registry::VERSION = '2.004000';
10             }
11              
12             $Type::Registry::VERSION =~ tr/_//d;
13              
14 20     20   124 use Exporter::Tiny qw( mkopt );
  20         46  
  20         151  
15 20     20   6157 use Scalar::Util qw( refaddr );
  20         45  
  20         1127  
16 20     20   7034 use Type::Parser qw( eval_type );
  20         54  
  20         188  
17 20     20   5071 use Types::TypeTiny ();
  20         50  
  20         9156  
18              
19             our @ISA = 'Exporter::Tiny';
20             our @EXPORT_OK = qw(t);
21              
22 4     4   35 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  4         23  
23              
24             sub _generate_t {
25 10     10   1531 my $class = shift;
26 10         25 my ( $name, $value, $globals ) = @_;
27            
28 10         23 my $caller = $globals->{into};
29 10 100       96 my $reg = $class->for_class(
30             ref( $caller ) ? sprintf( 'HASH(0x%08X)', refaddr( $caller ) ) : $caller );
31            
32 10 100   44   78 sub (;$) { @_ ? $reg->lookup( @_ ) : $reg };
  44         12100  
33             } #/ sub _generate_t
34              
35             sub new {
36 62     62 1 1120 my $class = shift;
37 62 50       167 ref( $class ) and _croak( "Not an object method" );
38 62         382 bless {}, $class;
39             }
40              
41             {
42             my %registries;
43            
44             sub for_class {
45 437     437 1 1060 my $class = shift;
46 437         778 my ( $for ) = @_;
47 437   66     1585 $registries{$for} ||= $class->new;
48             }
49            
50             sub for_me {
51 8     8 1 50 my $class = shift;
52 8         22 my $for = caller;
53 8   33     71 $registries{$for} ||= $class->new;
54             }
55             }
56              
57             sub add_types {
58 11     11 1 41 my $self = shift;
59 11         62 my $opts = mkopt( \@_ );
60 11         242 for my $opt ( @$opts ) {
61 12         36 my ( $library, $types ) = @$opt;
62 12         58 $library =~ s/^-/Types::/;
63            
64             {
65 12     1   25 local $SIG{__DIE__} = sub { };
  12         93  
66 12         695 eval "require $library";
67             };
68            
69 12         55 my %hash;
70            
71 12 100 66     164 if ( $library->isa( "Type::Library" ) or $library eq 'Types::TypeTiny' ) {
    100 66        
    50          
    50          
72 10   100     83 $types ||= [qw/-types/];
73 10 50       83 Types::TypeTiny::is_ArrayLike( $types )
74             or _croak(
75             "Expected arrayref following '%s'; got %s", $library,
76             $types
77             );
78            
79 10         106 $library->import( { into => \%hash }, @$types );
80 10         510 $hash{$_} = &{ $hash{$_} }() for keys %hash;
  379         3130  
81             } #/ if ( $library->isa( "Type::Library"...))
82             elsif ( $library->isa( "Exporter" )
83 20     20   163 and my $type_tag = do { no strict 'refs'; ${"$library\::EXPORT_TAGS"}{'types'} } ) {
  20         42  
  20         31659  
  1         3  
  1         7  
84 1   33     7 $types ||= $type_tag;
85 1         6 $hash{$_} = $library->$_ for @$types;
86             }
87             elsif ( $library->isa( "MooseX::Types::Base" ) ) {
88 0   0     0 $types ||= [];
89 0 0 0     0 Types::TypeTiny::is_ArrayLike( $types ) && ( @$types == 0 )
90             or _croak(
91             "Library '%s' is a MooseX::Types type constraint library. No import options currently supported",
92             $library
93             );
94            
95 0         0 require Moose::Util::TypeConstraints;
96 0         0 my $moosextypes = $library->type_storage;
97 0         0 for my $name ( sort keys %$moosextypes ) {
98             my $tt = Types::TypeTiny::to_TypeTiny(
99 0         0 Moose::Util::TypeConstraints::find_type_constraint( $moosextypes->{$name} ) );
100 0         0 $hash{$name} = $tt;
101             }
102             } #/ elsif ( $library->isa( "MooseX::Types::Base"...))
103             elsif ( $library->isa( "MouseX::Types::Base" ) ) {
104 0   0     0 $types ||= [];
105 0 0 0     0 Types::TypeTiny::is_ArrayLike( $types ) && ( @$types == 0 )
106             or _croak(
107             "Library '%s' is a MouseX::Types type constraint library. No import options currently supported",
108             $library
109             );
110            
111 0         0 require Mouse::Util::TypeConstraints;
112 0         0 my $moosextypes = $library->type_storage;
113 0         0 for my $name ( sort keys %$moosextypes ) {
114             my $tt = Types::TypeTiny::to_TypeTiny(
115 0         0 Mouse::Util::TypeConstraints::find_type_constraint( $moosextypes->{$name} ) );
116 0         0 $hash{$name} = $tt;
117             }
118             } #/ elsif ( $library->isa( "MouseX::Types::Base"...))
119             else {
120 1         5 _croak( "%s is not a type library", $library );
121             }
122            
123 11         262 for my $key ( sort keys %hash ) {
124             exists( $self->{$key} )
125             and $self->{$key}{uniq} != $hash{$key}{uniq}
126 382 50 66     723 and _croak( "Duplicate type name: %s", $key );
127 382         626 $self->{$key} = $hash{$key};
128             }
129             } #/ for my $opt ( @$opts )
130 10         50 $self;
131             } #/ sub add_types
132              
133             sub add_type {
134 1262     1262 1 1576 my $self = shift;
135 1262         1949 my ( $type, $name ) = @_;
136 1262         2326 $type = Types::TypeTiny::to_TypeTiny( $type );
137 1262   100     2282 $name ||= do {
138 4 100       17 $type->is_anon
139             and
140             _croak( "Expected named type constraint; got anonymous type constraint" );
141 3         10 $type->name;
142             };
143            
144             exists( $self->{$name} )
145             and $self->{$name}{uniq} != $type->{uniq}
146 1261 50 66     2559 and _croak( "Duplicate type name: %s", $name );
147            
148 1261         2077 $self->{$name} = $type;
149 1261         1960 $self;
150             } #/ sub add_type
151              
152             sub alias_type {
153 5     5 1 10 my $self = shift;
154 5         15 my ( $old, @new ) = @_;
155 5 100       8 my $lookup = eval { $self->lookup( $old ) }
  5         18  
156             or _croak( "Expected existing type constraint name; got '$old'" );
157 4         17 $self->{$_} = $lookup for @new;
158 4         8 $self;
159             }
160              
161             sub simple_lookup {
162 185     185 1 254 my $self = shift;
163            
164 185         307 my ( $tc ) = @_;
165 185         716 $tc =~ s/(^\s+|\s+$)//g;
166            
167 185 100       466 if ( exists $self->{$tc} ) {
    100          
168 157         504 return $self->{$tc};
169             }
170             elsif ( $self->has_parent ) {
171 2         6 return $self->get_parent->simple_lookup( @_ );
172             }
173            
174 26         112 return;
175             } #/ sub simple_lookup
176              
177             sub set_parent {
178 1     1 1 2 my $self = shift;
179 1 50 33     11 $self->{'~~parent'} =
180             ref( $_[0] )
181             ? $_[0]
182             : ( ref( $self ) || $self )->for_class( $_[0] );
183 1         3 $self;
184             }
185              
186             sub clear_parent {
187 1     1 1 169 my $self = shift;
188 1         3 delete $self->{'~~parent'};
189 1         3 $self;
190             }
191              
192             sub has_parent {
193 28     28 1 102 !!ref( shift->{'~~parent'} );
194             }
195              
196             sub get_parent {
197 3     3 1 18 shift->{'~~parent'};
198             }
199              
200             sub foreign_lookup {
201 4     4 1 8 my $self = shift;
202            
203 4 50       34 return $_[1] ? () : $self->simple_lookup( $_[0], 1 )
    100          
204             unless $_[0] =~ /^(.+)::(\w+)$/;
205            
206 1         3 my $library = $1;
207 1         3 my $typename = $2;
208            
209             {
210 1     0   2 local $SIG{__DIE__} = sub { };
  1         7  
211 1         67 eval "require $library;";
212             };
213            
214 1 50       15 if ( $library->isa( 'MooseX::Types::Base' ) ) {
215 0         0 require Moose::Util::TypeConstraints;
216 0 0       0 my $type = Moose::Util::TypeConstraints::find_type_constraint(
217             $library->get_type( $typename ) )
218             or return;
219 0         0 return Types::TypeTiny::to_TypeTiny( $type );
220             }
221            
222 1 50       8 if ( $library->isa( 'MouseX::Types::Base' ) ) {
223 0         0 require Mouse::Util::TypeConstraints;
224 0 0       0 my $sub = $library->can( $typename ) or return;
225 0 0       0 my $type = Mouse::Util::TypeConstraints::find_type_constraint( $sub->() )
226             or return;
227 0         0 return Types::TypeTiny::to_TypeTiny( $type );
228             }
229            
230 1 50       19 if ( $library->can( "get_type" ) ) {
231 1         5 my $type = $library->get_type( $typename );
232 1         4 return Types::TypeTiny::to_TypeTiny( $type );
233             }
234            
235 0         0 return;
236             } #/ sub foreign_lookup
237              
238             sub lookup {
239 27     27 1 73 my $self = shift;
240            
241 27 100       78 $self->simple_lookup( @_ ) or eval_type( $_[0], $self );
242             }
243              
244             sub make_union {
245 1     1 1 2 my $self = shift;
246 1         4 my ( @types ) = @_;
247            
248 1         402 require Type::Tiny::Union;
249 1         5 return "Type::Tiny::Union"->new( type_constraints => \@types );
250             }
251              
252             sub _make_union_by_overload {
253 18     18   28 my $self = shift;
254 18         35 my ( @types ) = @_;
255            
256 18         535 require Type::Tiny::Union;
257 18         64 return "Type::Tiny::Union"->new_by_overload( type_constraints => \@types );
258             }
259              
260             sub make_intersection {
261 1     1 1 3 my $self = shift;
262 1         3 my ( @types ) = @_;
263            
264 1         424 require Type::Tiny::Intersection;
265 1         5 return "Type::Tiny::Intersection"->new( type_constraints => \@types );
266             }
267              
268             sub _make_intersection_by_overload {
269 8     8   12 my $self = shift;
270 8         18 my ( @types ) = @_;
271            
272 8         36 require Type::Tiny::Intersection;
273 8         26 return "Type::Tiny::Intersection"->new_by_overload( type_constraints => \@types );
274             }
275              
276             sub make_class_type {
277 10     10 1 16 my $self = shift;
278 10         21 my ( $class ) = @_;
279            
280 10         53 require Types::Standard;
281 10         32 return Types::Standard::InstanceOf()->of( $class );
282             }
283              
284             sub make_role_type {
285 3     3 1 9 my $self = shift;
286 3         7 my ( $role ) = @_;
287            
288 3         15 require Types::Standard;
289 3         12 return Types::Standard::ConsumerOf()->of( $role );
290             }
291              
292             sub AUTOLOAD {
293 17     17   50 my $self = shift;
294 17         117 my ( $method ) = ( our $AUTOLOAD =~ /(\w+)$/ );
295 17         54 my $type = $self->simple_lookup( $method );
296 17 100       102 return $type if $type;
297 1         5 _croak(
298             q[Can't locate object method "%s" via package "%s"], $method,
299             ref( $self )
300             );
301             } #/ sub AUTOLOAD
302              
303             # Prevent AUTOLOAD being called for DESTROY!
304             sub DESTROY {
305 0     0     return; # uncoverable statement
306             }
307              
308             DELAYED: {
309             our %DELAYED;
310             for my $package ( sort keys %DELAYED ) {
311             my $reg = __PACKAGE__->for_class( $package );
312             my $types = $DELAYED{$package};
313            
314             for my $name ( sort keys %$types ) {
315             $reg->add_type( $types->{$name}, $name );
316             }
317             }
318             } #/ DELAYED:
319              
320             1;
321              
322             __END__