File Coverage

blib/lib/Mite/Attribute.pm
Criterion Covered Total %
statement 393 549 71.5
branch 180 296 60.8
condition 97 180 53.8
subroutine 55 62 88.7
pod 0 14 0.0
total 725 1101 65.8


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