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