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