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