File Coverage

blib/lib/Mite/Attribute.pm
Criterion Covered Total %
statement 377 533 70.7
branch 171 286 59.7
condition 89 173 51.4
subroutine 51 58 87.9
pod 0 14 0.0
total 688 1064 64.6


line stmt bran cond sub pod time code
1 78     78   5727067 use 5.010001;
  78         493  
2 78     78   436 use strict;
  78         273  
  78         1547  
3 78     78   357 use warnings;
  78         131  
  78         2998  
4              
5             use Mite::Miteception qw( -all !lazy );
6 78     78   9252  
  78         204  
  78         600  
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.010008';
9              
10             use B ();
11 78     78   575 use List::Util ();
  78         157  
  78         1081  
12 78     78   760  
  78         139  
  78         55829  
13             my $order = 0;
14             has _order =>
15             is => rw,
16             init_arg => undef,
17             builder => sub { $order++ };
18 162     162   659  
19             has definition_context =>
20             is => rw,
21             isa => HashRef,
22             default => \ '{}';
23              
24             has class =>
25             is => rw,
26             isa => MitePackage,
27             weak_ref => true;
28              
29             has compiling_class =>
30             init_arg => undef,
31             is => rw,
32             isa => MitePackage,
33             local_writer => true;
34              
35             has _class_for_default =>
36             is => rw,
37             isa => MitePackage,
38             weak_ref => true,
39             lazy => true,
40             builder => sub { $_[0]->class || $_[0]->compiling_class };
41 26 100   26   99  
42             has name =>
43             is => rw,
44             isa => NonEmptyStr,
45             required => true;
46              
47             has init_arg =>
48             is => rw,
49             isa => NonEmptyStr|Undef,
50             default => sub { shift->name },
51             lazy => true;
52              
53             has required =>
54             is => rw,
55             isa => Bool,
56             coerce => true,
57             default => false,
58             default_is_trusted => true;
59              
60             has weak_ref =>
61             is => rw,
62             isa => Bool,
63             default => false;
64              
65             has is =>
66             is => rw,
67             enum => [ ro, rw, rwp, 'lazy', bare ],
68             default => bare;
69              
70             has [ 'reader', 'writer', 'accessor', 'clearer', 'predicate', 'lvalue', 'local_writer' ] =>
71             is => rw,
72             isa => MethodNameTemplate|One|Undef,
73             builder => true,
74             lazy => true;
75              
76             has isa =>
77             is => bare,
78             isa => Str|Ref,
79             reader => '_%s'; # collision with UNIVERSAL::isa
80              
81             has does =>
82             is => bare,
83             isa => Str|Ref,
84             reader => '_%s'; # collision with Mite's does method
85              
86             has enum =>
87             is => rw,
88             isa => ArrayRef[NonEmptyStr],
89             predicate => true;
90              
91             has type =>
92             is => 'lazy',
93             isa => Object|Undef,
94             builder => true;
95              
96             has coerce =>
97             is => rw,
98             isa => Bool,
99             default => false;
100              
101             has default =>
102             is => rw,
103             isa => Undef | Str | CodeRef | ScalarRef | Dict[] | Tuple[],
104             documentation => 'We support more possibilities than Moose!',
105             predicate => true;
106              
107             has [ 'default_is_trusted', 'default_does_trigger', 'skip_argc_check' ] =>
108             is => rw,
109             isa => Bool,
110             coerce => true,
111             default => false,
112             default_is_trusted => true;
113              
114             has lazy =>
115             is => rw,
116             isa => Bool,
117             default => false;
118              
119             has coderef_default_variable =>
120             is => rw,
121             isa => NonEmptyStr,
122             lazy => true, # else $self->name might not be set
123             default => sub {
124             # This must be coordinated with Mite.pm
125             return sprintf '$%s::__%s_DEFAULT__', $_[0]->_class_for_default->name, $_[0]->name;
126             };
127              
128             has [ 'trigger', 'builder' ] =>
129             is => rw,
130             isa => MethodNameTemplate|One|CodeRef,
131             predicate => true;
132              
133             has clone =>
134             is => bare,
135             isa => MethodNameTemplate|One|CodeRef|Undef,
136             reader => 'cloner_method';
137              
138             has [ 'clone_on_read', 'clone_on_write' ] =>
139             is => 'lazy',
140             isa => Bool,
141             coerce => true,
142             builder => sub { !! shift->cloner_method };
143 232     232   939  
144             has documentation =>
145             is => rw,
146             predicate => true;
147              
148             has handles =>
149             is => rw,
150             isa => HandlesHash | Enum[ 1, 2 ],
151             predicate => true,
152             coerce => true;
153              
154             has handles_via =>
155             is => rw,
156             isa => ArrayRef->of( Str )->plus_coercions( Str, q{ [$_] } ),
157             predicate => true,
158             coerce => true;
159              
160             has alias =>
161             is => rw,
162             isa => AliasList,
163             coerce => true,
164             default => sub { [] };
165              
166             has alias_is_for =>
167             is => 'lazy',
168             init_arg => undef;
169              
170              
171 285     285   620 for my $function ( qw/ carp croak confess / ) {
  285         1846  
172 496     496   1179 no strict 'refs';
173 269     269   425 *{"_function_for_$function"} = sub {
  269         645  
174             my $self = shift;
175             return $self->compiling_class->${\"_function_for_$function"}
176 78     78   591 if defined $self->compiling_class;
  78         163  
  78         624241  
177             my $shim = eval { $self->class->shim_name };
178 127     127   315 return "$shim\::$function" if $shim;
179 127 100       453 $function eq 'carp' ? 'warn sprintf' : 'die sprintf';
  122         626  
180             };
181 5         12 }
  5         10  
182 5 50       22  
183 5 50       53 my @method_name_generator = (
184             { # public
185             reader => sub { "get_$_" },
186             writer => sub { "set_$_" },
187             accessor => sub { $_ },
188             lvalue => sub { $_ },
189             clearer => sub { "clear_$_" },
190             predicate => sub { "has_$_" },
191             builder => sub { "_build_$_" },
192             trigger => sub { "_trigger_$_" },
193             local_writer => sub { "locally_set_$_" },
194             clone => sub { "_clone_$_" },
195             },
196             { # private
197             reader => sub { "_get_$_" },
198             writer => sub { "_set_$_" },
199             accessor => sub { $_ },
200             lvalue => sub { $_ },
201             clearer => sub { "_clear_$_" },
202             predicate => sub { "_has_$_" },
203             builder => sub { "_build_$_" },
204             trigger => sub { "_trigger_$_" },
205             local_writer => sub { "_locally_set_$_" },
206             clone => sub { "_clone_$_" },
207             },
208             );
209              
210             my $self = shift;
211              
212             croak "Required attribute with no init_arg"
213             if $self->required && !defined $self->init_arg;
214              
215 161     161 0 344 if ( $self->is eq 'lazy' ) {
216             $self->lazy( true );
217 161 50 66     828 $self->builder( true ) unless $self->has_builder || $self->has_default;
218             $self->is( ro );
219             }
220 161 100       778  
221 4         52 if ( $self->has_builder and $self->has_default ) {
222 4 100 66     59 croak "Attribute cannot have both default and builder.";
223 4         27 }
224              
225             for my $method_type ( 'builder', 'trigger' ) {
226 161 50 66     1043 if ( CodeRef->check( $self->$method_type ) ) {
227 0         0 $self->$method_type( true );
228             }
229             }
230 161         479  
231 322 100       1984 for my $method_type ( 'reader', 'writer', 'accessor', 'clearer', 'predicate', 'builder', 'trigger', 'lvalue', 'local_writer' ) {
232 7         86 my $name = $self->$method_type;
233             if ( defined $name and $name eq true ) {
234             my $gen = $method_name_generator[$self->is_private]{$method_type};
235             local $_ = $self->name;
236 161         1066 my $newname = $gen->( $_ );
237 1449         4639 $self->$method_type( $newname );
238 1449 100 100     3501 }
239 39         144 }
240 39         113  
241 39         186 if ( defined $self->lvalue ) {
242 39         109 croak( 'Attributes with lazy defaults cannot have an lvalue accessor' )
243             if $self->lazy;
244             croak( 'Attributes with triggers cannot have an lvalue accessor' )
245             if $self->trigger;
246 161 100       470 croak( 'Attributes with weak_ref cannot have an lvalue accessor' )
247 5 100       16 if $self->weak_ref;
248             croak( 'Attributes with type constraints or coercions cannot have an lvalue accessor' )
249 4 100       15 if $self->type || $self->coerce;
250             croak( 'Attributes with autoclone cannot have an lvalue accessor' )
251 3 100       18 if $self->cloner_method;
252             }
253 2 100 66     9 }
254              
255 1 50       7 my ( $self, $name ) = @_;
256              
257             return undef unless defined $name;
258             return $name unless $name =~ /\%/;
259              
260             my %tokens = (
261 598     598   1080 's' => $self->name,
262             '%' => '%',
263 598 100       1097 );
264 584 100       3133  
265             $name =~ s/%(.)/$tokens{$1}/eg;
266 125         388 return $name;
267             }
268              
269             my ( $self, %args ) = ( shift, @_ );
270              
271 125         797 if ( exists $args{is} ) {
  125         514  
272 125         477 croak "Cannot use the `is` shortcut when extending an attribute";
273             }
274              
275             my %inherit = %$self;
276 8     8 0 32  
277             # type will need to be rebuilt
278 8 50       23 delete $inherit{type} if $args{isa} || $args{type};
279 0         0  
280             # these should not be cloned at all
281             delete $inherit{coderef_default_variable};
282 8         124 delete $inherit{_order};
283              
284             # Allow child class to switch from default to builder
285 8 50 33     67 # or vice versa.
286             if ( exists $args{builder} or exists $args{default} ) {
287             delete $inherit{builder};
288 8         16 delete $inherit{default};
289 8         14 }
290              
291             return ref($self)->new( %inherit, %args );
292             }
293 8 100 66     46  
294 5         10 0+!! ( shift->name =~ /^_/ );
295 5         19 }
296              
297             my $self = shift;
298 8         97 ( $self->is eq ro or $self->is eq rwp ) ? '%s' : undef;
299             }
300              
301             my $self = shift;
302 39     39 0 138 ( $self->is eq rwp ) ? '_set_%s' : undef;
303             }
304              
305             my $self = shift;
306 150     150   279 ( $self->is eq rw ) ? '%s' : undef;
307 150 100 100     415 }
308              
309              
310              
311 149     149   259  
312 149 100       403  
313             my $self = shift;
314             return undef unless @{ $self->alias };
315             my @seek_order = $self->is eq rw
316 149     149   259 ? qw( accessor reader lvalue writer )
317 149 100       403 : qw( reader accessor lvalue writer );
318             for my $sought ( @seek_order ) {
319             return $sought if $self->$sought;
320 150     150   325 }
321             return undef;
322 150     150   331 }
323              
324 148     148   300 my $self = shift;
325             my $aliases = $self->alias;
326 152     152   321 return unless @$aliases;
327             map $self->_expand_name($_), @$aliases;
328             }
329 120     120   256  
330 120 100       205 my $self = shift;
  120         284  
331 2 100       10  
332             my @methods = grep defined, (
333             $self->_all_aliases,
334 2         4 map(
335 2 50       6 $self->_expand_name($self->$_),
336             qw( reader writer accessor clearer predicate lvalue local_writer builder trigger cloner_method ),
337 0         0 ),
338             );
339              
340             if ( ref $self->handles ) {
341 260     260   426 if ( ! $self->handles_via ) {
342 260         713 push @methods, sprintf '_assert_blessed_%s', $self->name;
343 260 100       974 }
344 6         20 push @methods, map $self->_expand_name($_), sort keys %{ $self->handles };
345             }
346             elsif ( $self->handles ) {
347             my %delegations = $self->_compile_native_delegations;
348 1     1 0 3 push @methods, sort keys %delegations;
349             }
350 1         4  
351             return @methods;
352             }
353              
354             my $self = shift;
355              
356             my ( $fallback, $string );
357             if ( my $isa = $self->_isa ) {
358 1 50       4 $string = $isa;
    0          
359 1 50       5 $fallback = [ 'make_class_type' ];
360 1         4 }
361             elsif ( my $does = $self->_does ) {
362 1         3 $string = $does;
  1         4  
363             $fallback = [ 'make_role_type' ];
364             }
365 0         0 elsif ( $self->has_enum ) {
366 0         0 require Types::Standard;
367             return Types::Standard::Enum()->of( @{ $self->enum } );
368             }
369 1         5 else {
370             return undef;
371             }
372              
373 121     121   229 my $type;
374             if ( ref $string ) {
375 121         240 $type = $string;
376 121 100       1121  
    50          
    100          
377 17         86 if ( blessed $type and not $type->isa( 'Type::Tiny' ) ) {
378 17         143 if ( $type->can( 'to_TypeTiny' ) ) {
379             $type = $type->to_TypeTiny;
380             }
381 0         0 else {
382 0         0 require Types::TypeTiny;
383             $type = $type->Types::TypeTiny::to_TypeTiny;
384             }
385 2         10 }
386 2         11 elsif ( not blessed $type ) {
  2         32  
387             require Types::TypeTiny;
388             $type = Types::TypeTiny::to_TypeTiny( $type );
389 102         280 }
390             }
391             else {
392 17         46 require Type::Utils;
393 17 100       64 $type = Type::Utils::dwim_type(
394 2         4 $string,
395             fallback => $fallback,
396 2 50 66     26 for => $self->class->name,
    100          
397 0 0       0 );
398 0         0  
399             $type or croak 'Type %s cannot be found', $string;
400             }
401 0         0  
402 0         0 $type->can_be_inlined
403             or croak 'Type %s cannot be inlined', $type->display_name;
404              
405             if ( $self->coerce ) {
406 1         11 $type->has_coercion
407 1         5 or carp 'Type %s has no coercions', $type->display_name;
408             $type->coercion->can_be_inlined
409             or carp 'Coercion to type %s cannot be inlined', $type->display_name;
410             }
411 15         84  
412 15         106 return $type;
413             }
414              
415             my $self = shift;
416            
417             my $values;
418 15 50       2622 if ( $self->has_enum ) {
419             $values = $self->enum;
420             }
421 17 50       415 if ( not $values and my $type = $self->type ) {
422             require Types::Standard;
423             my $enum = $type->find_parent( sub {
424 17 100       397 $_->isa( 'Type::Tiny::Enum' );
425 6 50       21 } );
426             if ( $enum ) {
427 6 50       1469 $values = $enum->unique_values;
428             }
429             }
430              
431 17         459 my %return = map {
432             my $label = $_;
433             my $value = $_;
434             $label =~ s/([\W])/sprintf('_%x', ord($1))/ge;
435 2     2 0 3 $label => $value;
436             } @$values;
437 2         4  
438 2 50       7 return \%return;
439 2         6 }
440              
441 2 50 33     8 my $self = shift;
442 0         0  
443             # We don't have a default
444 0     0   0 return 0 unless $self->has_default;
445 0         0  
446 0 0       0 return CodeRef->check( $self->default );
447 0         0 }
448              
449             my $self = shift;
450              
451             # We don't have a default
452 2         3 return 0 unless $self->has_default;
  6         36  
453 6         7  
454 6         11 return ScalarRef->check( $self->default );
  0         0  
455 6         12 }
456              
457             my $self = shift;
458 2         17  
459             # We don't have a default
460             return 0 unless $self->has_default;
461              
462 80     80 0 157 return HashRef->check( $self->default ) || ArrayRef->check( $self->default );
463             }
464              
465 80 50       338 my $self = shift;
466              
467 80         491 return 0 unless $self->has_default;
468              
469             return !ref $self->default;
470             }
471 39     39 0 362  
472             my ( $self, $varname ) = @_;
473              
474 39 50       202 my $type = $self->type
475             or return ( $self->imported_functions->{true} ? 'true' : '!!1' );
476 39         217  
477             my $code = undef;
478              
479             if ( $self->compiling_class
480 38     38 0 355 and $self->compiling_class->imported_functions->{blessed} ) {
481             my $ctype = $type->find_constraining_type;
482              
483 38 50       182 if ( $ctype == Object ) {
484             $code = "blessed( $varname )";
485 38   100     186 }
486             elsif ( $ctype->isa( 'Type::Tiny::Class' ) ) {
487             $code = sprintf 'blessed( %s ) && %s->isa( %s )',
488             $varname, $varname, $self->_q( $ctype->class );
489 82     82 0 16382 }
490             }
491 82 50       247  
492             $code //= do {
493 82         183 local $Type::Tiny::AvoidCallbacks = 1;
494             $type->inline_check( $varname );
495             };
496              
497 43     43   318 if ( my $autolax = $self->autolax ) {
498             $code = "( !$autolax or $code )";
499             }
500 43 0       160  
    50          
501             return $code;
502 43         247 }
503              
504 43 50 33     108 my ( $self, $expression ) = @_;
505             if ( $self->coerce and my $type = $self->type ) {
506 0         0 local $Type::Tiny::AvoidCallbacks = 1;
507             return sprintf 'do { my $to_coerce = %s; %s }',
508 0 0       0 $expression, $type->coercion->inline_coercion( '$to_coerce' );
    0          
509 0         0 }
510             return $expression;
511             }
512 0         0  
513             my ( $self, $selfvar ) = @_;
514              
515             my $default = $self->_compile_default( $selfvar );
516             return $default if $self->default_is_trusted;
517 43   33     194 my $type = $self->type or return $default;
518 43         88  
519 43         114 if ( $self->coerce ) {
520             $default = $self->_compile_coercion( $default );
521             }
522 43 50       2885  
523 0         0 return sprintf 'do { my $default_value = %s; %s or %s( "Type check failed in default: %%s should be %%s", %s, %s ); $default_value }',
524             $default, $self->_compile_check('$default_value'), $self->_function_for_croak, $self->_q($self->name), $self->_q($type->display_name);
525             }
526 43         1759  
527             my ( $self, $selfvar ) = @_;
528              
529             if ( $self->has_builder ) {
530 15     15   36 return sprintf '%s->%s', $selfvar, $self->_expand_name( $self->builder );
531 15 50 33     30 }
532 15         99 elsif ( $self->has_coderef_default ) {
533 15         53 my $var = $self->coderef_default_variable;
534             return sprintf '%s->( %s )', $var, $selfvar;
535             }
536 0         0 elsif ( $self->has_inline_default ) {
537             return ${ $self->default };
538             }
539             elsif ( $self->has_reference_default ) {
540 20     20   88 return HashRef->check( $self->default ) ? '{}' : '[]';
541             }
542 20         121 elsif ( $self->has_simple_default and $self->type and $self->type == Bool ) {
543 20 100       115 my $truthy = $self->compiling_class->imported_functions->{true} ? 'true' : '!!1';
544 19 100       70 my $falsey = $self->compiling_class->imported_functions->{false} ? 'false' : '!!0';
545             return $self->default ? $truthy : $falsey;
546 7 100       54 }
547 3         10 elsif ( $self->has_simple_default ) {
548             return defined( $self->default ) ? $self->_q( $self->default ) : 'undef';
549             }
550 7         486  
551             # should never get here
552             return 'undef';
553             }
554              
555 81     81   217 my ( $self, $selfvar, @args ) = @_;
556             my $method_name = $self->_expand_name( $self->trigger );
557 81 100 66     471  
    100 66        
    100          
    100          
    50          
    50          
558 13         58 return sprintf '%s->%s( %s )',
559             $selfvar, $method_name, join( q{, }, @args );
560             }
561 29         263  
562 29         145 my ( $self, $selfvar, $valuevar ) = @_;
563              
564             if ( 'CODE' eq ref $self->cloner_method ) {
565 1         9 return sprintf '%s->_clone_%s( %s, %s )',
  1         50  
566             $selfvar, $self->name, $self->_q( $self->name ), $valuevar;
567             }
568 3 100       37  
569             if ( MethodNameTemplate->check( $self->cloner_method ) ) {
570             return sprintf '%s->%s( %s, %s )',
571 0 0       0 $selfvar, $self->_expand_name( $self->cloner_method ), $self->_q( $self->name ), $valuevar;
572 0 0       0 }
573 0 0       0  
574             return "Storable::dclone( $valuevar )";
575             }
576 35 100       99  
577             ( my $str = pop ) =~ s/([_\W])/$1 eq '_' ? '__' : sprintf('_%x', ord($1))/ge;
578             $str;
579             }
580 0         0  
581             my ( $self, $selfvar, $argvar ) = @_;
582              
583             my @code;
584 11     11   33  
585 11         23 my $init_arg = $self->_expand_name( $self->init_arg );
586              
587 11         54 if ( defined $init_arg ) {
588              
589             if ( my @alias = $self->_all_aliases ) {
590             my $new_argvar = "\$args_for_" . $self->_sanitize_identifier( $self->name );
591             push @code, sprintf( 'my %s = {};', $new_argvar );
592 12     12   28 push @code, sprintf 'for ( %s, %s ) { next unless exists %s->{$_}; %s->{%s} = %s->{$_}; last; }',
593             $self->_q_init_arg, $self->_q( @alias ), $argvar, $new_argvar, $self->_q_init_arg, $argvar;
594 12 100       49 $argvar = $new_argvar;
595 2         8 }
596              
597             my $code;
598             my $valuevar = sprintf '%s->{%s}', $argvar, $self->_q_init_arg;
599 10 100       26 my $postamble = '';
600 2         63 my $needs_check = 1;
601              
602             if ( $self->clone_on_write ) {
603             push @code, sprintf '%s = %s if exists( %s );',
604 8         162 $valuevar, $self->_compile_clone( $selfvar, $valuevar ), $valuevar;
605             }
606              
607             if ( $self->has_default || $self->has_builder and not $self->lazy ) {
608 2 50   2   14 if ( $self->default_is_trusted and my $type = $self->type ) {
  2         11  
609 2         6 my $coerce_and_check;
610             local $Type::Tiny::AvoidCallbacks = 1;
611             if ( $type->has_coercion ) {
612             $coerce_and_check = sprintf 'do { my $coerced_value = %s; ( %s ) ? $coerced_value : %s( "Type check failed in constructor: %%s should be %%s", %s, %s ) }',
613 130     130 0 323 $self->_compile_coercion( $valuevar ), $self->_compile_check( '$coerced_value' ), $self->_function_for_croak, $self->_q_init_arg, $self->_q( $type->display_name );
614             }
615 130         206 else {
616             $coerce_and_check = sprintf '( ( %s ) ? %s : %s( "Type check failed in constructor: %%s should be %%s", %s, %s ) )',
617 130         604 $self->_compile_check( $valuevar ), $valuevar, $self->_function_for_croak, $self->_q_init_arg, $self->_q( $type->display_name );
618             }
619 130 100 66     422 $code .= sprintf 'do { my $value = exists( %s ) ? %s : %s; ',
    50 66        
620             $valuevar, $coerce_and_check, $self->_compile_default( $selfvar );
621 127 100       419 $valuevar = '$value';
622 2         6 $postamble = "}; $postamble";
623 2         17 $needs_check = 0;
624 2         7 }
625             elsif ( $self->type ) {
626 2         8 $code .= sprintf 'do { my $value = exists( %s ) ? %s : %s; ',
627             $valuevar, $valuevar, $self->_compile_default( $selfvar );
628             $valuevar = '$value';
629 127         238 $postamble = "}; $postamble";
630 127         452 }
631 127         385 else {
632 127         243 $valuevar = sprintf '( exists( %s ) ? %s : %s )',
633             $valuevar, $valuevar, $self->_compile_default( $selfvar );
634 127 100       461 }
635 5         37  
636             my $trigger_condition_code =
637             ( $self->default_does_trigger and ! $self->lazy and $self->has_default || $self->has_builder )
638             ? '; '
639 127 100 100     1340 : sprintf( ' if exists %s->{%s}; ', $argvar, $self->_q_init_arg );
    100 100        
      66        
640 61 100 66     254 my $trigger_code = $self->trigger
    100          
641 1         7 ? $self->_compile_trigger(
642 1         2 $selfvar,
643 1 50       2 sprintf( '%s->{%s}', $selfvar, $self->_q_name ),
644 1         10 ) . $trigger_condition_code
645             : '';
646             $postamble = $trigger_code . $postamble;
647             }
648 0         0 elsif ( $self->required and not $self->lazy ) {
649             push @code, sprintf '%s "Missing key in constructor: %s" unless exists %s; ',
650             $self->_function_for_croak, $init_arg, $valuevar;
651 1         4 }
652             else {
653 1         2 my $trigger_code = $self->trigger
654 1         3 ? $self->_compile_trigger(
655 1         2 $selfvar,
656             sprintf( '%s->{%s}', $selfvar, $self->_q_name ),
657             ) . '; '
658 5         88 : '';
659              
660 5         33 $code .= sprintf 'if ( exists %s->{%s} ) { ',
661 5         15 $argvar, $self->_q_init_arg;
662             $postamble = "$trigger_code} $postamble";
663             }
664 55         244  
665             if ( $needs_check and my $type = $self->type ) {
666             if ( $self->coerce ) {
667             $code .= sprintf 'do { my $coerced_value = %s; ', $self->_compile_coercion( $valuevar );
668 61 100 66     268 $valuevar = '$coerced_value';
669             $postamble = "}; $postamble";
670             }
671              
672 61 100       247 $code .= sprintf '%s or %s "Type check failed in constructor: %%s should be %%s", %s, %s; ',
673             $self->_compile_check( $valuevar ),
674             $self->_function_for_croak,
675             $self->_q_init_arg,
676             $self->_q( $type->display_name );
677              
678 61         218 $code .= sprintf '%s->{%s} = %s; ',
679             $selfvar, $self->_q_name, $valuevar;
680             }
681 6         24 else {
682             $code .= sprintf '%s->{%s} = %s; ',
683             $selfvar, $self->_q_name, $valuevar;
684             }
685 60 100       219
686             $code .= $postamble;
687             push @code, $code;
688             }
689             elsif ( $self->has_default || $self->has_builder and not $self->lazy ) {
690             push @code, sprintf '%s->{%s} = %s; ',
691             $selfvar, $self->_q_name, $self->_compile_checked_default( $selfvar );
692 60         520 }
693              
694 60         195 if ( $self->weak_ref ) {
695             push @code, sprintf 'require Scalar::Util && Scalar::Util::weaken(%s->{%s}) if ref %s->{%s};',
696             $selfvar, $self->_q_name, $selfvar, $self->_q_name;
697 127 100 100     859 }
698 17 100       179  
699 5         25 for ( @code ) {
700 5         1444 $_ = "$_;" unless /;\s*$/;
701 5         12 }
702              
703             return @code;
704 17         122 }
705              
706             my $self = shift;
707              
708             if ( my $class = $self->compiling_class ) {
709             return $class->autolax;
710 17         82 }
711             return if not $self->class;
712             return if not eval { $self->class->project->config->data->{autolax} };
713             return sprintf '%s::STRICT', $self->class->project->config->data->{shim};
714 110         330 }
715              
716             my $make_usage = sub {
717             my ( $self, $code, $check, $usage_info, %arg ) = @_;
718 127         282 $arg{skip_argc_check} and return $code;
719 127         393 $self->skip_argc_check and return $code;
720              
721             my $label = ucfirst $arg{label};
722 0         0 $label .= sprintf ' "%s"', $arg{name}
723             if defined $arg{name};
724              
725             if ( my $autolax = $self->autolax ) {
726 130 100       444 $check = "!$autolax or $check"
727 1         4 }
728              
729             return sprintf q{%s or %s( '%s usage: $self->%s(%s)' ); %s},
730             $check, $self->_function_for_croak, $label, $arg{name} || '$METHOD', $usage_info, $code;
731 130         365 };
732 143 100       1087  
733             my %code_template;
734             %code_template = (
735 130         666 reader => sub {
736             my $self = shift;
737             my %arg = @_;
738             my $code = sprintf '$_[0]{%s}', $self->_q_name;
739 111     111 0 199 if ( $self->lazy ) {
740             my $checked_default = $self->_compile_checked_default( '$_[0]' );
741 111 100       296 if ( $self->default_does_trigger ) {
742 106         586 $checked_default = sprintf 'do { my $default = %s; %s; $default }',
743             $checked_default, $self->_compile_trigger( '$_[0]', '$default' );
744 5 50       19 }
745 0 0       0 $code = sprintf '( exists($_[0]{%s}) ? $_[0]{%s} : ( $_[0]{%s} = %s ) )',
  0         0  
746 0         0 $self->_q_name, $self->_q_name, $self->_q_name, $checked_default;
747             }
748             if ( $self->clone_on_read ) {
749             $code = $self->_compile_clone( '$_[0]', $code );
750             }
751             return $make_usage->( $self, $code, '@_ == 1', '', label => 'reader', %arg );
752             },
753             asserter => sub {
754             my $self = shift;
755             my %arg = @_;
756             my $reader = $code_template{reader}->( $self, skip_argc_check => true );
757             my $blessed = 'require Scalar::Util && Scalar::Util::blessed';
758             if ( $self->compiling_class and $self->compiling_class->imported_functions->{blessed} ) {
759             $blessed = 'blessed';
760             }
761             return sprintf 'my $object = do { %s }; %s($object) or %s( "%s is not a blessed object" ); $object',
762             $reader, $blessed, $self->_function_for_croak, $self->name;
763             },
764             writer => sub {
765             my $self = shift;
766             my %arg = @_;
767             my $code = '';
768             if ( $self->trigger ) {
769             $code .= sprintf 'my @oldvalue; @oldvalue = $_[0]{%s} if exists $_[0]{%s}; ',
770             $self->_q_name, $self->_q_name;
771             }
772             my $valuevar = '$_[1]';
773             if ( my $type = $self->type ) {
774             if ( $self->coerce ) {
775             $code .= sprintf 'my $value = %s; ', $self->_compile_coercion($valuevar);
776             $valuevar = '$value';
777             }
778             $code .= sprintf '%s or %s( "Type check failed in %%s: value should be %%s", %s, %s ); ',
779             $self->_compile_check($valuevar), $self->_function_for_croak, $self->_q( $arg{label} // 'writer' ), $self->_q( $type->display_name );
780             }
781             if ( $self->clone_on_write ) {
782             $code .= sprintf 'my $cloned = %s; ',
783             $self->_compile_clone( '$_[0]', $valuevar );
784             $valuevar = '$cloned';
785             }
786             $code .= sprintf '$_[0]{%s} = %s; ',
787             $self->_q_name,
788             $valuevar;
789             if ( $self->trigger ) {
790             $code .= ' ' . $self->_compile_trigger(
791             '$_[0]',
792             sprintf( '$_[0]{%s}', $self->_q_name ),
793             '@oldvalue',
794             ) . '; ';
795             }
796             if ( $self->weak_ref ) {
797             $code .= sprintf 'require Scalar::Util && Scalar::Util::weaken($_[0]{%s}) if ref $_[0]{%s}; ',
798             $self->_q_name, $self->_q_name;
799             }
800             $code .= '$_[0];';
801             return $make_usage->( $self, $code, '@_ == 2', ' $newvalue ', label => 'writer', %arg );
802             },
803             accessor => sub {
804             my $self = shift;
805             my %arg = @_;
806             my @parts = (
807             $code_template{writer}->( $self, skip_argc_check => true, label => 'accessor' ),
808             $code_template{reader}->( $self, skip_argc_check => true ),
809             );
810             for my $i ( 0 .. 1 ) {
811             $parts[$i] = $parts[$i] =~ /\;/
812             ? "do { $parts[$i] }"
813             : "( $parts[$i] )"
814             }
815             my $code = sprintf '@_ > 1 ? %s : %s', @parts;
816             },
817             clearer => sub {
818             my $self = shift;
819             my %arg = @_;
820             my $code = sprintf 'delete $_[0]{%s}; $_[0];', $self->_q_name;
821             return $make_usage->( $self, $code, '@_ == 1', '', label => 'clearer', %arg );
822             },
823             predicate => sub {
824             my $self = shift;
825             my %arg = @_;
826             my $code = sprintf 'exists $_[0]{%s}', $self->_q_name;
827             return $make_usage->( $self, $code, '@_ == 1', '', label => 'predicate', %arg );
828             },
829             lvalue => sub {
830             my $self = shift;
831             my %arg = @_;
832             my $code = sprintf '$_[0]{%s}', $self->_q_name;
833             return $make_usage->( $self, $code, '@_ == 1', '', label => 'lvalue', %arg );
834             },
835             local_writer => sub {
836             my $self = shift;
837             my %arg = @_;
838              
839             my $CROAK = $self->_function_for_croak;
840             my $GET = $self->reader ? $self->_q( $self->_expand_name( $self->reader ) )
841             : $self->accessor ? $self->_q( $self->_expand_name( $self->accessor ) )
842             : sprintf( 'sub { %s }', $code_template{reader}->( $self, skip_argc_check => true ) );
843             my $SET = $self->writer ? $self->_q( $self->_expand_name( $self->writer ) )
844             : $self->accessor ? $self->_q( $self->_expand_name( $self->accessor ) )
845             : sprintf( 'sub { %s }', $code_template{writer}->( $self, skip_argc_check => true, label => 'local writer' ) );
846             my $HAS = $self->predicate ? $self->_q( $self->_expand_name( $self->predicate ) )
847             : sprintf( 'sub { %s }', $code_template{predicate}->( $self, skip_argc_check => true ) );
848             my $CLEAR = $self->clearer ? $self->_q( $self->_expand_name( $self->clearer ) )
849             : sprintf( 'sub { %s }', $code_template{clearer}->( $self, skip_argc_check => true ) );
850             my $GUARD_NS = $self->compiling_class->imported_functions->{guard} ? ''
851             : ( eval { $self->compiling_class->shim_name } || eval { $self->class->shim_name } || die() );
852             $GUARD_NS .= '::' if $GUARD_NS;
853              
854             return sprintf <<'CODE', $CROAK, $GET, $SET, $HAS, $CLEAR, $GUARD_NS;
855              
856             defined wantarray or %s( "This method cannot be called in void context" );
857             my $get = %s;
858             my $set = %s;
859             my $has = %s;
860             my $clear = %s;
861             my $old = undef;
862             my ( $self, $new ) = @_;
863             my $restorer = $self->$has
864             ? do { $old = $self->$get; sub { $self->$set( $old ) } }
865             : sub { $self->$clear };
866             @_ == 2 ? $self->$set( $new ) : $self->$clear;
867             &%sguard( $restorer, $old );
868             CODE
869             },
870             );
871              
872             my %code_attr = (
873             lvalue => ' :lvalue',
874             );
875              
876             my $self = shift;
877             my $prefix;
878             if ( $self->handles eq 1 ) {
879             $prefix = "is_";
880             }
881             elsif ( $self->handles eq 2 ) {
882             $prefix = $self->name . "_is_";
883             }
884              
885             if ( defined $prefix ) {
886             my $needs_reader = 0;
887             my $reader;
888             if ( $self->lazy or $self->clone_on_read ) {
889             $reader = $self->_expand_name( $self->reader )
890             // $self->_expand_name( $self->accessor )
891             // $self->_expand_name( $self->lvalue )
892             // do { $needs_reader++; '_get_value_for_' . $self->name };
893             }
894             else {
895             $reader = sprintf '{%s}', $self->_q_name;
896             }
897            
898             my %values = %{ $self->possible_values };
899             my %native_delegations = map {
900             my $method_name = "$prefix$_";
901             my $value = $values{$_};
902             $method_name => sprintf( '$_[0]->%s eq %s', $reader, $self->_q( $value ) );
903             } keys %values;
904             if ( $needs_reader ) {
905             $native_delegations{$reader} = $code_template{reader}->( $self, name => $reader, skip_argc_check => true );
906             }
907             return \%native_delegations;
908             }
909              
910 2     2   4 return {};
911 2         2 }
912 2 100       13  
    50          
913 1         1 my $self = shift;
914              
915             my $reader_method = $self->_expand_name(
916 1         2 $self->reader // $self->accessor // $self->lvalue
917             );
918             my $writer_method = $self->_expand_name(
919 2 50       12 $self->writer // $self->accessor
920 2         5 );
921 2         4  
922 2 50 33     6 require Mite::Attribute::SHV::CodeGen;
923              
924             my $codegen = 'Mite::Attribute::SHV::CodeGen'->new(
925             toolkit => '__DUMMY__',
926 0   0     0 sandboxing_package => undef,
  0   0     0  
  0   0     0  
927             target => ( $self->compiling_class || $self->class )->name,
928             attribute => $self->name,
929 2         5 env => {},
930             isa => $self->type,
931             coerce => $self->coerce,
932 2         6 get_is_lvalue => ! defined( $reader_method ),
  2         11  
933             set_checks_isa => defined( $writer_method ),
934 2         9 set_strictly => $self->clone_on_read || $self->clone_on_write || $self->trigger,
  6         13  
935 6         7 generator_for_get => sub {
936 6         11 my ( $gen ) = @_;
937             if ( defined $reader_method ) {
938 2 50       8 return sprintf '%s->%s', $gen->generate_self, $reader_method;
939 0         0 }
940             else {
941 2         9 return sprintf '%s->{%s}', $gen->generate_self, $self->_q_name;
942             }
943             },
944 0         0 generator_for_set => sub {
945             my ( $gen, $newvalue ) = @_;
946             if ( defined $writer_method ) {
947             return sprintf '%s->%s( %s )', $gen->generate_self, $writer_method, $newvalue;
948 2     2   9 }
949             else {
950 2   66     14 return sprintf '( %s->{%s} = %s )', $gen->generate_self, $self->_q_name, $newvalue;
      66        
951             }
952             },
953 2   33     6 generator_for_slot => sub {
954             my ( $gen ) = @_;
955             return sprintf '%s->{%s}', $gen->generate_self, $self->_q_name;
956             },
957 2         761 generator_for_default => sub {
958             my ( $gen ) = @_;
959             return $self->_compile_default( $gen->generate_self );
960             },
961             generator_for_type_assertion => sub {
962             local $Type::Tiny::AvoidCallbacks = 1;
963             my ( $gen, $env, $type, $varname ) = @_;
964             if ( $gen->coerce and $type->{uniq} == Bool->{uniq} ) {
965             return sprintf '%s = !!%s;', $varname, $varname;
966             }
967             if ( $gen->coerce and $type->has_coercion ) {
968             return sprintf 'do { my $coerced = %s; %s or %s("Type check failed after coercion in delegated method: expected %%s, got value %%s", %s, $coerced); $coerced };',
969             $type->coercion->inline_coercion( $varname ), $type->inline_check( '$coerced' ), $self->_function_for_croak, $self->_q( $type->display_name );
970             }
971 8     8   405 return sprintf 'do { %s or %s("Type check failed in delegated method: expected %%s, got value %%s", %s, %s); %s };',
972 8 100       17 $type->inline_check( $varname ), $self->_function_for_croak, $self->_q( $type->display_name ), $varname, $varname;
973 7         14 },
974             );
975             $codegen->{mite_attribute} = $self;
976 1         4 return $codegen;
977             }
978              
979             my $self = shift;
980 0     0   0  
981 0 0       0 my $code = '';
982 0         0 my $via = $self->handles_via;
983             my %handles = %{ $self->handles } or return $code;
984             my $gen = $self->_shv_codegen;
985 0         0  
986             require Sub::HandlesVia::Handler;
987             local $Type::Tiny::AvoidCallbacks = 1;
988              
989 0     0   0 for my $method_name ( sort keys %handles ) {
990 0         0 my $handler = 'Sub::HandlesVia::Handler'->lookup(
991             $handles{$method_name},
992             $via,
993 0     0   0 );
994 0         0 $method_name = $self->_expand_name( $method_name );
995             my $result = $gen->_generate_ec_args_for_handler( $method_name => $handler );
996             if ( keys %{ $result->{environment} } ) {
997 3     3   3415 require Data::Dumper;
998 3         7 my %env = %{ $result->{environment} };
999 3 50 33     15 my $dd = Data::Dumper->new( [ \%env ], [ 'ENVIRONMENT' ] );
1000 3         28 my $env_dump = 'my ' . $dd->Purity( true )->Deparse( true )->Dump;
1001             $code .= sprintf "do {\n\t%s;%s\t*%s = %s;\n};\n",
1002 0 0 0     0 $env_dump,
1003 0         0 join( '', map { sprintf "\tmy %s = %s{\$ENVIRONMENT->{'%s'}};\n", $_, substr( $_, 0, 1 ), $_ } sort keys %env),
1004             $method_name,
1005             join( "\n", @{ $result->{source} } );
1006 0         0 }
1007             else {
1008             $code .= sprintf "*%s = %s;\n",
1009 2   33     14 $method_name, join( "\n", @{ $result->{source} } );
      33        
1010 2         400 }
1011 2         6 }
1012              
1013             return $code;
1014             }
1015 2     2   3  
1016             my ( $self, $asserter ) = @_;
1017 2         3  
1018 2         6 $self->has_handles or return '';
1019 2 50       2  
  2         6  
1020 2         7 my $code = sprintf "# Delegated methods for %s\n", $self->name;
1021             $code .= '# ' . $self->definition_context_to_pretty_string. "\n";
1022 2         796  
1023 2         39550 if ( $self->has_handles_via ) {
1024             return $code . $self->_compile_delegations_via;
1025 2         11 }
1026             elsif ( ref $self->handles ) {
1027 5         64 my %delegated = %{ $self->handles };
1028             for my $key ( sort keys %delegated ) {
1029             $code .= sprintf 'sub %s { shift->%s->%s( @_ ) }' . "\n",
1030 5         15170 $self->_expand_name( $key ), $asserter, $delegated{$key};
1031 5         26 }
1032 5 100       2016 }
  5         19  
1033 1         568 else {
1034 1         5478 my %native_delegations = %{ $self->_compile_native_delegations };
  1         4  
1035 1         7 for my $method_name ( sort keys %native_delegations ) {
1036 1         25 $code .= sprintf "sub %s { %s }\n",
1037             $method_name, $native_delegations{$method_name};
1038             }
1039 1         11 }
1040             $code .= "\n";
1041 1         49  
  1         16  
1042             return $code;
1043             }
1044              
1045 4         6 my $self = shift;
  4         45  
1046             my %args = @_;
1047              
1048             my $xs_condition = $args{xs_condition}
1049 2         58 || '!$ENV{PERL_ONLY} && eval { require Class::XSAccessor; Class::XSAccessor->VERSION("1.19") }';
1050             my $slot_name = $self->name;
1051              
1052             my %xs_option_name = (
1053 120     120   455 reader => 'getters',
1054             writer => 'setters',
1055 120 100       717 accessor => 'accessors',
1056             predicate => 'exists_predicates',
1057 8         65 lvalue => 'lvalue_accessors',
1058 8         34 );
1059              
1060 8 100       40 my %want_xs;
    100          
1061 2         5 my %want_pp;
1062             my %method_name;
1063              
1064 4         8 for my $method_type ( keys %code_template ) {
  4         19  
1065 4         19 my $method_name = $self->can($method_type) ? $self->$method_type : undef;
1066             next unless defined $method_name;
1067 6         19  
1068             $method_name{$method_type} = $self->_expand_name( $method_name );
1069             if ( $xs_option_name{$method_type} ) {
1070             $want_xs{$method_type} = 1;
1071 2         4 }
  2         4  
1072 2         10 $want_pp{$method_type} = 1;
1073             }
1074 6         16  
1075             if ( $self->has_handles and !$self->has_handles_via and ref $self->handles ) {
1076             $method_name{asserter} = sprintf '_assert_blessed_%s', $self->name;
1077 6         16 $want_pp{asserter} = 1;
1078             }
1079 6         27  
1080             # Class::XSAccessor can't do type checks, triggers, weaken, or cloning
1081             if ( $self->type or $self->weak_ref or $self->trigger or $self->clone_on_write ) {
1082             delete $want_xs{writer};
1083 120     120 0 243 delete $want_xs{accessor};
1084 120         496 }
1085              
1086             # Class::XSAccessor can't do lazy builders checks or cloning
1087 120   100     3653 if ( $self->lazy or $self->clone_on_read ) {
1088 120         522 delete $want_xs{reader};
1089             delete $want_xs{accessor};
1090 120         792 }
1091              
1092             my $code = '';
1093             if ( keys %want_xs or keys %want_pp ) {
1094             $code .= "# Accessors for $slot_name\n";
1095             $code .= '# ' . $self->definition_context_to_pretty_string. "\n";
1096             }
1097              
1098 120         488 if ( keys %want_xs ) {
1099             $code .= "if ( $xs_condition ) {\n";
1100 120         0 $code .= " Class::XSAccessor->import(\n";
1101             $code .= " chained => 1,\n";
1102 120         754 for my $method_type ( sort keys %want_xs ) {
1103 960 100       3579 $code .= sprintf " %s => { %s => %s },\n",
1104 960 100       1860 $self->_q( $xs_option_name{$method_type} ), $self->_q( $method_name{$method_type} ), $self->_q_name;
1105             }
1106 131         389 $code .= " );\n";
1107 131 100       393 $code .= "}\n";
1108 126         2284 $code .= "else {\n";
1109             for my $method_type ( sort keys %want_xs ) {
1110 131         260 $code .= sprintf ' *%s = sub%s { %s };' . "\n",
1111             $method_name{$method_type}, $code_attr{$method_type} || '', $code_template{$method_type}->( $self, name => $method_name{$method_type} );
1112             delete $want_pp{$method_type};
1113 120 100 100     861 }
      100        
1114 4         14 $code .= "}\n";
1115 4         11 }
1116              
1117             for my $method_type ( sort keys %want_pp ) {
1118             $code .= sprintf 'sub %s%s { %s }' . "\n",
1119 120 100 100     431 $method_name{$method_type}, $code_attr{$method_type} || '', $code_template{$method_type}->( $self, name => $method_name{$method_type} );
      100        
      100        
1120 29         182 }
1121 29         80  
1122             $code .= "\n";
1123              
1124             if ( $self->alias and my $alias_is_for = $self->alias_is_for ) {
1125 120 100 100     460 $code .= sprintf "# Aliases for %s\n", $self->name;
1126 21         45 $code .= '# ' . $self->definition_context_to_pretty_string. "\n";
1127 21         47 my $alias_target = $self->_expand_name( $self->$alias_is_for );
1128             for my $alias ( $self->_all_aliases ) {
1129             $code .= sprintf 'sub %s { shift->%s( @_ ) }' . "\n",
1130 120         380 $alias, $alias_target;
1131 120 100 100     743 }
1132 112         377 $code .= "\n";
1133 112         376 }
1134              
1135             $code .= $self->_compile_delegations( $method_name{asserter} );
1136 120 100       414  
1137 79         193 return $code;
1138 79         192 }
1139 79         160  
1140 79         754 my $self = shift;
1141             my %context = ( %{ $self->definition_context }, @_ );
1142 83         287  
1143             return sprintf '{ %s }',
1144 79         181 join q{, },
1145 79         187 map sprintf( '%s => %s', $_, B::perlstring( $context{$_} ) ),
1146 79         126 sort keys %context;
1147 79         224 }
1148              
1149 83   100     687 my $self = shift;
1150 83         243 my %context = ( %{ $self->definition_context }, @_ );
1151              
1152 79         157 ( $context{context} and $context{file} and $context{line} )
1153             or return '(unknown definition context)';
1154              
1155 120         363 return sprintf( '%s, file %s, line %d', $context{context}, $context{file}, $context{line} );
1156             }
1157 52   50     507  
1158             my $self = shift;
1159              
1160 120         294 my $opts_string = '';
1161             my $accessors_code = '';
1162 120 100 66     373 my $opts_indent = "\n ";
1163 2         5  
1164 2         5 $opts_string .= $opts_indent . '__hack_no_process_options => true,';
1165 2         5 if ( $self->compiling_class->isa('Mite::Class') ) {
1166 2         6 $opts_string .= $opts_indent . 'associated_class => $PACKAGE,';
1167 3         18 }
1168             else {
1169             $opts_string .= $opts_indent . 'associated_role => $PACKAGE,';
1170 2         5 }
1171              
1172             $opts_string .= $opts_indent . 'definition_context => ' . $self->definition_context_to_string . ',';
1173 120         606  
1174             {
1175 120         2591 my %translate = ( ro => 'ro', rw => 'rw', rwp => 'ro', bare => 'bare', lazy => 'ro' );
1176             $opts_string .= $opts_indent . sprintf( 'is => "%s",', $translate{$self->is} || 'bare' );
1177             }
1178              
1179 0     0 0 0 $opts_string .= $opts_indent . sprintf( 'weak_ref => %s,', $self->weak_ref ? 'true' : 'false' );
1180 0         0  
  0         0  
1181             {
1182             my $init_arg = $self->init_arg;
1183             if ( defined $init_arg ) {
1184 0         0 $opts_string .= $opts_indent . sprintf( 'init_arg => %s,', $self->_q_init_arg );
1185             $opts_string .= $opts_indent . sprintf( 'required => %s,', $self->required ? 'true' : 'false' );
1186             }
1187             else {
1188             $opts_string .= $opts_indent . 'init_arg => undef,';
1189 249     249 0 453 }
1190 249         348 }
  249         734  
1191              
1192             if ( my $type = $self->type ) {
1193 249 50 66     1889 # Easy case...
      33        
1194             if ( $type->name and $type->library ) {
1195 221         1537 $opts_string .= $opts_indent . sprintf( 'type_constraint => do { require %s; %s::%s() },', $type->library, $type->library, $type->name );
1196             }
1197             elsif ( $type->isa( 'Type::Tiny::Union' ) and List::Util::all { $_->name and $_->library } @$type ) {
1198             my $requires = join q{; }, List::Util::uniq( map sprintf( 'require %s', $_->library ), @$type );
1199 0     0     my $union = join q{ | }, List::Util::uniq( map sprintf( '%s::%s()', $_->library, $_->name ), @$type );
1200             $opts_string .= $opts_indent . sprintf( 'type_constraint => do { %s; %s },', $requires, $union );
1201 0           }
1202 0           elsif ( $type->is_parameterized
1203 0           and 1 == @{ $type->parameters }
1204             and $type->parent->name
1205 0           and $type->parent->library
1206 0 0         and $type->type_parameter->name
1207 0           and $type->type_parameter->library ) {
1208             my $requires = join q{; }, List::Util::uniq( map sprintf( 'require %s', $_->library ), $type->parent, $type->type_parameter );
1209             my $ptype = sprintf( '%s::%s()->parameterize( %s::%s() )', $type->parent->library, $type->parent->name, $type->type_parameter->library, , $type->type_parameter->name );
1210 0           $opts_string .= $opts_indent . sprintf( 'type_constraint => do { %s; %s },', $requires, $ptype );
1211             }
1212             else {
1213 0           local $Type::Tiny::AvoidCallbacks = 1;
1214             local $Type::Tiny::SafePackage = '';
1215             $opts_string .= $opts_indent . 'type_constraint => do {';
1216 0           $opts_string .= $opts_indent . ' require Type::Tiny;';
  0            
1217 0   0       $opts_string .= $opts_indent . ' my $TYPE = Type::Tiny->new(';
1218             $opts_string .= $opts_indent . sprintf ' display_name => %s,', B::perlstring( $type->display_name );
1219             $opts_string .= $opts_indent . sprintf ' constraint => sub { %s },', $type->inline_check( '$_' );
1220 0 0         $opts_string .= $opts_indent . ' );';
1221             if ( $type->has_coercion ) {
1222             $opts_string .= $opts_indent . ' require Types::Standard;';
1223 0           $opts_string .= $opts_indent . ' $TYPE->coercion->add_type_coercions(';
  0            
1224 0 0         $opts_string .= $opts_indent . ' Types::Standard::Any(),';
1225 0           $opts_string .= $opts_indent . sprintf ' sub { %s },', $type->coercion->inline_coercion( '$_' );
1226 0 0         $opts_string .= $opts_indent . ' );';
1227             $opts_string .= $opts_indent . ' $TYPE->coercion->freeze;';
1228             }
1229 0           $opts_string .= $opts_indent . ' $TYPE;';
1230             $opts_string .= $opts_indent . '},';
1231             }
1232             if ( $type->has_coercion and $self->coerce ) {
1233 0 0         $opts_string .= $opts_indent . 'coerce => true,';
1234             }
1235 0 0 0       }
    0 0        
    0 0        
      0        
      0        
      0        
      0        
1236 0            
1237             for my $accessor ( qw/ reader writer accessor predicate clearer / ) {
1238 0 0   0     my $name = $self->_expand_name( $self->$accessor );
1239 0           defined $name or next;
1240 0           my $qname = $self->_q( $name );
1241 0           my $dfnctx = $self->definition_context_to_string( description => sprintf( '%s %s::%s', $accessor, $self->compiling_class->name, $name ) );
1242              
1243             $opts_string .= $opts_indent . sprintf( '%s => %s,', $accessor, $qname );
1244 0            
1245             $accessors_code .= sprintf <<'CODE', $accessor, $self->_q_name, $qname, $self->compiling_class->name, $name, $self->_q($self->compiling_class->name), $dfnctx, $self->_q_name;
1246             {
1247             my $ACCESSOR = Moose::Meta::Method::Accessor->new(
1248             accessor_type => '%s',
1249 0           attribute => $ATTR{%s},
1250 0           name => %s,
1251 0           body => \&%s::%s,
1252             package_name => %s,
1253             definition_context => %s,
1254 0           );
1255 0           $ATTR{%s}->associate_method( $ACCESSOR );
1256 0           $PACKAGE->add_method( $ACCESSOR->name, $ACCESSOR );
1257 0           }
1258 0           CODE
1259 0           }
1260 0            
1261 0           for my $accessor ( qw/ lvalue local_writer / ) {
1262 0 0         my $name = $self->_expand_name( $self->$accessor );
1263 0           defined $name or next;
1264 0           my $qname = $self->_q( $name );
1265 0            
1266 0           $accessors_code .= sprintf <<'CODE', $qname, $self->compiling_class->name, $name, $self->_q($self->compiling_class->name), $self->_q_name;
1267 0           {
1268 0           my $ACCESSOR = Moose::Meta::Method->_new(
1269             name => %s,
1270 0           body => \&%s::%s,
1271 0           package_name => %s,
1272             );
1273 0 0 0       $ATTR{%s}->associate_method( $ACCESSOR );
1274 0           $PACKAGE->add_method( $ACCESSOR->name, $ACCESSOR );
1275             }
1276             CODE
1277             }
1278 0            
1279 0           if ( $self->has_handles_via ) {
1280 0 0         my $h = $self->handles;
1281 0           for my $delegated ( sort keys %$h ) {
1282 0           my $name = $self->_expand_name( $delegated );
1283             my $qname = $self->_q( $name );
1284 0            
1285             $accessors_code .= sprintf <<'CODE', $qname, $self->compiling_class->name, $name, $self->_q($self->compiling_class->name), $self->_q_name;
1286 0           {
1287             my $DELEGATION = Moose::Meta::Method->_new(
1288             name => %s,
1289             body => \&%s::%s,
1290             package_name => %s,
1291             );
1292             $ATTR{%s}->associate_method( $DELEGATION );
1293             $PACKAGE->add_method( $DELEGATION->name, $DELEGATION );
1294             }
1295             CODE
1296             }
1297             }
1298             elsif ( ref $self->handles ) {
1299             my $h = $self->handles;
1300             my $hstring = '';
1301             for my $delegated ( sort keys %$h ) {
1302 0           my $name = $self->_expand_name( $delegated );
1303 0           my $qname = $self->_q( $name );
1304 0 0         my $target = $h->{$delegated};
1305 0           my $qtarget = $self->_q( $target );
1306             $hstring .= ", $qname => $qtarget";
1307 0            
1308             $accessors_code .= sprintf <<'CODE', $qname, $self->_q_name, $qtarget, $self->compiling_class->name, $name, $self->_q($self->compiling_class->name), $self->_q_name;
1309             {
1310             my $DELEGATION = Moose::Meta::Method::Delegation->new(
1311             name => %s,
1312             attribute => $ATTR{%s},
1313             delegate_to_method => %s,
1314             curried_arguments => [],
1315             body => \&%s::%s,
1316             package_name => %s,
1317             );
1318             $ATTR{%s}->associate_method( $DELEGATION );
1319             $PACKAGE->add_method( $DELEGATION->name, $DELEGATION );
1320 0 0         }
    0          
    0          
1321 0           CODE
1322 0           }
1323 0            
1324 0           if ( $hstring ) {
1325             $hstring =~ s/^, //;
1326 0           $opts_string .= $opts_indent . "handles => { $hstring },";
1327             }
1328             }
1329             elsif ( $self->has_handles ) {
1330             my %native_delegations = %{ $self->_compile_native_delegations };
1331             for my $method_name ( sort keys %native_delegations ) {
1332             my $qname = $self->_q( $method_name );
1333             $accessors_code .= sprintf <<'CODE', $qname, $self->compiling_class->name, $method_name, $self->_q($self->compiling_class->name), $self->_q_name;
1334             {
1335             my $DELEGATION = Moose::Meta::Method->_new(
1336             name => %s,
1337             body => \&%s::%s,
1338             package_name => %s,
1339             );
1340 0           $ATTR{%s}->associate_method( $DELEGATION );
1341 0           $PACKAGE->add_method( $DELEGATION->name, $DELEGATION );
1342 0           }
1343 0           CODE
1344 0           }
1345 0           }
1346 0            
1347 0           {
1348             my @aliases = $self->_all_aliases;
1349 0           for my $name ( sort @aliases ) {
1350             my $qname = $self->_q( $name );
1351              
1352             $accessors_code .= sprintf <<'CODE', $qname, $self->compiling_class->name, $name, $self->_q($self->compiling_class->name), $self->_q_name;
1353             {
1354             my $ALIAS = Moose::Meta::Method->_new(
1355             name => %s,
1356             body => \&%s::%s,
1357             package_name => %s,
1358             );
1359             $ATTR{%s}->associate_method( $ALIAS );
1360             $PACKAGE->add_method( $ALIAS->name, $ALIAS );
1361             }
1362             CODE
1363             }
1364             }
1365 0 0          
1366 0           if ( my $builder = $self->_expand_name( $self->builder ) ) {
1367 0           $opts_string .= $opts_indent . sprintf( 'builder => %s,', $self->_q( $builder ) );
1368             }
1369             elsif ( $self->has_inline_default or $self->has_reference_default ) {
1370             $opts_string .= $opts_indent . sprintf( 'default => sub { %s },', $self->_compile_default );
1371 0           }
  0            
1372 0           elsif ( $self->has_coderef_default ) {
1373 0           $opts_string .= $opts_indent . sprintf( 'default => %s,', $self->coderef_default_variable );
1374 0           }
1375             elsif ( $self->has_default ) {
1376             $opts_string .= $opts_indent . sprintf( 'default => %s,', $self->_compile_default );
1377             }
1378             if ( $self->has_default or $self->has_builder ) {
1379             $opts_string .= $opts_indent . sprintf( 'lazy => %s,', $self->lazy ? 'true' : 'false' );
1380             }
1381              
1382             if ( my $trigger = $self->_expand_name( $self->trigger ) ) {
1383             $opts_string .= $opts_indent . sprintf( 'trigger => sub { shift->%s( @_ ) },', $trigger );
1384             }
1385              
1386             if ( $self->has_documentation ) {
1387             $opts_string .= $opts_indent . sprintf( 'documentation => %s,', $self->_q( $self->documentation ) );
1388             }
1389 0            
  0            
1390 0           if ( not $self->compiling_class->isa( 'Mite::Class' ) ) {
1391 0           $accessors_code = sprintf "delete \$ATTR{%s}{original_options}{\$_} for qw( associated_role );\n",
1392             $self->_q_name;
1393 0           }
1394              
1395             $opts_string .= "\n";
1396             return sprintf <<'CODE', $self->_q_name, $self->compiling_class->_mop_attribute_metaclass, $self->_q_name, $opts_string, $accessors_code, $self->_q_name;
1397             $ATTR{%s} = %s->new( %s,%s);
1398             %sdo {
1399             no warnings 'redefine';
1400             local *Moose::Meta::Attribute::install_accessors = sub {};
1401             $PACKAGE->add_attribute( $ATTR{%s} );
1402             };
1403             CODE
1404             }
1405              
1406             1;