Beginning of dzilization
[gitmo/Moose.git] / lib / Moose / Meta / Attribute.pm
1
2 package Moose::Meta::Attribute;
3
4 use strict;
5 use warnings;
6
7 use Class::MOP ();
8 use Scalar::Util 'blessed', 'weaken';
9 use List::MoreUtils 'any';
10 use Try::Tiny;
11 use overload     ();
12
13 our $AUTHORITY = 'cpan:STEVAN';
14
15 use Moose::Deprecated;
16 use Moose::Meta::Method::Accessor;
17 use Moose::Meta::Method::Delegation;
18 use Moose::Util ();
19 use Moose::Util::TypeConstraints ();
20 use Class::MOP::MiniTrait;
21
22 use base 'Class::MOP::Attribute', 'Moose::Meta::Mixin::AttributeCore';
23
24 Class::MOP::MiniTrait::apply(__PACKAGE__, 'Moose::Meta::Object::Trait');
25
26 __PACKAGE__->meta->add_attribute('traits' => (
27     reader    => 'applied_traits',
28     predicate => 'has_applied_traits',
29 ));
30
31 # we need to have a ->does method in here to
32 # more easily support traits, and the introspection
33 # of those traits. We extend the does check to look
34 # for metatrait aliases.
35 sub does {
36     my ($self, $role_name) = @_;
37     my $name = try {
38         Moose::Util::resolve_metatrait_alias(Attribute => $role_name)
39     };
40     return 0 if !defined($name); # failed to load class
41     return $self->Moose::Object::does($name);
42 }
43
44 sub throw_error {
45     my $self = shift;
46     my $class = ( ref $self && $self->associated_class ) || "Moose::Meta::Class";
47     unshift @_, "message" if @_ % 2 == 1;
48     unshift @_, attr => $self if ref $self;
49     unshift @_, $class;
50     my $handler = $class->can("throw_error"); # to avoid incrementing depth by 1
51     goto $handler;
52 }
53
54 sub _inline_throw_error {
55     my ( $self, $msg, $args ) = @_;
56     "\$meta->throw_error($msg" . ($args ? ", $args" : "") . ")"; # FIXME makes deparsing *REALLY* hard
57 }
58
59 sub new {
60     my ($class, $name, %options) = @_;
61     $class->_process_options($name, \%options) unless $options{__hack_no_process_options}; # used from clone()... YECHKKK FIXME ICKY YUCK GROSS
62     
63     delete $options{__hack_no_process_options};
64
65     my %attrs =
66         ( map { $_ => 1 }
67           grep { defined }
68           map { $_->init_arg() }
69           $class->meta()->get_all_attributes()
70         );
71
72     my @bad = sort grep { ! $attrs{$_} }  keys %options;
73
74     if (@bad)
75     {
76         Carp::cluck "Found unknown argument(s) passed to '$name' attribute constructor in '$class': @bad";
77     }
78
79     return $class->SUPER::new($name, %options);
80 }
81
82 sub interpolate_class_and_new {
83     my ($class, $name, %args) = @_;
84
85     my ( $new_class, @traits ) = $class->interpolate_class(\%args);
86
87     $new_class->new($name, %args, ( scalar(@traits) ? ( traits => \@traits ) : () ) );
88 }
89
90 sub interpolate_class {
91     my ($class, $options) = @_;
92
93     $class = ref($class) || $class;
94
95     if ( my $metaclass_name = delete $options->{metaclass} ) {
96         my $new_class = Moose::Util::resolve_metaclass_alias( Attribute => $metaclass_name );
97
98         if ( $class ne $new_class ) {
99             if ( $new_class->can("interpolate_class") ) {
100                 return $new_class->interpolate_class($options);
101             } else {
102                 $class = $new_class;
103             }
104         }
105     }
106
107     my @traits;
108
109     if (my $traits = $options->{traits}) {
110         my $i = 0;
111         while ($i < @$traits) {
112             my $trait = $traits->[$i++];
113             next if ref($trait); # options to a trait we discarded
114
115             $trait = Moose::Util::resolve_metatrait_alias(Attribute => $trait)
116                   || $trait;
117
118             next if $class->does($trait);
119
120             push @traits, $trait;
121
122             # are there options?
123             push @traits, $traits->[$i++]
124                 if $traits->[$i] && ref($traits->[$i]);
125         }
126
127         if (@traits) {
128             my $anon_class = Moose::Meta::Class->create_anon_class(
129                 superclasses => [ $class ],
130                 roles        => [ @traits ],
131                 cache        => 1,
132             );
133
134             $class = $anon_class->name;
135         }
136     }
137
138     return ( wantarray ? ( $class, @traits ) : $class );
139 }
140
141 # ...
142
143 # method-generating options shouldn't be overridden
144 sub illegal_options_for_inheritance {
145     qw(reader writer accessor clearer predicate)
146 }
147
148 # NOTE/TODO
149 # This method *must* be able to handle
150 # Class::MOP::Attribute instances as
151 # well. Yes, I know that is wrong, but
152 # apparently we didn't realize it was
153 # doing that and now we have some code
154 # which is dependent on it. The real
155 # solution of course is to push this
156 # feature back up into Class::MOP::Attribute
157 # but I not right now, I am too lazy.
158 # However if you are reading this and
159 # looking for something to do,.. please
160 # be my guest.
161 # - stevan
162 sub clone_and_inherit_options {
163     my ($self, %options) = @_;
164
165     # NOTE:
166     # we may want to extends a Class::MOP::Attribute
167     # in which case we need to be able to use the
168     # core set of legal options that have always
169     # been here. But we allows Moose::Meta::Attribute
170     # instances to changes them.
171     # - SL
172     my @illegal_options = $self->can('illegal_options_for_inheritance')
173         ? $self->illegal_options_for_inheritance
174         : ();
175
176     my @found_illegal_options = grep { exists $options{$_} && exists $self->{$_} ? $_ : undef } @illegal_options;
177     (scalar @found_illegal_options == 0)
178         || $self->throw_error("Illegal inherited options => (" . (join ', ' => @found_illegal_options) . ")", data => \%options);
179
180     if ($options{isa}) {
181         my $type_constraint;
182         if (blessed($options{isa}) && $options{isa}->isa('Moose::Meta::TypeConstraint')) {
183             $type_constraint = $options{isa};
184         }
185         else {
186             $type_constraint = Moose::Util::TypeConstraints::find_or_create_isa_type_constraint($options{isa});
187             (defined $type_constraint)
188                 || $self->throw_error("Could not find the type constraint '" . $options{isa} . "'", data => $options{isa});
189         }
190
191         $options{type_constraint} = $type_constraint;
192     }
193
194     if ($options{does}) {
195         my $type_constraint;
196         if (blessed($options{does}) && $options{does}->isa('Moose::Meta::TypeConstraint')) {
197             $type_constraint = $options{does};
198         }
199         else {
200             $type_constraint = Moose::Util::TypeConstraints::find_or_create_does_type_constraint($options{does});
201             (defined $type_constraint)
202                 || $self->throw_error("Could not find the type constraint '" . $options{does} . "'", data => $options{does});
203         }
204
205         $options{type_constraint} = $type_constraint;
206     }
207
208     # NOTE:
209     # this doesn't apply to Class::MOP::Attributes,
210     # so we can ignore it for them.
211     # - SL
212     if ($self->can('interpolate_class')) {
213         ( $options{metaclass}, my @traits ) = $self->interpolate_class(\%options);
214
215         my %seen;
216         my @all_traits = grep { $seen{$_}++ } @{ $self->applied_traits || [] }, @traits;
217         $options{traits} = \@all_traits if @all_traits;
218     }
219
220     # This method can be called on a CMOP::Attribute object, so we need to
221     # make sure we can call this method.
222     $self->_process_lazy_build_option( $self->name, \%options )
223         if $self->can('_process_lazy_build_option');
224
225     $self->clone(%options);
226 }
227
228 sub clone {
229     my ( $self, %params ) = @_;
230
231     my $class = delete $params{metaclass} || ref $self;
232
233     my ( @init, @non_init );
234
235     foreach my $attr ( grep { $_->has_value($self) } Class::MOP::class_of($self)->get_all_attributes ) {
236         push @{ $attr->has_init_arg ? \@init : \@non_init }, $attr;
237     }
238
239     my %new_params = ( ( map { $_->init_arg => $_->get_value($self) } @init ), %params );
240
241     my $name = delete $new_params{name};
242
243     my $clone = $class->new($name, %new_params, __hack_no_process_options => 1 );
244
245     foreach my $attr ( @non_init ) {
246         $attr->set_value($clone, $attr->get_value($self));
247     }
248
249     return $clone;
250 }
251
252 sub _process_options {
253     my ( $class, $name, $options ) = @_;
254
255     $class->_process_is_option( $name, $options );
256     $class->_process_isa_option( $name, $options );
257     $class->_process_does_option( $name, $options );
258     $class->_process_coerce_option( $name, $options );
259     $class->_process_trigger_option( $name, $options );
260     $class->_process_auto_deref_option( $name, $options );
261     $class->_process_lazy_build_option( $name, $options );
262     $class->_process_lazy_option( $name, $options );
263     $class->_process_required_option( $name, $options );
264 }
265
266 sub _process_is_option {
267     my ( $class, $name, $options ) = @_;
268
269     return unless $options->{is};
270
271     ### -------------------------
272     ## is => ro, writer => _foo    # turns into (reader => foo, writer => _foo) as before
273     ## is => rw, writer => _foo    # turns into (reader => foo, writer => _foo)
274     ## is => rw, accessor => _foo  # turns into (accessor => _foo)
275     ## is => ro, accessor => _foo  # error, accesor is rw
276     ### -------------------------
277
278     if ( $options->{is} eq 'ro' ) {
279         $class->throw_error(
280             "Cannot define an accessor name on a read-only attribute, accessors are read/write",
281             data => $options )
282             if exists $options->{accessor};
283         $options->{reader} ||= $name;
284     }
285     elsif ( $options->{is} eq 'rw' ) {
286         if ( $options->{writer} ) {
287             $options->{reader} ||= $name;
288         }
289         else {
290             $options->{accessor} ||= $name;
291         }
292     }
293     elsif ( $options->{is} eq 'bare' ) {
294         return;
295         # do nothing, but don't complain (later) about missing methods
296     }
297     else {
298         $class->throw_error( "I do not understand this option (is => "
299                 . $options->{is}
300                 . ") on attribute ($name)", data => $options->{is} );
301     }
302 }
303
304 sub _process_isa_option {
305     my ( $class, $name, $options ) = @_;
306
307     return unless exists $options->{isa};
308
309     if ( exists $options->{does} ) {
310         if ( try { $options->{isa}->can('does') } ) {
311             ( $options->{isa}->does( $options->{does} ) )
312                 || $class->throw_error(
313                 "Cannot have an isa option and a does option if the isa does not do the does on attribute ($name)",
314                 data => $options );
315         }
316         else {
317             $class->throw_error(
318                 "Cannot have an isa option which cannot ->does() on attribute ($name)",
319                 data => $options );
320         }
321     }
322
323     # allow for anon-subtypes here ...
324     if ( blessed( $options->{isa} )
325         && $options->{isa}->isa('Moose::Meta::TypeConstraint') ) {
326         $options->{type_constraint} = $options->{isa};
327     }
328     else {
329         $options->{type_constraint}
330             = Moose::Util::TypeConstraints::find_or_create_isa_type_constraint(
331             $options->{isa} );
332     }
333 }
334
335 sub _process_does_option {
336     my ( $class, $name, $options ) = @_;
337
338     return unless exists $options->{does} && ! exists $options->{isa};
339
340     # allow for anon-subtypes here ...
341     if ( blessed( $options->{does} )
342         && $options->{does}->isa('Moose::Meta::TypeConstraint') ) {
343         $options->{type_constraint} = $options->{does};
344     }
345     else {
346         $options->{type_constraint}
347             = Moose::Util::TypeConstraints::find_or_create_does_type_constraint(
348             $options->{does} );
349     }
350 }
351
352 sub _process_coerce_option {
353     my ( $class, $name, $options ) = @_;
354
355     return unless $options->{coerce};
356
357     ( exists $options->{type_constraint} )
358         || $class->throw_error(
359         "You cannot have coercion without specifying a type constraint on attribute ($name)",
360         data => $options );
361
362     $class->throw_error(
363         "You cannot have a weak reference to a coerced value on attribute ($name)",
364         data => $options )
365         if $options->{weak_ref};
366
367     unless ( $options->{type_constraint}->has_coercion ) {
368         my $type = $options->{type_constraint}->name;
369
370         Moose::Deprecated::deprecated(
371             feature => 'coerce without coercion',
372             message =>
373                 "You cannot coerce an attribute ($name) unless its type ($type) has a coercion"
374         );
375     }
376 }
377
378 sub _process_trigger_option {
379     my ( $class, $name, $options ) = @_;
380
381     return unless exists $options->{trigger};
382
383     ( 'CODE' eq ref $options->{trigger} )
384         || $class->throw_error("Trigger must be a CODE ref on attribute ($name)", data => $options->{trigger});
385 }
386
387 sub _process_auto_deref_option {
388     my ( $class, $name, $options ) = @_;
389
390     return unless $options->{auto_deref};
391
392     ( exists $options->{type_constraint} )
393         || $class->throw_error(
394         "You cannot auto-dereference without specifying a type constraint on attribute ($name)",
395         data => $options );
396
397     ( $options->{type_constraint}->is_a_type_of('ArrayRef')
398       || $options->{type_constraint}->is_a_type_of('HashRef') )
399         || $class->throw_error(
400         "You cannot auto-dereference anything other than a ArrayRef or HashRef on attribute ($name)",
401         data => $options );
402 }
403
404 sub _process_lazy_build_option {
405     my ( $class, $name, $options ) = @_;
406
407     return unless $options->{lazy_build};
408
409     $class->throw_error(
410         "You can not use lazy_build and default for the same attribute ($name)",
411         data => $options )
412         if exists $options->{default};
413
414     $options->{lazy} = 1;
415     $options->{builder} ||= "_build_${name}";
416
417     if ( $name =~ /^_/ ) {
418         $options->{clearer}   ||= "_clear${name}";
419         $options->{predicate} ||= "_has${name}";
420     }
421     else {
422         $options->{clearer}   ||= "clear_${name}";
423         $options->{predicate} ||= "has_${name}";
424     }
425 }
426
427 sub _process_lazy_option {
428     my ( $class, $name, $options ) = @_;
429
430     return unless $options->{lazy};
431
432     ( exists $options->{default} || defined $options->{builder} )
433         || $class->throw_error(
434         "You cannot have a lazy attribute ($name) without specifying a default value for it",
435         data => $options );
436 }
437
438 sub _process_required_option {
439     my ( $class, $name, $options ) = @_;
440
441     if (
442         $options->{required}
443         && !(
444             ( !exists $options->{init_arg} || defined $options->{init_arg} )
445             || exists $options->{default}
446             || defined $options->{builder}
447         )
448         ) {
449         $class->throw_error(
450             "You cannot have a required attribute ($name) without a default, builder, or an init_arg",
451             data => $options );
452     }
453 }
454
455 sub initialize_instance_slot {
456     my ($self, $meta_instance, $instance, $params) = @_;
457     my $init_arg = $self->init_arg();
458     # try to fetch the init arg from the %params ...
459
460     my $val;
461     my $value_is_set;
462     if ( defined($init_arg) and exists $params->{$init_arg}) {
463         $val = $params->{$init_arg};
464         $value_is_set = 1;
465     }
466     else {
467         # skip it if it's lazy
468         return if $self->is_lazy;
469         # and die if it's required and doesn't have a default value
470         $self->throw_error("Attribute (" . $self->name . ") is required", object => $instance, data => $params)
471             if $self->is_required && !$self->has_default && !$self->has_builder;
472
473         # if nothing was in the %params, we can use the
474         # attribute's default value (if it has one)
475         if ($self->has_default) {
476             $val = $self->default($instance);
477             $value_is_set = 1;
478         }
479         elsif ($self->has_builder) {
480             $val = $self->_call_builder($instance);
481             $value_is_set = 1;
482         }
483     }
484
485     return unless $value_is_set;
486
487     $val = $self->_coerce_and_verify( $val, $instance );
488
489     $self->set_initial_value($instance, $val);
490
491     if ( ref $val && $self->is_weak_ref ) {
492         $self->_weaken_value($instance);
493     }
494 }
495
496 sub _call_builder {
497     my ( $self, $instance ) = @_;
498
499     my $builder = $self->builder();
500
501     return $instance->$builder()
502         if $instance->can( $self->builder );
503
504     $self->throw_error(  blessed($instance)
505             . " does not support builder method '"
506             . $self->builder
507             . "' for attribute '"
508             . $self->name
509             . "'",
510             object => $instance,
511      );
512 }
513
514 ## Slot management
515
516 sub _make_initializer_writer_callback {
517     my $self = shift;
518     my ($meta_instance, $instance, $slot_name) = @_;
519     my $old_callback = $self->SUPER::_make_initializer_writer_callback(@_);
520     return sub {
521         $old_callback->($self->_coerce_and_verify($_[0], $instance));
522     };
523 }
524
525 sub set_value {
526     my ($self, $instance, @args) = @_;
527     my $value = $args[0];
528
529     my $attr_name = $self->name;
530
531     if ($self->is_required and not @args) {
532         $self->throw_error("Attribute ($attr_name) is required", object => $instance);
533     }
534
535     $value = $self->_coerce_and_verify( $value, $instance );
536
537     my @old;
538     if ( $self->has_trigger && $self->has_value($instance) ) {
539         @old = $self->get_value($instance, 'for trigger');
540     }
541
542     $self->SUPER::set_value($instance, $value);
543
544     if ( ref $value && $self->is_weak_ref ) {
545         $self->_weaken_value($instance);
546     }
547
548     if ($self->has_trigger) {
549         $self->trigger->($instance, $value, @old);
550     }
551 }
552
553 sub _inline_set_value {
554     my $self = shift;
555     my ($instance, $value, $tc, $tc_obj, $for_constructor) = @_;
556
557     my $old   = '@old';
558     my $copy  = '$val';
559     $tc     ||= '$type_constraint';
560     $tc_obj ||= '$type_constraint_obj';
561
562     my @code;
563     if ($self->_writer_value_needs_copy) {
564         push @code, $self->_inline_copy_value($value, $copy);
565         $value = $copy;
566     }
567
568     # constructors already handle required checks
569     push @code, $self->_inline_check_required
570         unless $for_constructor;
571
572     push @code, $self->_inline_tc_code($value, $tc, $tc_obj);
573
574     # constructors do triggers all at once at the end
575     push @code, $self->_inline_get_old_value_for_trigger($instance, $old)
576         unless $for_constructor;
577
578     push @code, (
579         $self->SUPER::_inline_set_value($instance, $value),
580         $self->_inline_weaken_value($instance, $value),
581     );
582
583     # constructors do triggers all at once at the end
584     push @code, $self->_inline_trigger($instance, $value, $old)
585         unless $for_constructor;
586
587     return @code;
588 }
589
590 sub _writer_value_needs_copy {
591     my $self = shift;
592     return $self->should_coerce;
593 }
594
595 sub _inline_copy_value {
596     my $self = shift;
597     my ($value, $copy) = @_;
598
599     return 'my ' . $copy . ' = ' . $value . ';'
600 }
601
602 sub _inline_check_required {
603     my $self = shift;
604
605     return unless $self->is_required;
606
607     my $attr_name = quotemeta($self->name);
608
609     return (
610         'if (@_ < 2) {',
611             $self->_inline_throw_error(
612                 '"Attribute (' . $attr_name . ') is required, so cannot '
613               . 'be set to undef"' # defined $_[1] is not good enough
614             ) . ';',
615         '}',
616     );
617 }
618
619 sub _inline_tc_code {
620     my $self = shift;
621     return (
622         $self->_inline_check_coercion(@_),
623         $self->_inline_check_constraint(@_),
624     );
625 }
626
627 sub _inline_check_coercion {
628     my $self = shift;
629     my ($value, $tc, $tc_obj) = @_;
630
631     return unless $self->should_coerce && $self->type_constraint->has_coercion;
632
633     return $value . ' = ' . $tc_obj . '->coerce(' . $value . ');';
634 }
635
636 sub _inline_check_constraint {
637     my $self = shift;
638     my ($value, $tc, $tc_obj) = @_;
639
640     return unless $self->has_type_constraint;
641
642     my $attr_name = quotemeta($self->name);
643
644     return (
645         'if (!' . $tc . '->(' . $value . ')) {',
646             $self->_inline_throw_error(
647                 '"Attribute (' . $attr_name . ') does not pass the type '
648               . 'constraint because: " . '
649               . $tc_obj . '->get_message(' . $value . ')',
650                 'data => ' . $value
651             ) . ';',
652         '}',
653     );
654 }
655
656 sub _inline_get_old_value_for_trigger {
657     my $self = shift;
658     my ($instance, $old) = @_;
659
660     return unless $self->has_trigger;
661
662     return (
663         'my ' . $old . ' = ' . $self->_inline_instance_has($instance),
664             '? ' . $self->_inline_instance_get($instance),
665             ': ();',
666     );
667 }
668
669 sub _inline_weaken_value {
670     my $self = shift;
671     my ($instance, $value) = @_;
672
673     return unless $self->is_weak_ref;
674
675     my $mi = $self->associated_class->get_meta_instance;
676     return (
677         $mi->inline_weaken_slot_value($instance, $self->name, $value),
678             'if ref ' . $value . ';',
679     );
680 }
681
682 sub _inline_trigger {
683     my $self = shift;
684     my ($instance, $value, $old) = @_;
685
686     return unless $self->has_trigger;
687
688     return '$attr->trigger->(' . $instance . ', ' . $value . ', ' . $old . ');';
689 }
690
691 sub _weaken_value {
692     my ( $self, $instance ) = @_;
693
694     my $meta_instance = Class::MOP::Class->initialize( blessed($instance) )
695         ->get_meta_instance;
696
697     $meta_instance->weaken_slot_value( $instance, $self->name );
698 }
699
700 sub get_value {
701     my ($self, $instance, $for_trigger) = @_;
702
703     if ($self->is_lazy) {
704         unless ($self->has_value($instance)) {
705             my $value;
706             if ($self->has_default) {
707                 $value = $self->default($instance);
708             } elsif ( $self->has_builder ) {
709                 $value = $self->_call_builder($instance);
710             }
711
712             $value = $self->_coerce_and_verify( $value, $instance );
713
714             $self->set_initial_value($instance, $value);
715         }
716     }
717
718     if ( $self->should_auto_deref && ! $for_trigger ) {
719
720         my $type_constraint = $self->type_constraint;
721
722         if ($type_constraint->is_a_type_of('ArrayRef')) {
723             my $rv = $self->SUPER::get_value($instance);
724             return unless defined $rv;
725             return wantarray ? @{ $rv } : $rv;
726         }
727         elsif ($type_constraint->is_a_type_of('HashRef')) {
728             my $rv = $self->SUPER::get_value($instance);
729             return unless defined $rv;
730             return wantarray ? %{ $rv } : $rv;
731         }
732         else {
733             $self->throw_error("Can not auto de-reference the type constraint '" . $type_constraint->name . "'", object => $instance, type_constraint => $type_constraint);
734         }
735
736     }
737     else {
738
739         return $self->SUPER::get_value($instance);
740     }
741 }
742
743 sub _inline_get_value {
744     my $self = shift;
745     my ($instance, $tc, $tc_obj) = @_;
746
747     my $slot_access = $self->_inline_instance_get($instance);
748     $tc           ||= '$type_constraint';
749     $tc_obj       ||= '$type_constraint_obj';
750
751     return (
752         $self->_inline_check_lazy($instance, $tc, $tc_obj),
753         $self->_inline_return_auto_deref($slot_access),
754     );
755 }
756
757 sub _inline_check_lazy {
758     my $self = shift;
759     my ($instance, $tc, $tc_obj) = @_;
760
761     return unless $self->is_lazy;
762
763     my $slot_exists = $self->_inline_instance_has($instance);
764
765     return (
766         'if (!' . $slot_exists . ') {',
767             $self->_inline_init_from_default($instance, '$default', $tc, $tc_obj, 'lazy'),
768         '}',
769     );
770 }
771
772 sub _inline_init_from_default {
773     my $self = shift;
774     my ($instance, $default, $tc, $tc_obj, $for_lazy) = @_;
775
776     if (!($self->has_default || $self->has_builder)) {
777         $self->throw_error(
778             'You cannot have a lazy attribute '
779           . '(' . $self->name . ') '
780           . 'without specifying a default value for it',
781             attr => $self,
782         );
783     }
784
785     return (
786         $self->_inline_generate_default($instance, $default),
787         # intentionally not using _inline_tc_code, since that can be overridden
788         # to do things like possibly only do member tc checks, which isn't
789         # appropriate for checking the result of a default
790         $self->has_type_constraint
791             ? ($self->_inline_check_coercion($default, $tc, $tc_obj, $for_lazy),
792                $self->_inline_check_constraint($default, $tc, $tc_obj, $for_lazy))
793             : (),
794         $self->_inline_init_slot($instance, $default),
795     );
796 }
797
798 sub _inline_generate_default {
799     my $self = shift;
800     my ($instance, $default) = @_;
801
802     if ($self->has_default) {
803         return 'my ' . $default . ' = $attr->default(' . $instance . ');';
804     }
805     elsif ($self->has_builder) {
806         return (
807             'my ' . $default . ';',
808             'if (my $builder = ' . $instance . '->can($attr->builder)) {',
809                 $default . ' = ' . $instance . '->$builder;',
810             '}',
811             'else {',
812                 'my $class = ref(' . $instance . ') || ' . $instance . ';',
813                 'my $builder_name = $attr->builder;',
814                 'my $attr_name = $attr->name;',
815                 $self->_inline_throw_error(
816                     '"$class does not support builder method '
817                   . '\'$builder_name\' for attribute \'$attr_name\'"'
818                 ) . ';',
819             '}',
820         );
821     }
822     else {
823         $self->throw_error(
824             "Can't generate a default for " . $self->name
825           . " since no default or builder was specified"
826         );
827     }
828 }
829
830 sub _inline_init_slot {
831     my $self = shift;
832     my ($inv, $value) = @_;
833
834     if ($self->has_initializer) {
835         return '$attr->set_initial_value(' . $inv . ', ' . $value . ');';
836     }
837     else {
838         return $self->_inline_instance_set($inv, $value) . ';';
839     }
840 }
841
842 sub _inline_return_auto_deref {
843     my $self = shift;
844
845     return 'return ' . $self->_auto_deref(@_) . ';';
846 }
847
848 sub _auto_deref {
849     my $self = shift;
850     my ($ref_value) = @_;
851
852     return $ref_value unless $self->should_auto_deref;
853
854     my $type_constraint = $self->type_constraint;
855
856     my $sigil;
857     if ($type_constraint->is_a_type_of('ArrayRef')) {
858         $sigil = '@';
859     }
860     elsif ($type_constraint->is_a_type_of('HashRef')) {
861         $sigil = '%';
862     }
863     else {
864         $self->throw_error(
865             'Can not auto de-reference the type constraint \''
866           . $type_constraint->name
867           . '\'',
868             type_constraint => $type_constraint,
869         );
870     }
871
872     return 'wantarray '
873              . '? ' . $sigil . '{ (' . $ref_value . ') || return } '
874              . ': (' . $ref_value . ')';
875 }
876
877 ## installing accessors
878
879 sub accessor_metaclass { 'Moose::Meta::Method::Accessor' }
880
881 sub install_accessors {
882     my $self = shift;
883     $self->SUPER::install_accessors(@_);
884     $self->install_delegation if $self->has_handles;
885     return;
886 }
887
888 sub _check_associated_methods {
889     my $self = shift;
890     unless (
891         @{ $self->associated_methods }
892         || ($self->_is_metadata || '') eq 'bare'
893     ) {
894         Carp::cluck(
895             'Attribute (' . $self->name . ') of class '
896             . $self->associated_class->name
897             . ' has no associated methods'
898             . ' (did you mean to provide an "is" argument?)'
899             . "\n"
900         )
901     }
902 }
903
904 sub _process_accessors {
905     my $self = shift;
906     my ($type, $accessor, $generate_as_inline_methods) = @_;
907
908     $accessor = ( keys %$accessor )[0] if ( ref($accessor) || '' ) eq 'HASH';
909     my $method = $self->associated_class->get_method($accessor);
910
911     if (   $method
912         && $method->isa('Class::MOP::Method::Accessor')
913         && $method->associated_attribute->name ne $self->name ) {
914
915         my $other_attr_name = $method->associated_attribute->name;
916         my $name            = $self->name;
917
918         Carp::cluck(
919             "You are overwriting an accessor ($accessor) for the $other_attr_name attribute"
920                 . " with a new accessor method for the $name attribute" );
921     }
922
923     if (
924            $method
925         && !$method->isa('Class::MOP::Method::Accessor')
926         && (  !$self->definition_context
927             || $method->package_name eq $self->definition_context->{package} )
928         ) {
929
930         Carp::cluck(
931             "You are overwriting a locally defined method ($accessor) with "
932                 . "an accessor" );
933     }
934
935     if (  !$self->associated_class->has_method($accessor)
936         && $self->associated_class->has_package_symbol( '&' . $accessor ) ) {
937
938         Carp::cluck(
939             "You are overwriting a locally defined function ($accessor) with "
940                 . "an accessor" );
941     }
942
943     $self->SUPER::_process_accessors(@_);
944 }
945
946 sub remove_accessors {
947     my $self = shift;
948     $self->SUPER::remove_accessors(@_);
949     $self->remove_delegation if $self->has_handles;
950     return;
951 }
952
953 sub install_delegation {
954     my $self = shift;
955
956     # NOTE:
957     # Here we canonicalize the 'handles' option
958     # this will sort out any details and always
959     # return an hash of methods which we want
960     # to delagate to, see that method for details
961     my %handles = $self->_canonicalize_handles;
962
963
964     # install the delegation ...
965     my $associated_class = $self->associated_class;
966     foreach my $handle (keys %handles) {
967         my $method_to_call = $handles{$handle};
968         my $class_name = $associated_class->name;
969         my $name = "${class_name}::${handle}";
970
971             (!$associated_class->has_method($handle))
972                 || $self->throw_error("You cannot overwrite a locally defined method ($handle) with a delegation", method_name => $handle);
973
974         # NOTE:
975         # handles is not allowed to delegate
976         # any of these methods, as they will
977         # override the ones in your class, which
978         # is almost certainly not what you want.
979
980         # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something
981         #cluck("Not delegating method '$handle' because it is a core method") and
982         next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle);
983
984         my $method = $self->_make_delegation_method($handle, $method_to_call);
985
986         $self->associated_class->add_method($method->name, $method);
987         $self->associate_method($method);
988     }
989 }
990
991 sub remove_delegation {
992     my $self = shift;
993     my %handles = $self->_canonicalize_handles;
994     my $associated_class = $self->associated_class;
995     foreach my $handle (keys %handles) {
996         next unless any { $handle eq $_ }
997                     map { $_->name }
998                     @{ $self->associated_methods };
999         $self->associated_class->remove_method($handle);
1000     }
1001 }
1002
1003 # private methods to help delegation ...
1004
1005 sub _canonicalize_handles {
1006     my $self    = shift;
1007     my $handles = $self->handles;
1008     if (my $handle_type = ref($handles)) {
1009         if ($handle_type eq 'HASH') {
1010             return %{$handles};
1011         }
1012         elsif ($handle_type eq 'ARRAY') {
1013             return map { $_ => $_ } @{$handles};
1014         }
1015         elsif ($handle_type eq 'Regexp') {
1016             ($self->has_type_constraint)
1017                 || $self->throw_error("Cannot delegate methods based on a Regexp without a type constraint (isa)", data => $handles);
1018             return map  { ($_ => $_) }
1019                    grep { /$handles/ } $self->_get_delegate_method_list;
1020         }
1021         elsif ($handle_type eq 'CODE') {
1022             return $handles->($self, $self->_find_delegate_metaclass);
1023         }
1024         elsif (blessed($handles) && $handles->isa('Moose::Meta::TypeConstraint::DuckType')) {
1025             return map { $_ => $_ } @{ $handles->methods };
1026         }
1027         elsif (blessed($handles) && $handles->isa('Moose::Meta::TypeConstraint::Role')) {
1028             $handles = $handles->role;
1029         }
1030         else {
1031             $self->throw_error("Unable to canonicalize the 'handles' option with $handles", data => $handles);
1032         }
1033     }
1034
1035     Class::MOP::load_class($handles);
1036     my $role_meta = Class::MOP::class_of($handles);
1037
1038     (blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
1039         || $self->throw_error("Unable to canonicalize the 'handles' option with $handles because its metaclass is not a Moose::Meta::Role", data => $handles);
1040
1041     return map { $_ => $_ }
1042         map { $_->name }
1043         grep { !$_->isa('Class::MOP::Method::Meta') } (
1044         $role_meta->_get_local_methods,
1045         $role_meta->get_required_method_list,
1046         );
1047 }
1048
1049 sub _get_delegate_method_list {
1050     my $self = shift;
1051     my $meta = $self->_find_delegate_metaclass;
1052     if ($meta->isa('Class::MOP::Class')) {
1053         return map  { $_->name }  # NOTE: !never! delegate &meta
1054                grep { $_->package_name ne 'Moose::Object' && !$_->isa('Class::MOP::Method::Meta') }
1055                     $meta->get_all_methods;
1056     }
1057     elsif ($meta->isa('Moose::Meta::Role')) {
1058         return $meta->get_method_list;
1059     }
1060     else {
1061         $self->throw_error("Unable to recognize the delegate metaclass '$meta'", data => $meta);
1062     }
1063 }
1064
1065 sub _find_delegate_metaclass {
1066     my $self = shift;
1067     if (my $class = $self->_isa_metadata) {
1068         unless ( Class::MOP::is_class_loaded($class) ) {
1069             $self->throw_error(
1070                 sprintf(
1071                     'The %s attribute is trying to delegate to a class which has not been loaded - %s',
1072                     $self->name, $class
1073                 )
1074             );
1075         }
1076         # we might be dealing with a non-Moose class,
1077         # and need to make our own metaclass. if there's
1078         # already a metaclass, it will be returned
1079         return Class::MOP::Class->initialize($class);
1080     }
1081     elsif (my $role = $self->_does_metadata) {
1082         unless ( Class::MOP::is_class_loaded($class) ) {
1083             $self->throw_error(
1084                 sprintf(
1085                     'The %s attribute is trying to delegate to a role which has not been loaded - %s',
1086                     $self->name, $role
1087                 )
1088             );
1089         }
1090
1091         return Class::MOP::class_of($role);
1092     }
1093     else {
1094         $self->throw_error("Cannot find delegate metaclass for attribute " . $self->name);
1095     }
1096 }
1097
1098 sub delegation_metaclass { 'Moose::Meta::Method::Delegation' }
1099
1100 sub _make_delegation_method {
1101     my ( $self, $handle_name, $method_to_call ) = @_;
1102
1103     my @curried_arguments;
1104
1105     ($method_to_call, @curried_arguments) = @$method_to_call
1106         if 'ARRAY' eq ref($method_to_call);
1107
1108     return $self->delegation_metaclass->new(
1109         name               => $handle_name,
1110         package_name       => $self->associated_class->name,
1111         attribute          => $self,
1112         delegate_to_method => $method_to_call,
1113         curried_arguments  => \@curried_arguments,
1114     );
1115 }
1116
1117 sub _coerce_and_verify {
1118     my $self     = shift;
1119     my $val      = shift;
1120     my $instance = shift;
1121
1122     return $val unless $self->has_type_constraint;
1123
1124     $val = $self->type_constraint->coerce($val)
1125         if $self->should_coerce && $self->type_constraint->has_coercion;
1126
1127     $self->verify_against_type_constraint($val, instance => $instance);
1128
1129     return $val;
1130 }
1131
1132 sub verify_against_type_constraint {
1133     my $self = shift;
1134     my $val  = shift;
1135
1136     return 1 if !$self->has_type_constraint;
1137
1138     my $type_constraint = $self->type_constraint;
1139
1140     $type_constraint->check($val)
1141         || $self->throw_error("Attribute ("
1142                  . $self->name
1143                  . ") does not pass the type constraint because: "
1144                  . $type_constraint->get_message($val), data => $val, @_);
1145 }
1146
1147 package Moose::Meta::Attribute::Custom::Moose;
1148 sub register_implementation { 'Moose::Meta::Attribute' }
1149
1150 1;
1151
1152 # ABSTRACT: The Moose attribute metaclass
1153
1154 __END__
1155
1156 =pod
1157
1158 =head1 DESCRIPTION
1159
1160 This class is a subclass of L<Class::MOP::Attribute> that provides
1161 additional Moose-specific functionality.
1162
1163 To really understand this class, you will need to start with the
1164 L<Class::MOP::Attribute> documentation. This class can be understood
1165 as a set of additional features on top of the basic feature provided
1166 by that parent class.
1167
1168 =head1 INHERITANCE
1169
1170 C<Moose::Meta::Attribute> is a subclass of L<Class::MOP::Attribute>.
1171
1172 =head1 METHODS
1173
1174 Many of the documented below override methods in
1175 L<Class::MOP::Attribute> and add Moose specific features.
1176
1177 =head2 Creation
1178
1179 =over 4
1180
1181 =item B<< Moose::Meta::Attribute->new(%options) >>
1182
1183 This method overrides the L<Class::MOP::Attribute> constructor.
1184
1185 Many of the options below are described in more detail in the
1186 L<Moose::Manual::Attributes> document.
1187
1188 It adds the following options to the constructor:
1189
1190 =over 8
1191
1192 =item * is => 'ro', 'rw', 'bare'
1193
1194 This provides a shorthand for specifying the C<reader>, C<writer>, or
1195 C<accessor> names. If the attribute is read-only ('ro') then it will
1196 have a C<reader> method with the same attribute as the name.
1197
1198 If it is read-write ('rw') then it will have an C<accessor> method
1199 with the same name. If you provide an explicit C<writer> for a
1200 read-write attribute, then you will have a C<reader> with the same
1201 name as the attribute, and a C<writer> with the name you provided.
1202
1203 Use 'bare' when you are deliberately not installing any methods
1204 (accessor, reader, etc.) associated with this attribute; otherwise,
1205 Moose will issue a deprecation warning when this attribute is added to a
1206 metaclass.
1207
1208 =item * isa => $type
1209
1210 This option accepts a type. The type can be a string, which should be
1211 a type name. If the type name is unknown, it is assumed to be a class
1212 name.
1213
1214 This option can also accept a L<Moose::Meta::TypeConstraint> object.
1215
1216 If you I<also> provide a C<does> option, then your C<isa> option must
1217 be a class name, and that class must do the role specified with
1218 C<does>.
1219
1220 =item * does => $role
1221
1222 This is short-hand for saying that the attribute's type must be an
1223 object which does the named role.
1224
1225 =item * coerce => $bool
1226
1227 This option is only valid for objects with a type constraint
1228 (C<isa>) that defined a coercion. If this is true, then coercions will be applied whenever
1229 this attribute is set.
1230
1231 You can make both this and the C<weak_ref> option true.
1232
1233 =item * trigger => $sub
1234
1235 This option accepts a subroutine reference, which will be called after
1236 the attribute is set.
1237
1238 =item * required => $bool
1239
1240 An attribute which is required must be provided to the constructor. An
1241 attribute which is required can also have a C<default> or C<builder>,
1242 which will satisfy its required-ness.
1243
1244 A required attribute must have a C<default>, C<builder> or a
1245 non-C<undef> C<init_arg>
1246
1247 =item * lazy => $bool
1248
1249 A lazy attribute must have a C<default> or C<builder>. When an
1250 attribute is lazy, the default value will not be calculated until the
1251 attribute is read.
1252
1253 =item * weak_ref => $bool
1254
1255 If this is true, the attribute's value will be stored as a weak
1256 reference.
1257
1258 =item * auto_deref => $bool
1259
1260 If this is true, then the reader will dereference the value when it is
1261 called. The attribute must have a type constraint which defines the
1262 attribute as an array or hash reference.
1263
1264 =item * lazy_build => $bool
1265
1266 Setting this to true makes the attribute lazy and provides a number of
1267 default methods.
1268
1269   has 'size' => (
1270       is         => 'ro',
1271       lazy_build => 1,
1272   );
1273
1274 is equivalent to this:
1275
1276   has 'size' => (
1277       is        => 'ro',
1278       lazy      => 1,
1279       builder   => '_build_size',
1280       clearer   => 'clear_size',
1281       predicate => 'has_size',
1282   );
1283
1284
1285 If your attribute name starts with an underscore (C<_>), then the clearer
1286 and predicate will as well:
1287
1288   has '_size' => (
1289       is         => 'ro',
1290       lazy_build => 1,
1291   );
1292
1293 becomes:
1294
1295   has '_size' => (
1296       is        => 'ro',
1297       lazy      => 1,
1298       builder   => '_build__size',
1299       clearer   => '_clear_size',
1300       predicate => '_has_size',
1301   );
1302
1303 Note the doubled underscore in the builder name. Internally, Moose
1304 simply prepends the attribute name with "_build_" to come up with the
1305 builder name.
1306
1307 =item * documentation
1308
1309 An arbitrary string that can be retrieved later by calling C<<
1310 $attr->documentation >>.
1311
1312 =back
1313
1314 =item B<< $attr->clone(%options) >>
1315
1316 This creates a new attribute based on attribute being cloned. You must
1317 supply a C<name> option to provide a new name for the attribute.
1318
1319 The C<%options> can only specify options handled by
1320 L<Class::MOP::Attribute>.
1321
1322 =back
1323
1324 =head2 Value management
1325
1326 =over 4
1327
1328 =item B<< $attr->initialize_instance_slot($meta_instance, $instance, $params) >>
1329
1330 This method is used internally to initialize the attribute's slot in
1331 the object C<$instance>.
1332
1333 This overrides the L<Class::MOP::Attribute> method to handle lazy
1334 attributes, weak references, and type constraints.
1335
1336 =item B<get_value>
1337
1338 =item B<set_value>
1339
1340   eval { $point->meta->get_attribute('x')->set_value($point, 'forty-two') };
1341   if($@) {
1342     print "Oops: $@\n";
1343   }
1344
1345 I<Attribute (x) does not pass the type constraint (Int) with 'forty-two'>
1346
1347 Before setting the value, a check is made on the type constraint of
1348 the attribute, if it has one, to see if the value passes it. If the
1349 value fails to pass, the set operation dies with a L</throw_error>.
1350
1351 Any coercion to convert values is done before checking the type constraint.
1352
1353 To check a value against a type constraint before setting it, fetch the
1354 attribute instance using L<Class::MOP::Class/find_attribute_by_name>,
1355 fetch the type_constraint from the attribute using L<Moose::Meta::Attribute/type_constraint>
1356 and call L<Moose::Meta::TypeConstraint/check>. See L<Moose::Cookbook::Basics::Recipe4>
1357 for an example.
1358
1359 =back
1360
1361 =head2 Attribute Accessor generation
1362
1363 =over 4
1364
1365 =item B<< $attr->install_accessors >>
1366
1367 This method overrides the parent to also install delegation methods.
1368
1369 If, after installing all methods, the attribute object has no associated
1370 methods, it throws an error unless C<< is => 'bare' >> was passed to the
1371 attribute constructor.  (Trying to add an attribute that has no associated
1372 methods is almost always an error.)
1373
1374 =item B<< $attr->remove_accessors >>
1375
1376 This method overrides the parent to also remove delegation methods.
1377
1378 =item B<< $attr->inline_set($instance_var, $value_var) >>
1379
1380 This method return a code snippet suitable for inlining the relevant
1381 operation. It expect strings containing variable names to be used in the
1382 inlining, like C<'$self'> or C<'$_[1]'>.
1383
1384 =item B<< $attr->install_delegation >>
1385
1386 This method adds its delegation methods to the attribute's associated
1387 class, if it has any to add.
1388
1389 =item B<< $attr->remove_delegation >>
1390
1391 This method remove its delegation methods from the attribute's
1392 associated class.
1393
1394 =item B<< $attr->accessor_metaclass >>
1395
1396 Returns the accessor metaclass name, which defaults to
1397 L<Moose::Meta::Method::Accessor>.
1398
1399 =item B<< $attr->delegation_metaclass >>
1400
1401 Returns the delegation metaclass name, which defaults to
1402 L<Moose::Meta::Method::Delegation>.
1403
1404 =back
1405
1406 =head2 Additional Moose features
1407
1408 These methods are not found in the superclass. They support features
1409 provided by Moose.
1410
1411 =over 4
1412
1413 =item B<< $attr->does($role) >>
1414
1415 This indicates whether the I<attribute itself> does the given
1416 role. The role can be given as a full class name, or as a resolvable
1417 trait name.
1418
1419 Note that this checks the attribute itself, not its type constraint,
1420 so it is checking the attribute's metaclass and any traits applied to
1421 the attribute.
1422
1423 =item B<< Moose::Meta::Class->interpolate_class_and_new($name, %options) >>
1424
1425 This is an alternate constructor that handles the C<metaclass> and
1426 C<traits> options.
1427
1428 Effectively, this method is a factory that finds or creates the
1429 appropriate class for the given C<metaclass> and/or C<traits>.
1430
1431 Once it has the appropriate class, it will call C<< $class->new($name,
1432 %options) >> on that class.
1433
1434 =item B<< $attr->clone_and_inherit_options(%options) >>
1435
1436 This method supports the C<has '+foo'> feature. It does various bits
1437 of processing on the supplied C<%options> before ultimately calling
1438 the C<clone> method.
1439
1440 One of its main tasks is to make sure that the C<%options> provided
1441 does not include the options returned by the
1442 C<illegal_options_for_inheritance> method.
1443
1444 =item B<< $attr->illegal_options_for_inheritance >>
1445
1446 This returns a blacklist of options that can not be overridden in a
1447 subclass's attribute definition.
1448
1449 This exists to allow a custom metaclass to change or add to the list
1450 of options which can not be changed.
1451
1452 =item B<< $attr->type_constraint >>
1453
1454 Returns the L<Moose::Meta::TypeConstraint> object for this attribute,
1455 if it has one.
1456
1457 =item B<< $attr->has_type_constraint >>
1458
1459 Returns true if this attribute has a type constraint.
1460
1461 =item B<< $attr->verify_against_type_constraint($value) >>
1462
1463 Given a value, this method returns true if the value is valid for the
1464 attribute's type constraint. If the value is not valid, it throws an
1465 error.
1466
1467 =item B<< $attr->handles >>
1468
1469 This returns the value of the C<handles> option passed to the
1470 constructor.
1471
1472 =item B<< $attr->has_handles >>
1473
1474 Returns true if this attribute performs delegation.
1475
1476 =item B<< $attr->is_weak_ref >>
1477
1478 Returns true if this attribute stores its value as a weak reference.
1479
1480 =item B<< $attr->is_required >>
1481
1482 Returns true if this attribute is required to have a value.
1483
1484 =item B<< $attr->is_lazy >>
1485
1486 Returns true if this attribute is lazy.
1487
1488 =item B<< $attr->is_lazy_build >>
1489
1490 Returns true if the C<lazy_build> option was true when passed to the
1491 constructor.
1492
1493 =item B<< $attr->should_coerce >>
1494
1495 Returns true if the C<coerce> option passed to the constructor was
1496 true.
1497
1498 =item B<< $attr->should_auto_deref >>
1499
1500 Returns true if the C<auto_deref> option passed to the constructor was
1501 true.
1502
1503 =item B<< $attr->trigger >>
1504
1505 This is the subroutine reference that was in the C<trigger> option
1506 passed to the constructor, if any.
1507
1508 =item B<< $attr->has_trigger >>
1509
1510 Returns true if this attribute has a trigger set.
1511
1512 =item B<< $attr->documentation >>
1513
1514 Returns the value that was in the C<documentation> option passed to
1515 the constructor, if any.
1516
1517 =item B<< $attr->has_documentation >>
1518
1519 Returns true if this attribute has any documentation.
1520
1521 =item B<< $attr->applied_traits >>
1522
1523 This returns an array reference of all the traits which were applied
1524 to this attribute. If none were applied, this returns C<undef>.
1525
1526 =item B<< $attr->has_applied_traits >>
1527
1528 Returns true if this attribute has any traits applied.
1529
1530 =back
1531
1532 =head1 BUGS
1533
1534 See L<Moose/BUGS> for details on reporting bugs.
1535
1536 =cut