File Coverage

lib/Type/Registry.pm
Criterion Covered Total %
statement 146 170 86.4
branch 36 58 62.0
condition 23 45 51.1
subroutine 34 36 94.4
pod 17 17 100.0
total 256 326 78.8


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