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