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