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