Fixed a couple of typos.
[gitmo/Moose.git] / lib / Moose / Meta / Attribute.pm
CommitLineData
c0e30cf5 1
2package Moose::Meta::Attribute;
3
4use strict;
5use warnings;
6
9238220f 7use Class::MOP ();
21f1e231 8use Scalar::Util 'blessed', 'weaken';
fe11f190 9use List::MoreUtils 'any';
1454efcc 10use Try::Tiny;
a909a4df 11use overload ();
a15dff8d 12
bb8ef151 13our $VERSION = '1.9900';
d44714be 14our $AUTHORITY = 'cpan:STEVAN';
78cd1d3b 15
f1309155 16use Moose::Deprecated;
8ee73eeb 17use Moose::Meta::Method::Accessor;
a05f85c1 18use Moose::Meta::Method::Delegation;
d5c30e52 19use Moose::Util ();
a3c7e2fe 20use Moose::Util::TypeConstraints ();
d2782813 21use Class::MOP::MiniTrait;
bc1e29b5 22
f785aad8 23use base 'Class::MOP::Attribute', 'Moose::Meta::Mixin::AttributeCore';
c0e30cf5 24
d2782813 25Class::MOP::MiniTrait::apply(__PACKAGE__, 'Moose::Meta::Object::Trait');
26
82a5b1a7 27__PACKAGE__->meta->add_attribute('traits' => (
28 reader => 'applied_traits',
29 predicate => 'has_applied_traits',
30));
82168dbb 31
d03bd989 32# we need to have a ->does method in here to
33# more easily support traits, and the introspection
0db4f1d7 34# of those traits. We extend the does check to look
35# for metatrait aliases.
36sub does {
37 my ($self, $role_name) = @_;
1454efcc 38 my $name = try {
0db4f1d7 39 Moose::Util::resolve_metatrait_alias(Attribute => $role_name)
40 };
41 return 0 if !defined($name); # failed to load class
e8895723 42 return $self->Moose::Object::does($name);
0db4f1d7 43}
587e457d 44
be05faea 45sub throw_error {
46 my $self = shift;
47 my $class = ( ref $self && $self->associated_class ) || "Moose::Meta::Class";
48 unshift @_, "message" if @_ % 2 == 1;
49 unshift @_, attr => $self if ref $self;
50 unshift @_, $class;
18748ad6 51 my $handler = $class->can("throw_error"); # to avoid incrementing depth by 1
52 goto $handler;
be05faea 53}
54
6e50f7e9 55sub _inline_throw_error {
56 my ( $self, $msg, $args ) = @_;
57 "\$meta->throw_error($msg" . ($args ? ", $args" : "") . ")"; # FIXME makes deparsing *REALLY* hard
58}
59
78cd1d3b 60sub new {
f3c4e20e 61 my ($class, $name, %options) = @_;
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;
ec86bdff 556 my ($instance, $value, $tc, $tc_obj, $for_constructor) = @_;
6e50f7e9 557
ec86bdff 558 my $old = '@old';
559 my $copy = '$val';
560 $tc ||= '$type_constraint';
561 $tc_obj ||= '$type_constraint_obj';
6e50f7e9 562
563 my @code;
564 if ($self->_writer_value_needs_copy) {
565 push @code, $self->_inline_copy_value($value, $copy);
566 $value = $copy;
567 }
568
ec86bdff 569 # constructors already handle required checks
570 push @code, $self->_inline_check_required
571 unless $for_constructor;
572
573 push @code, $self->_inline_tc_code($value, $tc, $tc_obj);
574
575 # constructors do triggers all at once at the end
576 push @code, $self->_inline_get_old_value_for_trigger($instance, $old)
577 unless $for_constructor;
578
6e50f7e9 579 push @code, (
6e50f7e9 580 $self->SUPER::_inline_set_value($instance, $value),
581 $self->_inline_weaken_value($instance, $value),
6e50f7e9 582 );
583
ec86bdff 584 # constructors do triggers all at once at the end
585 push @code, $self->_inline_trigger($instance, $value, $old)
586 unless $for_constructor;
587
6e50f7e9 588 return @code;
589}
590
591sub _writer_value_needs_copy {
592 my $self = shift;
593 return $self->should_coerce;
594}
595
596sub _inline_copy_value {
597 my $self = shift;
598 my ($value, $copy) = @_;
599
600 return 'my ' . $copy . ' = ' . $value . ';'
601}
602
603sub _inline_check_required {
604 my $self = shift;
605
606 return unless $self->is_required;
607
608 my $attr_name = quotemeta($self->name);
609
610 return (
611 'if (@_ < 2) {',
612 $self->_inline_throw_error(
613 '"Attribute (' . $attr_name . ') is required, so cannot '
614 . 'be set to undef"' # defined $_[1] is not good enough
615 ) . ';',
616 '}',
617 );
618}
619
620sub _inline_tc_code {
621 my $self = shift;
622 return (
623 $self->_inline_check_coercion(@_),
624 $self->_inline_check_constraint(@_),
625 );
626}
627
628sub _inline_check_coercion {
629 my $self = shift;
ec86bdff 630 my ($value, $tc, $tc_obj) = @_;
6e50f7e9 631
632 return unless $self->should_coerce && $self->type_constraint->has_coercion;
633
ec86bdff 634 return $value . ' = ' . $tc_obj . '->coerce(' . $value . ');';
6e50f7e9 635}
636
637sub _inline_check_constraint {
638 my $self = shift;
ec86bdff 639 my ($value, $tc, $tc_obj) = @_;
6e50f7e9 640
641 return unless $self->has_type_constraint;
642
643 my $attr_name = quotemeta($self->name);
644
645 return (
ec86bdff 646 'if (!' . $tc . '->(' . $value . ')) {',
6e50f7e9 647 $self->_inline_throw_error(
648 '"Attribute (' . $attr_name . ') does not pass the type '
649 . 'constraint because: " . '
ec86bdff 650 . $tc_obj . '->get_message(' . $value . ')',
6e50f7e9 651 'data => ' . $value
652 ) . ';',
653 '}',
654 );
655}
656
657sub _inline_get_old_value_for_trigger {
658 my $self = shift;
659 my ($instance, $old) = @_;
660
661 return unless $self->has_trigger;
662
663 return (
664 'my ' . $old . ' = ' . $self->_inline_instance_has($instance),
665 '? ' . $self->_inline_instance_get($instance),
666 ': ();',
667 );
668}
669
670sub _inline_weaken_value {
671 my $self = shift;
672 my ($instance, $value) = @_;
673
674 return unless $self->is_weak_ref;
675
676 my $mi = $self->associated_class->get_meta_instance;
677 return (
678 $mi->inline_weaken_slot_value($instance, $self->name, $value),
679 'if ref ' . $value . ';',
680 );
681}
682
683sub _inline_trigger {
684 my $self = shift;
685 my ($instance, $value, $old) = @_;
686
687 return unless $self->has_trigger;
688
689 return '$attr->trigger->(' . $instance . ', ' . $value . ', ' . $old . ');';
690}
691
32881f68 692sub _weaken_value {
312e0f0c 693 my ( $self, $instance ) = @_;
694
32881f68 695 my $meta_instance = Class::MOP::Class->initialize( blessed($instance) )
696 ->get_meta_instance;
312e0f0c 697
698 $meta_instance->weaken_slot_value( $instance, $self->name );
699}
700
946289d1 701sub get_value {
3dda07f5 702 my ($self, $instance, $for_trigger) = @_;
26fbace8 703
946289d1 704 if ($self->is_lazy) {
8de73ff1 705 unless ($self->has_value($instance)) {
e606ae5f 706 my $value;
8de73ff1 707 if ($self->has_default) {
e606ae5f 708 $value = $self->default($instance);
3f11800d 709 } elsif ( $self->has_builder ) {
e606ae5f 710 $value = $self->_call_builder($instance);
711 }
9c9563c7 712
713 $value = $self->_coerce_and_verify( $value, $instance );
714
e606ae5f 715 $self->set_initial_value($instance, $value);
8de73ff1 716 }
946289d1 717 }
26fbace8 718
3dda07f5 719 if ( $self->should_auto_deref && ! $for_trigger ) {
26fbace8 720
946289d1 721 my $type_constraint = $self->type_constraint;
722
723 if ($type_constraint->is_a_type_of('ArrayRef')) {
724 my $rv = $self->SUPER::get_value($instance);
725 return unless defined $rv;
726 return wantarray ? @{ $rv } : $rv;
26fbace8 727 }
946289d1 728 elsif ($type_constraint->is_a_type_of('HashRef')) {
729 my $rv = $self->SUPER::get_value($instance);
730 return unless defined $rv;
731 return wantarray ? %{ $rv } : $rv;
26fbace8 732 }
946289d1 733 else {
46cb090f 734 $self->throw_error("Can not auto de-reference the type constraint '" . $type_constraint->name . "'", object => $instance, type_constraint => $type_constraint);
946289d1 735 }
26fbace8 736
946289d1 737 }
738 else {
26fbace8 739
946289d1 740 return $self->SUPER::get_value($instance);
26fbace8 741 }
946289d1 742}
a15dff8d 743
6e50f7e9 744sub _inline_get_value {
745 my $self = shift;
ec86bdff 746 my ($instance, $tc, $tc_obj) = @_;
6e50f7e9 747
748 my $slot_access = $self->_inline_instance_get($instance);
ec86bdff 749 $tc ||= '$type_constraint';
750 $tc_obj ||= '$type_constraint_obj';
6e50f7e9 751
752 return (
ec86bdff 753 $self->_inline_check_lazy($instance, $tc, $tc_obj),
6e50f7e9 754 $self->_inline_return_auto_deref($slot_access),
755 );
756}
757
758sub _inline_check_lazy {
759 my $self = shift;
ec86bdff 760 my ($instance, $tc, $tc_obj) = @_;
6e50f7e9 761
762 return unless $self->is_lazy;
763
764 my $slot_exists = $self->_inline_instance_has($instance);
765
766 return (
767 'if (!' . $slot_exists . ') {',
ec86bdff 768 $self->_inline_init_from_default($instance, '$default', $tc, $tc_obj, 'lazy'),
6e50f7e9 769 '}',
770 );
771}
772
773sub _inline_init_from_default {
774 my $self = shift;
ec86bdff 775 my ($instance, $default, $tc, $tc_obj, $for_lazy) = @_;
6e50f7e9 776
777 if (!($self->has_default || $self->has_builder)) {
778 $self->throw_error(
779 'You cannot have a lazy attribute '
780 . '(' . $self->name . ') '
781 . 'without specifying a default value for it',
782 attr => $self,
783 );
784 }
785
786 return (
787 $self->_inline_generate_default($instance, $default),
788 # intentionally not using _inline_tc_code, since that can be overridden
789 # to do things like possibly only do member tc checks, which isn't
790 # appropriate for checking the result of a default
791 $self->has_type_constraint
ec86bdff 792 ? ($self->_inline_check_coercion($default, $tc, $tc_obj, $for_lazy),
793 $self->_inline_check_constraint($default, $tc, $tc_obj, $for_lazy))
6e50f7e9 794 : (),
795 $self->_inline_init_slot($instance, $default),
796 );
797}
798
799sub _inline_generate_default {
800 my $self = shift;
801 my ($instance, $default) = @_;
802
803 if ($self->has_default) {
804 return 'my ' . $default . ' = $attr->default(' . $instance . ');';
805 }
806 elsif ($self->has_builder) {
807 return (
808 'my ' . $default . ';',
809 'if (my $builder = ' . $instance . '->can($attr->builder)) {',
810 $default . ' = ' . $instance . '->$builder;',
811 '}',
812 'else {',
813 'my $class = ref(' . $instance . ') || ' . $instance . ';',
814 'my $builder_name = $attr->builder;',
815 'my $attr_name = $attr->name;',
816 $self->_inline_throw_error(
817 '"$class does not support builder method '
818 . '\'$builder_name\' for attribute \'$attr_name\'"'
819 ) . ';',
820 '}',
821 );
822 }
823 else {
824 $self->throw_error(
825 "Can't generate a default for " . $self->name
826 . " since no default or builder was specified"
827 );
828 }
829}
830
831sub _inline_init_slot {
832 my $self = shift;
833 my ($inv, $value) = @_;
834
835 if ($self->has_initializer) {
836 return '$attr->set_initial_value(' . $inv . ', ' . $value . ');';
837 }
838 else {
839 return $self->_inline_instance_set($inv, $value) . ';';
840 }
841}
842
843sub _inline_return_auto_deref {
844 my $self = shift;
845
846 return 'return ' . $self->_auto_deref(@_) . ';';
847}
848
849sub _auto_deref {
850 my $self = shift;
851 my ($ref_value) = @_;
852
853 return $ref_value unless $self->should_auto_deref;
854
855 my $type_constraint = $self->type_constraint;
856
857 my $sigil;
858 if ($type_constraint->is_a_type_of('ArrayRef')) {
859 $sigil = '@';
860 }
861 elsif ($type_constraint->is_a_type_of('HashRef')) {
862 $sigil = '%';
863 }
864 else {
865 $self->throw_error(
866 'Can not auto de-reference the type constraint \''
867 . $type_constraint->name
868 . '\'',
869 type_constraint => $type_constraint,
870 );
871 }
872
873 return 'wantarray '
874 . '? ' . $sigil . '{ (' . $ref_value . ') || return } '
875 . ': (' . $ref_value . ')';
876}
877
26fbace8 878## installing accessors
c0e30cf5 879
246bbeef 880sub accessor_metaclass { 'Moose::Meta::Method::Accessor' }
881
882sub install_accessors {
ae907ae0 883 my $self = shift;
246bbeef 884 $self->SUPER::install_accessors(@_);
885 $self->install_delegation if $self->has_handles;
28af3424 886 return;
887}
888
9340e346 889sub _check_associated_methods {
28af3424 890 my $self = shift;
86cf196b 891 unless (
0bbd378f 892 @{ $self->associated_methods }
86cf196b 893 || ($self->_is_metadata || '') eq 'bare'
894 ) {
895 Carp::cluck(
8f4450f3 896 'Attribute (' . $self->name . ') of class '
897 . $self->associated_class->name
898 . ' has no associated methods'
86cf196b 899 . ' (did you mean to provide an "is" argument?)'
900 . "\n"
901 )
902 }
e606ae5f 903}
26fbace8 904
3b6e2290 905sub _process_accessors {
906 my $self = shift;
907 my ($type, $accessor, $generate_as_inline_methods) = @_;
837f61c9 908
909 $accessor = ( keys %$accessor )[0] if ( ref($accessor) || '' ) eq 'HASH';
99541dfd 910 my $method = $self->associated_class->get_method($accessor);
837f61c9 911
d7dfe605 912 if ( $method
913 && $method->isa('Class::MOP::Method::Accessor')
914 && $method->associated_attribute->name ne $self->name ) {
915
916 my $other_attr_name = $method->associated_attribute->name;
917 my $name = $self->name;
918
919 Carp::cluck(
920 "You are overwriting an accessor ($accessor) for the $other_attr_name attribute"
921 . " with a new accessor method for the $name attribute" );
922 }
923
837f61c9 924 if (
925 $method
926 && !$method->isa('Class::MOP::Method::Accessor')
927 && ( !$self->definition_context
928 || $method->package_name eq $self->definition_context->{package} )
929 ) {
930
3b6e2290 931 Carp::cluck(
1d18c898 932 "You are overwriting a locally defined method ($accessor) with "
837f61c9 933 . "an accessor" );
3b6e2290 934 }
d7dfe605 935
837f61c9 936 if ( !$self->associated_class->has_method($accessor)
937 && $self->associated_class->has_package_symbol( '&' . $accessor ) ) {
938
3968746e 939 Carp::cluck(
940 "You are overwriting a locally defined function ($accessor) with "
837f61c9 941 . "an accessor" );
3968746e 942 }
837f61c9 943
3b6e2290 944 $self->SUPER::_process_accessors(@_);
e606ae5f 945}
26fbace8 946
e1d6f0a3 947sub remove_accessors {
948 my $self = shift;
949 $self->SUPER::remove_accessors(@_);
950 $self->remove_delegation if $self->has_handles;
951 return;
952}
953
e606ae5f 954sub install_delegation {
955 my $self = shift;
26fbace8 956
e606ae5f 957 # NOTE:
958 # Here we canonicalize the 'handles' option
959 # this will sort out any details and always
960 # return an hash of methods which we want
961 # to delagate to, see that method for details
962 my %handles = $self->_canonicalize_handles;
963
e606ae5f 964
965 # install the delegation ...
966 my $associated_class = $self->associated_class;
967 foreach my $handle (keys %handles) {
968 my $method_to_call = $handles{$handle};
969 my $class_name = $associated_class->name;
970 my $name = "${class_name}::${handle}";
26fbace8 971
452bac1b 972 (!$associated_class->has_method($handle))
cee532a1 973 || $self->throw_error("You cannot overwrite a locally defined method ($handle) with a delegation", method_name => $handle);
26fbace8 974
e606ae5f 975 # NOTE:
976 # handles is not allowed to delegate
977 # any of these methods, as they will
978 # override the ones in your class, which
979 # is almost certainly not what you want.
4fe78472 980
e606ae5f 981 # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something
982 #cluck("Not delegating method '$handle' because it is a core method") and
983 next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle);
26fbace8 984
46f7e6a5 985 my $method = $self->_make_delegation_method($handle, $method_to_call);
a05f85c1 986
987 $self->associated_class->add_method($method->name, $method);
0bbd378f 988 $self->associate_method($method);
d03bd989 989 }
452bac1b 990}
991
e1d6f0a3 992sub remove_delegation {
993 my $self = shift;
994 my %handles = $self->_canonicalize_handles;
995 my $associated_class = $self->associated_class;
996 foreach my $handle (keys %handles) {
684323b3 997 next unless any { $handle eq $_ }
998 map { $_->name }
999 @{ $self->associated_methods };
e1d6f0a3 1000 $self->associated_class->remove_method($handle);
1001 }
1002}
1003
98aae381 1004# private methods to help delegation ...
1005
452bac1b 1006sub _canonicalize_handles {
1007 my $self = shift;
1008 my $handles = $self->handles;
c84f324f 1009 if (my $handle_type = ref($handles)) {
1010 if ($handle_type eq 'HASH') {
1011 return %{$handles};
1012 }
1013 elsif ($handle_type eq 'ARRAY') {
1014 return map { $_ => $_ } @{$handles};
1015 }
1016 elsif ($handle_type eq 'Regexp') {
1017 ($self->has_type_constraint)
0286711b 1018 || $self->throw_error("Cannot delegate methods based on a Regexp without a type constraint (isa)", data => $handles);
26fbace8 1019 return map { ($_ => $_) }
c84f324f 1020 grep { /$handles/ } $self->_get_delegate_method_list;
1021 }
1022 elsif ($handle_type eq 'CODE') {
1023 return $handles->($self, $self->_find_delegate_metaclass);
1024 }
6cbf4a23 1025 elsif (blessed($handles) && $handles->isa('Moose::Meta::TypeConstraint::DuckType')) {
1026 return map { $_ => $_ } @{ $handles->methods };
1027 }
c7761602 1028 elsif (blessed($handles) && $handles->isa('Moose::Meta::TypeConstraint::Role')) {
1029 $handles = $handles->role;
1030 }
c84f324f 1031 else {
be05faea 1032 $self->throw_error("Unable to canonicalize the 'handles' option with $handles", data => $handles);
c84f324f 1033 }
452bac1b 1034 }
c84f324f 1035
c7761602 1036 Class::MOP::load_class($handles);
1037 my $role_meta = Class::MOP::class_of($handles);
d03bd989 1038
c7761602 1039 (blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
1040 || $self->throw_error("Unable to canonicalize the 'handles' option with $handles because its metaclass is not a Moose::Meta::Role", data => $handles);
1041
1042 return map { $_ => $_ }
ba7d613d 1043 map { $_->name }
1044 grep { !$_->isa('Class::MOP::Method::Meta') } (
1045 $role_meta->_get_local_methods,
1046 $role_meta->get_required_method_list,
c7761602 1047 );
452bac1b 1048}
1049
452bac1b 1050sub _get_delegate_method_list {
1051 my $self = shift;
1052 my $meta = $self->_find_delegate_metaclass;
1053 if ($meta->isa('Class::MOP::Class')) {
e606ae5f 1054 return map { $_->name } # NOTE: !never! delegate &meta
ba7d613d 1055 grep { $_->package_name ne 'Moose::Object' && !$_->isa('Class::MOP::Method::Meta') }
e606ae5f 1056 $meta->get_all_methods;
452bac1b 1057 }
1058 elsif ($meta->isa('Moose::Meta::Role')) {
26fbace8 1059 return $meta->get_method_list;
452bac1b 1060 }
1061 else {
be05faea 1062 $self->throw_error("Unable to recognize the delegate metaclass '$meta'", data => $meta);
452bac1b 1063 }
1064}
1065
ccc2f11f 1066sub _find_delegate_metaclass {
1067 my $self = shift;
1068 if (my $class = $self->_isa_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 class which has not been loaded - %s',
1073 $self->name, $class
1074 )
1075 );
1076 }
ccc2f11f 1077 # we might be dealing with a non-Moose class,
1078 # and need to make our own metaclass. if there's
1079 # already a metaclass, it will be returned
1080 return Class::MOP::Class->initialize($class);
1081 }
1082 elsif (my $role = $self->_does_metadata) {
9238220f 1083 unless ( Class::MOP::is_class_loaded($class) ) {
1084 $self->throw_error(
1085 sprintf(
1086 'The %s attribute is trying to delegate to a role which has not been loaded - %s',
1087 $self->name, $role
1088 )
1089 );
1090 }
1091
ccc2f11f 1092 return Class::MOP::class_of($role);
1093 }
1094 else {
1095 $self->throw_error("Cannot find delegate metaclass for attribute " . $self->name);
1096 }
1097}
1098
bd1226e2 1099sub delegation_metaclass { 'Moose::Meta::Method::Delegation' }
1100
a05f85c1 1101sub _make_delegation_method {
46f7e6a5 1102 my ( $self, $handle_name, $method_to_call ) = @_;
a05f85c1 1103
3c573ca4 1104 my @curried_arguments;
2de18801 1105
3c573ca4 1106 ($method_to_call, @curried_arguments) = @$method_to_call
2de18801 1107 if 'ARRAY' eq ref($method_to_call);
1108
bd1226e2 1109 return $self->delegation_metaclass->new(
46f7e6a5 1110 name => $handle_name,
1111 package_name => $self->associated_class->name,
1112 attribute => $self,
1113 delegate_to_method => $method_to_call,
3c573ca4 1114 curried_arguments => \@curried_arguments,
a05f85c1 1115 );
1116}
1117
9c9563c7 1118sub _coerce_and_verify {
1119 my $self = shift;
1120 my $val = shift;
1121 my $instance = shift;
1122
1123 return $val unless $self->has_type_constraint;
1124
2b54d2a6 1125 $val = $self->type_constraint->coerce($val)
5aab256d 1126 if $self->should_coerce && $self->type_constraint->has_coercion;
9c9563c7 1127
1128 $self->verify_against_type_constraint($val, instance => $instance);
1129
1130 return $val;
1131}
1132
5755a9b2 1133sub verify_against_type_constraint {
2b86e02b 1134 my $self = shift;
1135 my $val = shift;
1136
1137 return 1 if !$self->has_type_constraint;
1138
1139 my $type_constraint = $self->type_constraint;
1140
1141 $type_constraint->check($val)
1142 || $self->throw_error("Attribute ("
1143 . $self->name
1144 . ") does not pass the type constraint because: "
1145 . $type_constraint->get_message($val), data => $val, @_);
1146}
1147
21f1e231 1148package Moose::Meta::Attribute::Custom::Moose;
1149sub register_implementation { 'Moose::Meta::Attribute' }
1150
c0e30cf5 11511;
1152
1153__END__
1154
1155=pod
1156
1157=head1 NAME
1158
6ba6d68c 1159Moose::Meta::Attribute - The Moose attribute metaclass
c0e30cf5 1160
1161=head1 DESCRIPTION
1162
93a708fd 1163This class is a subclass of L<Class::MOP::Attribute> that provides
1164additional Moose-specific functionality.
6ba6d68c 1165
7854b409 1166To really understand this class, you will need to start with the
1167L<Class::MOP::Attribute> documentation. This class can be understood
1168as a set of additional features on top of the basic feature provided
1169by that parent class.
e522431d 1170
d4b1449e 1171=head1 INHERITANCE
1172
1173C<Moose::Meta::Attribute> is a subclass of L<Class::MOP::Attribute>.
1174
c0e30cf5 1175=head1 METHODS
1176
93a708fd 1177Many of the documented below override methods in
1178L<Class::MOP::Attribute> and add Moose specific features.
6ba6d68c 1179
93a708fd 1180=head2 Creation
6ba6d68c 1181
c0e30cf5 1182=over 4
1183
93a708fd 1184=item B<< Moose::Meta::Attribute->new(%options) >>
c0e30cf5 1185
93a708fd 1186This method overrides the L<Class::MOP::Attribute> constructor.
c32c2c61 1187
93a708fd 1188Many of the options below are described in more detail in the
1189L<Moose::Manual::Attributes> document.
6e2840b7 1190
93a708fd 1191It adds the following options to the constructor:
d500266f 1192
93a708fd 1193=over 8
452bac1b 1194
996b8c8d 1195=item * is => 'ro', 'rw', 'bare'
e1d6f0a3 1196
93a708fd 1197This provides a shorthand for specifying the C<reader>, C<writer>, or
1198C<accessor> names. If the attribute is read-only ('ro') then it will
1199have a C<reader> method with the same attribute as the name.
e606ae5f 1200
93a708fd 1201If it is read-write ('rw') then it will have an C<accessor> method
1202with the same name. If you provide an explicit C<writer> for a
1203read-write attribute, then you will have a C<reader> with the same
1204name as the attribute, and a C<writer> with the name you provided.
e1d6f0a3 1205
996b8c8d 1206Use 'bare' when you are deliberately not installing any methods
1207(accessor, reader, etc.) associated with this attribute; otherwise,
1208Moose will issue a deprecation warning when this attribute is added to a
9340e346 1209metaclass.
996b8c8d 1210
93a708fd 1211=item * isa => $type
39b3bc94 1212
93a708fd 1213This option accepts a type. The type can be a string, which should be
1214a type name. If the type name is unknown, it is assumed to be a class
1215name.
1216
1217This option can also accept a L<Moose::Meta::TypeConstraint> object.
1218
1219If you I<also> provide a C<does> option, then your C<isa> option must
1220be a class name, and that class must do the role specified with
1221C<does>.
1222
1223=item * does => $role
1224
1225This is short-hand for saying that the attribute's type must be an
1226object which does the named role.
1227
1228=item * coerce => $bool
1229
1230This option is only valid for objects with a type constraint
3b98ba07 1231(C<isa>) that defined a coercion. If this is true, then coercions will be applied whenever
93a708fd 1232this attribute is set.
1233
1234You can make both this and the C<weak_ref> option true.
1235
1236=item * trigger => $sub
1237
1238This option accepts a subroutine reference, which will be called after
1239the attribute is set.
1240
1241=item * required => $bool
1242
1243An attribute which is required must be provided to the constructor. An
1244attribute which is required can also have a C<default> or C<builder>,
36741534 1245which will satisfy its required-ness.
93a708fd 1246
1247A required attribute must have a C<default>, C<builder> or a
1248non-C<undef> C<init_arg>
1249
1250=item * lazy => $bool
1251
1252A lazy attribute must have a C<default> or C<builder>. When an
1253attribute is lazy, the default value will not be calculated until the
1254attribute is read.
1255
1256=item * weak_ref => $bool
1257
1258If this is true, the attribute's value will be stored as a weak
1259reference.
1260
1261=item * auto_deref => $bool
1262
1263If this is true, then the reader will dereference the value when it is
1264called. The attribute must have a type constraint which defines the
1265attribute as an array or hash reference.
1266
1267=item * lazy_build => $bool
1268
1269Setting this to true makes the attribute lazy and provides a number of
1270default methods.
1271
1272 has 'size' => (
1273 is => 'ro',
1274 lazy_build => 1,
1275 );
1276
1277is equivalent to this:
1278
1279 has 'size' => (
1280 is => 'ro',
1281 lazy => 1,
1282 builder => '_build_size',
1283 clearer => 'clear_size',
1284 predicate => 'has_size',
1285 );
1286
970a92fa 1287
1288If your attribute name starts with an underscore (C<_>), then the clearer
1289and predicate will as well:
1290
1291 has '_size' => (
1292 is => 'ro',
1293 lazy_build => 1,
1294 );
1295
1296becomes:
1297
1298 has '_size' => (
1299 is => 'ro',
1300 lazy => 1,
1301 builder => '_build__size',
1302 clearer => '_clear_size',
1303 predicate => '_has_size',
1304 );
1305
1306Note the doubled underscore in the builder name. Internally, Moose
1307simply prepends the attribute name with "_build_" to come up with the
1308builder name.
1309
93a708fd 1310=item * documentation
1311
1312An arbitrary string that can be retrieved later by calling C<<
1313$attr->documentation >>.
1314
1315=back
1316
1317=item B<< $attr->clone(%options) >>
1318
1319This creates a new attribute based on attribute being cloned. You must
1320supply a C<name> option to provide a new name for the attribute.
1321
1322The C<%options> can only specify options handled by
1323L<Class::MOP::Attribute>.
1324
36741534 1325=back
1326
93a708fd 1327=head2 Value management
1328
36741534 1329=over 4
1330
93a708fd 1331=item B<< $attr->initialize_instance_slot($meta_instance, $instance, $params) >>
1332
1333This method is used internally to initialize the attribute's slot in
1334the object C<$instance>.
1335
1336This overrides the L<Class::MOP::Attribute> method to handle lazy
1337attributes, weak references, and type constraints.
bd1226e2 1338
946289d1 1339=item B<get_value>
1340
1341=item B<set_value>
1342
6549b0d1 1343 eval { $point->meta->get_attribute('x')->set_value($point, 'forty-two') };
bcbaa845 1344 if($@) {
1345 print "Oops: $@\n";
1346 }
1347
6549b0d1 1348I<Attribute (x) does not pass the type constraint (Int) with 'forty-two'>
bcbaa845 1349
1350Before setting the value, a check is made on the type constraint of
1351the attribute, if it has one, to see if the value passes it. If the
cec39889 1352value fails to pass, the set operation dies with a L</throw_error>.
bcbaa845 1353
1354Any coercion to convert values is done before checking the type constraint.
1355
1356To check a value against a type constraint before setting it, fetch the
ec00fa75 1357attribute instance using L<Class::MOP::Class/find_attribute_by_name>,
bcbaa845 1358fetch the type_constraint from the attribute using L<Moose::Meta::Attribute/type_constraint>
e606ae5f 1359and call L<Moose::Meta::TypeConstraint/check>. See L<Moose::Cookbook::Basics::Recipe4>
bcbaa845 1360for an example.
1361
a15dff8d 1362=back
1363
93a708fd 1364=head2 Attribute Accessor generation
6ba6d68c 1365
a15dff8d 1366=over 4
1367
93a708fd 1368=item B<< $attr->install_accessors >>
be05faea 1369
93a708fd 1370This method overrides the parent to also install delegation methods.
be05faea 1371
7a582117 1372If, after installing all methods, the attribute object has no associated
1373methods, it throws an error unless C<< is => 'bare' >> was passed to the
1374attribute constructor. (Trying to add an attribute that has no associated
1375methods is almost always an error.)
1376
36741534 1377=item B<< $attr->remove_accessors >>
d5c30e52 1378
93a708fd 1379This method overrides the parent to also remove delegation methods.
d5c30e52 1380
e06951bb 1381=item B<< $attr->inline_set($instance_var, $value_var) >>
d67398ab 1382
e06951bb 1383This method return a code snippet suitable for inlining the relevant
1384operation. It expect strings containing variable names to be used in the
1385inlining, like C<'$self'> or C<'$_[1]'>.
d67398ab 1386
93a708fd 1387=item B<< $attr->install_delegation >>
1388
1389This method adds its delegation methods to the attribute's associated
1390class, if it has any to add.
1391
1392=item B<< $attr->remove_delegation >>
1393
1394This method remove its delegation methods from the attribute's
1395associated class.
d5c30e52 1396
93a708fd 1397=item B<< $attr->accessor_metaclass >>
9e93dd19 1398
93a708fd 1399Returns the accessor metaclass name, which defaults to
1400L<Moose::Meta::Method::Accessor>.
1401
1402=item B<< $attr->delegation_metaclass >>
1403
1404Returns the delegation metaclass name, which defaults to
1405L<Moose::Meta::Method::Delegation>.
1406
1407=back
1408
1409=head2 Additional Moose features
1410
1411These methods are not found in the superclass. They support features
1412provided by Moose.
1413
36741534 1414=over 4
1415
93a708fd 1416=item B<< $attr->does($role) >>
1417
1418This indicates whether the I<attribute itself> does the given
36741534 1419role. The role can be given as a full class name, or as a resolvable
93a708fd 1420trait name.
1421
1422Note that this checks the attribute itself, not its type constraint,
1423so it is checking the attribute's metaclass and any traits applied to
1424the attribute.
1425
1426=item B<< Moose::Meta::Class->interpolate_class_and_new($name, %options) >>
1427
1428This is an alternate constructor that handles the C<metaclass> and
1429C<traits> options.
9e93dd19 1430
93a708fd 1431Effectively, this method is a factory that finds or creates the
36741534 1432appropriate class for the given C<metaclass> and/or C<traits>.
e606ae5f 1433
93a708fd 1434Once it has the appropriate class, it will call C<< $class->new($name,
1435%options) >> on that class.
e606ae5f 1436
93a708fd 1437=item B<< $attr->clone_and_inherit_options(%options) >>
a15dff8d 1438
93a708fd 1439This method supports the C<has '+foo'> feature. It does various bits
1440of processing on the supplied C<%options> before ultimately calling
1441the C<clone> method.
6ba6d68c 1442
93a708fd 1443One of its main tasks is to make sure that the C<%options> provided
7782e1da 1444does not include the options returned by the
1445C<illegal_options_for_inheritance> method.
a15dff8d 1446
7782e1da 1447=item B<< $attr->illegal_options_for_inheritance >>
a15dff8d 1448
7782e1da 1449This returns a blacklist of options that can not be overridden in a
93a708fd 1450subclass's attribute definition.
2b86e02b 1451
93a708fd 1452This exists to allow a custom metaclass to change or add to the list
7782e1da 1453of options which can not be changed.
2b86e02b 1454
93a708fd 1455=item B<< $attr->type_constraint >>
452bac1b 1456
93a708fd 1457Returns the L<Moose::Meta::TypeConstraint> object for this attribute,
1458if it has one.
452bac1b 1459
93a708fd 1460=item B<< $attr->has_type_constraint >>
452bac1b 1461
93a708fd 1462Returns true if this attribute has a type constraint.
452bac1b 1463
93a708fd 1464=item B<< $attr->verify_against_type_constraint($value) >>
a15dff8d 1465
93a708fd 1466Given a value, this method returns true if the value is valid for the
1467attribute's type constraint. If the value is not valid, it throws an
1468error.
4b598ea3 1469
93a708fd 1470=item B<< $attr->handles >>
ca01a97b 1471
93a708fd 1472This returns the value of the C<handles> option passed to the
1473constructor.
ca01a97b 1474
93a708fd 1475=item B<< $attr->has_handles >>
ca01a97b 1476
93a708fd 1477Returns true if this attribute performs delegation.
ca01a97b 1478
93a708fd 1479=item B<< $attr->is_weak_ref >>
26fbace8 1480
93a708fd 1481Returns true if this attribute stores its value as a weak reference.
26fbace8 1482
93a708fd 1483=item B<< $attr->is_required >>
26fbace8 1484
93a708fd 1485Returns true if this attribute is required to have a value.
26fbace8 1486
93a708fd 1487=item B<< $attr->is_lazy >>
58f85113 1488
93a708fd 1489Returns true if this attribute is lazy.
26fbace8 1490
93a708fd 1491=item B<< $attr->is_lazy_build >>
ca01a97b 1492
93a708fd 1493Returns true if the C<lazy_build> option was true when passed to the
1494constructor.
4b598ea3 1495
93a708fd 1496=item B<< $attr->should_coerce >>
6ba6d68c 1497
93a708fd 1498Returns true if the C<coerce> option passed to the constructor was
1499true.
536f0b17 1500
93a708fd 1501=item B<< $attr->should_auto_deref >>
536f0b17 1502
93a708fd 1503Returns true if the C<auto_deref> option passed to the constructor was
1504true.
536f0b17 1505
93a708fd 1506=item B<< $attr->trigger >>
8c9d74e7 1507
93a708fd 1508This is the subroutine reference that was in the C<trigger> option
1509passed to the constructor, if any.
02a0fb52 1510
36741534 1511=item B<< $attr->has_trigger >>
8c9d74e7 1512
93a708fd 1513Returns true if this attribute has a trigger set.
02a0fb52 1514
93a708fd 1515=item B<< $attr->documentation >>
ddbdc0cb 1516
93a708fd 1517Returns the value that was in the C<documentation> option passed to
1518the constructor, if any.
ddbdc0cb 1519
93a708fd 1520=item B<< $attr->has_documentation >>
ddbdc0cb 1521
93a708fd 1522Returns true if this attribute has any documentation.
ddbdc0cb 1523
93a708fd 1524=item B<< $attr->applied_traits >>
88f23977 1525
93a708fd 1526This returns an array reference of all the traits which were applied
1527to this attribute. If none were applied, this returns C<undef>.
88f23977 1528
93a708fd 1529=item B<< $attr->has_applied_traits >>
88f23977 1530
93a708fd 1531Returns true if this attribute has any traits applied.
88f23977 1532
c0e30cf5 1533=back
1534
1535=head1 BUGS
1536
d4048ef3 1537See L<Moose/BUGS> for details on reporting bugs.
c0e30cf5 1538
c0e30cf5 1539=head1 AUTHOR
1540
1541Stevan Little E<lt>stevan@iinteractive.comE<gt>
1542
98aae381 1543Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
1544
c0e30cf5 1545=head1 COPYRIGHT AND LICENSE
1546
7e0492d3 1547Copyright 2006-2010 by Infinity Interactive, Inc.
c0e30cf5 1548
1549L<http://www.iinteractive.com>
1550
1551This library is free software; you can redistribute it and/or modify
26fbace8 1552it under the same terms as Perl itself.
c0e30cf5 1553
8a7a9c53 1554=cut