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