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