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