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