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   15978 use 5.008001;
  20         75  
4 20     20   415 use strict;
  20         50  
  20         488  
5 20     20   115 use warnings;
  20         55  
  20         890  
6              
7             BEGIN {
8 20     20   60 $Type::Registry::AUTHORITY = 'cpan:TOBYINK';
9 20         838 $Type::Registry::VERSION = '2.002001';
10             }
11              
12             $Type::Registry::VERSION =~ tr/_//d;
13              
14 20     20   123 use Exporter::Tiny qw( mkopt );
  20         44  
  20         172  
15 20     20   6225 use Scalar::Util qw( refaddr );
  20         242  
  20         1299  
16 20     20   7497 use Type::Parser qw( eval_type );
  20         62  
  20         184  
17 20     20   5113 use Types::TypeTiny ();
  20         790  
  20         9308  
18              
19             our @ISA = 'Exporter::Tiny';
20             our @EXPORT_OK = qw(t);
21              
22 4     4   1182 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  4         26  
23              
24             sub _generate_t {
25 10     10   1525 my $class = shift;
26 10         26 my ( $name, $value, $globals ) = @_;
27            
28 10         20 my $caller = $globals->{into};
29 10 100       82 my $reg = $class->for_class(
30             ref( $caller ) ? sprintf( 'HASH(0x%08X)', refaddr( $caller ) ) : $caller );
31            
32 10 100   44   97 sub (;$) { @_ ? $reg->lookup( @_ ) : $reg };
  44         11212  
33             } #/ sub _generate_t
34              
35             sub new {
36 58     58 1 988 my $class = shift;
37 58 50       149 ref( $class ) and _croak( "Not an object method" );
38 58         351 bless {}, $class;
39             }
40              
41             {
42             my %registries;
43            
44             sub for_class {
45 432     432 1 1090 my $class = shift;
46 432         704 my ( $for ) = @_;
47 432   66     1562 $registries{$for} ||= $class->new;
48             }
49            
50             sub for_me {
51 8     8 1 55 my $class = shift;
52 8         22 my $for = caller;
53 8   33     68 $registries{$for} ||= $class->new;
54             }
55             }
56              
57             sub add_types {
58 11     11 1 46 my $self = shift;
59 11         56 my $opts = mkopt( \@_ );
60 11         252 for my $opt ( @$opts ) {
61 12         36 my ( $library, $types ) = @$opt;
62 12         61 $library =~ s/^-/Types::/;
63            
64             {
65 12     1   38 local $SIG{__DIE__} = sub { };
  12         107  
66 12         748 eval "require $library";
67             };
68            
69 12         49 my %hash;
70            
71 12 100 66     166 if ( $library->isa( "Type::Library" ) or $library eq 'Types::TypeTiny' ) {
    100 66        
    50          
    50          
72 10   100     85 $types ||= [qw/-types/];
73 10 50       79 Types::TypeTiny::is_ArrayLike( $types )
74             or _croak(
75             "Expected arrayref following '%s'; got %s", $library,
76             $types
77             );
78            
79 10         94 $library->import( { into => \%hash }, @$types );
80 10         527 $hash{$_} = &{ $hash{$_} }() for keys %hash;
  377         3209  
81             } #/ if ( $library->isa( "Type::Library"...))
82             elsif ( $library->isa( "Exporter" )
83 20     20   173 and my $type_tag = do { no strict 'refs'; ${"$library\::EXPORT_TAGS"}{'types'} } ) {
  20         59  
  20         33785  
  1         2  
  1         6  
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         7 _croak( "%s is not a type library", $library );
121             }
122            
123 11         275 for my $key ( sort keys %hash ) {
124             exists( $self->{$key} )
125             and $self->{$key}{uniq} != $hash{$key}{uniq}
126 380 50 66     761 and _croak( "Duplicate type name: %s", $key );
127 380         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 1111     1111 1 1397 my $self = shift;
135 1111         1740 my ( $type, $name ) = @_;
136 1111         2047 $type = Types::TypeTiny::to_TypeTiny( $type );
137 1111   100     2016 $name ||= do {
138 4 100       17 $type->is_anon
139             and
140             _croak( "Expected named type constraint; got anonymous type constraint" );
141 3         11 $type->name;
142             };
143            
144             exists( $self->{$name} )
145             and $self->{$name}{uniq} != $type->{uniq}
146 1110 50 66     2386 and _croak( "Duplicate type name: %s", $name );
147            
148 1110         1890 $self->{$name} = $type;
149 1110         1792 $self;
150             } #/ sub add_type
151              
152             sub alias_type {
153 5     5 1 12 my $self = shift;
154 5         15 my ( $old, @new ) = @_;
155 5 100       9 my $lookup = eval { $self->lookup( $old ) }
  5         15  
156             or _croak( "Expected existing type constraint name; got '$old'" );
157 4         18 $self->{$_} = $lookup for @new;
158 4         11 $self;
159             }
160              
161             sub simple_lookup {
162 185     185 1 265 my $self = shift;
163            
164 185         293 my ( $tc ) = @_;
165 185         740 $tc =~ s/(^\s+|\s+$)//g;
166            
167 185 100       481 if ( exists $self->{$tc} ) {
    100          
168 157         461 return $self->{$tc};
169             }
170             elsif ( $self->has_parent ) {
171 2         5 return $self->get_parent->simple_lookup( @_ );
172             }
173            
174 26         109 return;
175             } #/ sub simple_lookup
176              
177             sub set_parent {
178 1     1 1 3 my $self = shift;
179 1 50 33     12 $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 171 my $self = shift;
188 1         2 delete $self->{'~~parent'};
189 1         3 $self;
190             }
191              
192             sub has_parent {
193 28     28 1 97 !!ref( shift->{'~~parent'} );
194             }
195              
196             sub get_parent {
197 3     3 1 16 shift->{'~~parent'};
198             }
199              
200             sub foreign_lookup {
201 4     4 1 7 my $self = shift;
202            
203 4 50       23 return $_[1] ? () : $self->simple_lookup( $_[0], 1 )
    100          
204             unless $_[0] =~ /^(.+)::(\w+)$/;
205            
206 1         4 my $library = $1;
207 1         2 my $typename = $2;
208            
209             {
210 1     0   2 local $SIG{__DIE__} = sub { };
  1         8  
211 1         53 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       6 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       18 if ( $library->can( "get_type" ) ) {
231 1         3 my $type = $library->get_type( $typename );
232 1         5 return Types::TypeTiny::to_TypeTiny( $type );
233             }
234            
235 0         0 return;
236             } #/ sub foreign_lookup
237              
238             sub lookup {
239 27     27 1 70 my $self = shift;
240            
241 27 100       85 $self->simple_lookup( @_ ) or eval_type( $_[0], $self );
242             }
243              
244             sub make_union {
245 1     1 1 2 my $self = shift;
246 1         3 my ( @types ) = @_;
247            
248 1         407 require Type::Tiny::Union;
249 1         6 return "Type::Tiny::Union"->new( type_constraints => \@types );
250             }
251              
252             sub _make_union_by_overload {
253 18     18   35 my $self = shift;
254 18         35 my ( @types ) = @_;
255            
256 18         542 require Type::Tiny::Union;
257 18         73 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         426 require Type::Tiny::Intersection;
265 1         6 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         17 my ( @types ) = @_;
271            
272 8         37 require Type::Tiny::Intersection;
273 8         38 return "Type::Tiny::Intersection"->new_by_overload( type_constraints => \@types );
274             }
275              
276             sub make_class_type {
277 10     10 1 17 my $self = shift;
278 10         22 my ( $class ) = @_;
279            
280 10         52 require Types::Standard;
281 10         34 return Types::Standard::InstanceOf()->of( $class );
282             }
283              
284             sub make_role_type {
285 3     3 1 7 my $self = shift;
286 3         8 my ( $role ) = @_;
287            
288 3         13 require Types::Standard;
289 3         11 return Types::Standard::ConsumerOf()->of( $role );
290             }
291              
292             sub AUTOLOAD {
293 17     17   45 my $self = shift;
294 17         115 my ( $method ) = ( our $AUTOLOAD =~ /(\w+)$/ );
295 17         52 my $type = $self->simple_lookup( $method );
296 17 100       103 return $type if $type;
297 1         6 _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__