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