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