no idea what's up with this error message
[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(
9f468258 651 '"Attribute (' . $attr_name . ') is required"'
6e50f7e9 652 ) . ';',
653 '}',
654 );
655}
656
657sub _inline_tc_code {
658 my $self = shift;
a619fc2f 659 my ($value, $tc, $coercion, $message, $is_lazy) = @_;
6e50f7e9 660 return (
c40e4359 661 $self->_inline_check_coercion(
662 $value, $tc, $coercion, $is_lazy,
663 ),
664 $self->_inline_check_constraint(
a619fc2f 665 $value, $tc, $message, $is_lazy,
c40e4359 666 ),
6e50f7e9 667 );
668}
669
670sub _inline_check_coercion {
671 my $self = shift;
c40e4359 672 my ($value, $tc, $coercion) = @_;
6e50f7e9 673
674 return unless $self->should_coerce && $self->type_constraint->has_coercion;
675
c40e4359 676 if ( $self->type_constraint->can_be_inlined ) {
677 return (
678 'if (! (' . $self->type_constraint->_inline_check($value) . ')) {',
679 $value . ' = ' . $coercion . '->(' . $value . ');',
680 '}',
681 );
682 }
683 else {
684 return (
685 'if (!' . $tc . '->(' . $value . ')) {',
686 $value . ' = ' . $coercion . '->(' . $value . ');',
687 '}',
688 );
689 }
6e50f7e9 690}
691
692sub _inline_check_constraint {
693 my $self = shift;
a619fc2f 694 my ($value, $tc, $message) = @_;
6e50f7e9 695
696 return unless $self->has_type_constraint;
697
698 my $attr_name = quotemeta($self->name);
699
7c047a36 700 if ( $self->type_constraint->can_be_inlined ) {
4e36cf24 701 return (
702 'if (! (' . $self->type_constraint->_inline_check($value) . ')) {',
703 $self->_inline_throw_error(
704 '"Attribute (' . $attr_name . ') does not pass the type '
705 . 'constraint because: " . '
a619fc2f 706 . 'do { local $_ = ' . $value . '; '
707 . $message . '->(' . $value . ')'
708 . '}',
4e36cf24 709 'data => ' . $value
710 ) . ';',
711 '}',
712 );
713 }
714 else {
715 return (
716 'if (!' . $tc . '->(' . $value . ')) {',
717 $self->_inline_throw_error(
718 '"Attribute (' . $attr_name . ') does not pass the type '
719 . 'constraint because: " . '
a619fc2f 720 . 'do { local $_ = ' . $value . '; '
721 . $message . '->(' . $value . ')'
722 . '}',
4e36cf24 723 'data => ' . $value
724 ) . ';',
725 '}',
726 );
727 }
6e50f7e9 728}
729
730sub _inline_get_old_value_for_trigger {
731 my $self = shift;
732 my ($instance, $old) = @_;
733
734 return unless $self->has_trigger;
735
736 return (
737 'my ' . $old . ' = ' . $self->_inline_instance_has($instance),
738 '? ' . $self->_inline_instance_get($instance),
739 ': ();',
740 );
741}
742
743sub _inline_weaken_value {
744 my $self = shift;
745 my ($instance, $value) = @_;
746
747 return unless $self->is_weak_ref;
748
749 my $mi = $self->associated_class->get_meta_instance;
750 return (
12b0a103 751 $mi->inline_weaken_slot_value($instance, $self->name),
6e50f7e9 752 'if ref ' . $value . ';',
753 );
754}
755
756sub _inline_trigger {
757 my $self = shift;
758 my ($instance, $value, $old) = @_;
759
760 return unless $self->has_trigger;
761
37ffa261 762 return '$trigger->(' . $instance . ', ' . $value . ', ' . $old . ');';
6e50f7e9 763}
764
f7db8e35 765sub _eval_environment {
766 my $self = shift;
767
768 my $env = { };
769
770 $env->{'$trigger'} = \($self->trigger)
771 if $self->has_trigger;
772 $env->{'$attr_default'} = \($self->default)
773 if $self->has_default;
774
775 if ($self->has_type_constraint) {
776 my $tc_obj = $self->type_constraint;
777
778 $env->{'$type_constraint'} = \(
779 $tc_obj->_compiled_type_constraint
780 ) unless $tc_obj->can_be_inlined;
781 # these two could probably get inlined versions too
782 $env->{'$type_coercion'} = \(
783 $tc_obj->coercion->_compiled_type_coercion
784 ) if $tc_obj->has_coercion;
785 $env->{'$type_message'} = \(
786 $tc_obj->has_message ? $tc_obj->message : $tc_obj->_default_message
787 );
788
789 $env = { %$env, %{ $tc_obj->inline_environment } };
790 }
791
792 # XXX ugh, fix these
793 $env->{'$attr'} = \$self
794 if $self->has_initializer && $self->is_lazy;
795 # pretty sure this is only going to be closed over if you use a custom
796 # error class at this point, but we should still get rid of this
797 # at some point
798 $env->{'$meta'} = \($self->associated_class);
799
800 return $env;
801}
802
32881f68 803sub _weaken_value {
312e0f0c 804 my ( $self, $instance ) = @_;
805
32881f68 806 my $meta_instance = Class::MOP::Class->initialize( blessed($instance) )
807 ->get_meta_instance;
312e0f0c 808
809 $meta_instance->weaken_slot_value( $instance, $self->name );
810}
811
946289d1 812sub get_value {
3dda07f5 813 my ($self, $instance, $for_trigger) = @_;
26fbace8 814
946289d1 815 if ($self->is_lazy) {
8de73ff1 816 unless ($self->has_value($instance)) {
e606ae5f 817 my $value;
8de73ff1 818 if ($self->has_default) {
e606ae5f 819 $value = $self->default($instance);
3f11800d 820 } elsif ( $self->has_builder ) {
e606ae5f 821 $value = $self->_call_builder($instance);
822 }
9c9563c7 823
824 $value = $self->_coerce_and_verify( $value, $instance );
825
e606ae5f 826 $self->set_initial_value($instance, $value);
12b0a103 827
828 if ( ref $value && $self->is_weak_ref ) {
829 $self->_weaken_value($instance);
830 }
8de73ff1 831 }
946289d1 832 }
26fbace8 833
3dda07f5 834 if ( $self->should_auto_deref && ! $for_trigger ) {
26fbace8 835
946289d1 836 my $type_constraint = $self->type_constraint;
837
838 if ($type_constraint->is_a_type_of('ArrayRef')) {
839 my $rv = $self->SUPER::get_value($instance);
840 return unless defined $rv;
841 return wantarray ? @{ $rv } : $rv;
26fbace8 842 }
946289d1 843 elsif ($type_constraint->is_a_type_of('HashRef')) {
844 my $rv = $self->SUPER::get_value($instance);
845 return unless defined $rv;
846 return wantarray ? %{ $rv } : $rv;
26fbace8 847 }
946289d1 848 else {
46cb090f 849 $self->throw_error("Can not auto de-reference the type constraint '" . $type_constraint->name . "'", object => $instance, type_constraint => $type_constraint);
946289d1 850 }
26fbace8 851
946289d1 852 }
853 else {
26fbace8 854
946289d1 855 return $self->SUPER::get_value($instance);
26fbace8 856 }
946289d1 857}
a15dff8d 858
6e50f7e9 859sub _inline_get_value {
860 my $self = shift;
a619fc2f 861 my ($instance, $tc, $coercion, $message) = @_;
6e50f7e9 862
863 my $slot_access = $self->_inline_instance_get($instance);
ec86bdff 864 $tc ||= '$type_constraint';
c40e4359 865 $coercion ||= '$type_coercion';
a619fc2f 866 $message ||= '$type_message';
6e50f7e9 867
868 return (
a619fc2f 869 $self->_inline_check_lazy($instance, $tc, $coercion, $message),
6e50f7e9 870 $self->_inline_return_auto_deref($slot_access),
871 );
872}
873
874sub _inline_check_lazy {
875 my $self = shift;
a619fc2f 876 my ($instance, $tc, $coercion, $message) = @_;
6e50f7e9 877
878 return unless $self->is_lazy;
879
880 my $slot_exists = $self->_inline_instance_has($instance);
881
882 return (
883 'if (!' . $slot_exists . ') {',
a619fc2f 884 $self->_inline_init_from_default($instance, '$default', $tc, $coercion, $message, 'lazy'),
6e50f7e9 885 '}',
886 );
887}
888
889sub _inline_init_from_default {
890 my $self = shift;
a619fc2f 891 my ($instance, $default, $tc, $coercion, $message, $for_lazy) = @_;
6e50f7e9 892
893 if (!($self->has_default || $self->has_builder)) {
894 $self->throw_error(
895 'You cannot have a lazy attribute '
896 . '(' . $self->name . ') '
897 . 'without specifying a default value for it',
898 attr => $self,
899 );
900 }
901
902 return (
903 $self->_inline_generate_default($instance, $default),
904 # intentionally not using _inline_tc_code, since that can be overridden
905 # to do things like possibly only do member tc checks, which isn't
906 # appropriate for checking the result of a default
907 $self->has_type_constraint
c40e4359 908 ? ($self->_inline_check_coercion($default, $tc, $coercion, $for_lazy),
a619fc2f 909 $self->_inline_check_constraint($default, $tc, $message, $for_lazy))
6e50f7e9 910 : (),
911 $self->_inline_init_slot($instance, $default),
12b0a103 912 $self->_inline_weaken_value($instance, $default),
6e50f7e9 913 );
914}
915
916sub _inline_generate_default {
917 my $self = shift;
918 my ($instance, $default) = @_;
919
920 if ($self->has_default) {
0ec49767 921 my $source = 'my ' . $default . ' = $attr_default';
37ffa261 922 $source .= '->(' . $instance . ')'
923 if $self->is_default_a_coderef;
924 return $source . ';';
6e50f7e9 925 }
926 elsif ($self->has_builder) {
37ffa261 927 my $builder = B::perlstring($self->builder);
928 my $builder_str = quotemeta($self->builder);
929 my $attr_name_str = quotemeta($self->name);
6e50f7e9 930 return (
931 'my ' . $default . ';',
37ffa261 932 'if (my $builder = ' . $instance . '->can(' . $builder . ')) {',
6e50f7e9 933 $default . ' = ' . $instance . '->$builder;',
934 '}',
935 'else {',
936 'my $class = ref(' . $instance . ') || ' . $instance . ';',
6e50f7e9 937 $self->_inline_throw_error(
938 '"$class does not support builder method '
37ffa261 939 . '\'' . $builder_str . '\' for attribute '
940 . '\'' . $attr_name_str . '\'"'
6e50f7e9 941 ) . ';',
942 '}',
943 );
944 }
945 else {
946 $self->throw_error(
947 "Can't generate a default for " . $self->name
948 . " since no default or builder was specified"
949 );
950 }
951}
952
953sub _inline_init_slot {
954 my $self = shift;
955 my ($inv, $value) = @_;
956
957 if ($self->has_initializer) {
958 return '$attr->set_initial_value(' . $inv . ', ' . $value . ');';
959 }
960 else {
961 return $self->_inline_instance_set($inv, $value) . ';';
962 }
963}
964
965sub _inline_return_auto_deref {
966 my $self = shift;
967
968 return 'return ' . $self->_auto_deref(@_) . ';';
969}
970
971sub _auto_deref {
972 my $self = shift;
973 my ($ref_value) = @_;
974
975 return $ref_value unless $self->should_auto_deref;
976
977 my $type_constraint = $self->type_constraint;
978
979 my $sigil;
980 if ($type_constraint->is_a_type_of('ArrayRef')) {
981 $sigil = '@';
982 }
983 elsif ($type_constraint->is_a_type_of('HashRef')) {
984 $sigil = '%';
985 }
986 else {
987 $self->throw_error(
988 'Can not auto de-reference the type constraint \''
989 . $type_constraint->name
990 . '\'',
991 type_constraint => $type_constraint,
992 );
993 }
994
995 return 'wantarray '
996 . '? ' . $sigil . '{ (' . $ref_value . ') || return } '
997 . ': (' . $ref_value . ')';
998}
999
26fbace8 1000## installing accessors
c0e30cf5 1001
246bbeef 1002sub accessor_metaclass { 'Moose::Meta::Method::Accessor' }
1003
1004sub install_accessors {
ae907ae0 1005 my $self = shift;
246bbeef 1006 $self->SUPER::install_accessors(@_);
1007 $self->install_delegation if $self->has_handles;
28af3424 1008 return;
1009}
1010
9340e346 1011sub _check_associated_methods {
28af3424 1012 my $self = shift;
86cf196b 1013 unless (
0bbd378f 1014 @{ $self->associated_methods }
86cf196b 1015 || ($self->_is_metadata || '') eq 'bare'
1016 ) {
1017 Carp::cluck(
8f4450f3 1018 'Attribute (' . $self->name . ') of class '
1019 . $self->associated_class->name
1020 . ' has no associated methods'
86cf196b 1021 . ' (did you mean to provide an "is" argument?)'
1022 . "\n"
1023 )
1024 }
e606ae5f 1025}
26fbace8 1026
3b6e2290 1027sub _process_accessors {
1028 my $self = shift;
1029 my ($type, $accessor, $generate_as_inline_methods) = @_;
837f61c9 1030
1031 $accessor = ( keys %$accessor )[0] if ( ref($accessor) || '' ) eq 'HASH';
99541dfd 1032 my $method = $self->associated_class->get_method($accessor);
837f61c9 1033
d7dfe605 1034 if ( $method
1035 && $method->isa('Class::MOP::Method::Accessor')
1036 && $method->associated_attribute->name ne $self->name ) {
1037
1038 my $other_attr_name = $method->associated_attribute->name;
1039 my $name = $self->name;
1040
1041 Carp::cluck(
1042 "You are overwriting an accessor ($accessor) for the $other_attr_name attribute"
1043 . " with a new accessor method for the $name attribute" );
1044 }
1045
837f61c9 1046 if (
1047 $method
5bfb3fa4 1048 && !$method->is_stub
837f61c9 1049 && !$method->isa('Class::MOP::Method::Accessor')
1050 && ( !$self->definition_context
1051 || $method->package_name eq $self->definition_context->{package} )
1052 ) {
1053
3b6e2290 1054 Carp::cluck(
1d18c898 1055 "You are overwriting a locally defined method ($accessor) with "
837f61c9 1056 . "an accessor" );
3b6e2290 1057 }
d7dfe605 1058
837f61c9 1059 if ( !$self->associated_class->has_method($accessor)
1060 && $self->associated_class->has_package_symbol( '&' . $accessor ) ) {
1061
3968746e 1062 Carp::cluck(
1063 "You are overwriting a locally defined function ($accessor) with "
837f61c9 1064 . "an accessor" );
3968746e 1065 }
837f61c9 1066
3b6e2290 1067 $self->SUPER::_process_accessors(@_);
e606ae5f 1068}
26fbace8 1069
e1d6f0a3 1070sub remove_accessors {
1071 my $self = shift;
1072 $self->SUPER::remove_accessors(@_);
1073 $self->remove_delegation if $self->has_handles;
1074 return;
1075}
1076
e606ae5f 1077sub install_delegation {
1078 my $self = shift;
26fbace8 1079
e606ae5f 1080 # NOTE:
1081 # Here we canonicalize the 'handles' option
1082 # this will sort out any details and always
1083 # return an hash of methods which we want
1084 # to delagate to, see that method for details
1085 my %handles = $self->_canonicalize_handles;
1086
e606ae5f 1087
1088 # install the delegation ...
1089 my $associated_class = $self->associated_class;
d699590f 1090 foreach my $handle (sort keys %handles) {
e606ae5f 1091 my $method_to_call = $handles{$handle};
1092 my $class_name = $associated_class->name;
1093 my $name = "${class_name}::${handle}";
26fbace8 1094
906b9dad 1095 if ( my $method = $associated_class->get_method($handle) ) {
1096 $self->throw_error(
1097 "You cannot overwrite a locally defined method ($handle) with a delegation",
1098 method_name => $handle
1099 ) unless $method->is_stub;
1100 }
26fbace8 1101
e606ae5f 1102 # NOTE:
1103 # handles is not allowed to delegate
1104 # any of these methods, as they will
1105 # override the ones in your class, which
1106 # is almost certainly not what you want.
4fe78472 1107
e606ae5f 1108 # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something
1109 #cluck("Not delegating method '$handle' because it is a core method") and
1110 next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle);
26fbace8 1111
46f7e6a5 1112 my $method = $self->_make_delegation_method($handle, $method_to_call);
a05f85c1 1113
1114 $self->associated_class->add_method($method->name, $method);
0bbd378f 1115 $self->associate_method($method);
d03bd989 1116 }
452bac1b 1117}
1118
e1d6f0a3 1119sub remove_delegation {
1120 my $self = shift;
1121 my %handles = $self->_canonicalize_handles;
1122 my $associated_class = $self->associated_class;
1123 foreach my $handle (keys %handles) {
684323b3 1124 next unless any { $handle eq $_ }
1125 map { $_->name }
1126 @{ $self->associated_methods };
e1d6f0a3 1127 $self->associated_class->remove_method($handle);
1128 }
1129}
1130
98aae381 1131# private methods to help delegation ...
1132
452bac1b 1133sub _canonicalize_handles {
1134 my $self = shift;
1135 my $handles = $self->handles;
c84f324f 1136 if (my $handle_type = ref($handles)) {
1137 if ($handle_type eq 'HASH') {
1138 return %{$handles};
1139 }
1140 elsif ($handle_type eq 'ARRAY') {
1141 return map { $_ => $_ } @{$handles};
1142 }
1143 elsif ($handle_type eq 'Regexp') {
1144 ($self->has_type_constraint)
0286711b 1145 || $self->throw_error("Cannot delegate methods based on a Regexp without a type constraint (isa)", data => $handles);
26fbace8 1146 return map { ($_ => $_) }
c84f324f 1147 grep { /$handles/ } $self->_get_delegate_method_list;
1148 }
1149 elsif ($handle_type eq 'CODE') {
1150 return $handles->($self, $self->_find_delegate_metaclass);
1151 }
6cbf4a23 1152 elsif (blessed($handles) && $handles->isa('Moose::Meta::TypeConstraint::DuckType')) {
1153 return map { $_ => $_ } @{ $handles->methods };
1154 }
c7761602 1155 elsif (blessed($handles) && $handles->isa('Moose::Meta::TypeConstraint::Role')) {
1156 $handles = $handles->role;
1157 }
c84f324f 1158 else {
be05faea 1159 $self->throw_error("Unable to canonicalize the 'handles' option with $handles", data => $handles);
c84f324f 1160 }
452bac1b 1161 }
c84f324f 1162
b5ae7c00 1163 load_class($handles);
c7761602 1164 my $role_meta = Class::MOP::class_of($handles);
d03bd989 1165
c7761602 1166 (blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
1167 || $self->throw_error("Unable to canonicalize the 'handles' option with $handles because its metaclass is not a Moose::Meta::Role", data => $handles);
1168
1169 return map { $_ => $_ }
ba7d613d 1170 map { $_->name }
1171 grep { !$_->isa('Class::MOP::Method::Meta') } (
1172 $role_meta->_get_local_methods,
1173 $role_meta->get_required_method_list,
c7761602 1174 );
452bac1b 1175}
1176
452bac1b 1177sub _get_delegate_method_list {
1178 my $self = shift;
1179 my $meta = $self->_find_delegate_metaclass;
1180 if ($meta->isa('Class::MOP::Class')) {
e606ae5f 1181 return map { $_->name } # NOTE: !never! delegate &meta
ba7d613d 1182 grep { $_->package_name ne 'Moose::Object' && !$_->isa('Class::MOP::Method::Meta') }
e606ae5f 1183 $meta->get_all_methods;
452bac1b 1184 }
1185 elsif ($meta->isa('Moose::Meta::Role')) {
26fbace8 1186 return $meta->get_method_list;
452bac1b 1187 }
1188 else {
be05faea 1189 $self->throw_error("Unable to recognize the delegate metaclass '$meta'", data => $meta);
452bac1b 1190 }
1191}
1192
ccc2f11f 1193sub _find_delegate_metaclass {
1194 my $self = shift;
1195 if (my $class = $self->_isa_metadata) {
b5ae7c00 1196 unless ( is_class_loaded($class) ) {
9238220f 1197 $self->throw_error(
1198 sprintf(
1199 'The %s attribute is trying to delegate to a class which has not been loaded - %s',
1200 $self->name, $class
1201 )
1202 );
1203 }
ccc2f11f 1204 # we might be dealing with a non-Moose class,
1205 # and need to make our own metaclass. if there's
1206 # already a metaclass, it will be returned
1207 return Class::MOP::Class->initialize($class);
1208 }
1209 elsif (my $role = $self->_does_metadata) {
b5ae7c00 1210 unless ( is_class_loaded($class) ) {
9238220f 1211 $self->throw_error(
1212 sprintf(
1213 'The %s attribute is trying to delegate to a role which has not been loaded - %s',
1214 $self->name, $role
1215 )
1216 );
1217 }
1218
ccc2f11f 1219 return Class::MOP::class_of($role);
1220 }
1221 else {
1222 $self->throw_error("Cannot find delegate metaclass for attribute " . $self->name);
1223 }
1224}
1225
bd1226e2 1226sub delegation_metaclass { 'Moose::Meta::Method::Delegation' }
1227
a05f85c1 1228sub _make_delegation_method {
46f7e6a5 1229 my ( $self, $handle_name, $method_to_call ) = @_;
a05f85c1 1230
3c573ca4 1231 my @curried_arguments;
2de18801 1232
3c573ca4 1233 ($method_to_call, @curried_arguments) = @$method_to_call
2de18801 1234 if 'ARRAY' eq ref($method_to_call);
1235
bd1226e2 1236 return $self->delegation_metaclass->new(
46f7e6a5 1237 name => $handle_name,
1238 package_name => $self->associated_class->name,
1239 attribute => $self,
1240 delegate_to_method => $method_to_call,
3c573ca4 1241 curried_arguments => \@curried_arguments,
a05f85c1 1242 );
1243}
1244
9c9563c7 1245sub _coerce_and_verify {
1246 my $self = shift;
1247 my $val = shift;
1248 my $instance = shift;
1249
1250 return $val unless $self->has_type_constraint;
1251
2b54d2a6 1252 $val = $self->type_constraint->coerce($val)
5aab256d 1253 if $self->should_coerce && $self->type_constraint->has_coercion;
9c9563c7 1254
1255 $self->verify_against_type_constraint($val, instance => $instance);
1256
1257 return $val;
1258}
1259
5755a9b2 1260sub verify_against_type_constraint {
2b86e02b 1261 my $self = shift;
1262 my $val = shift;
1263
1264 return 1 if !$self->has_type_constraint;
1265
1266 my $type_constraint = $self->type_constraint;
1267
1268 $type_constraint->check($val)
1269 || $self->throw_error("Attribute ("
1270 . $self->name
1271 . ") does not pass the type constraint because: "
1272 . $type_constraint->get_message($val), data => $val, @_);
1273}
1274
21f1e231 1275package Moose::Meta::Attribute::Custom::Moose;
1276sub register_implementation { 'Moose::Meta::Attribute' }
1277
c0e30cf5 12781;
1279
ad46f524 1280# ABSTRACT: The Moose attribute metaclass
1281
c0e30cf5 1282__END__
1283
1284=pod
1285
c0e30cf5 1286=head1 DESCRIPTION
1287
93a708fd 1288This class is a subclass of L<Class::MOP::Attribute> that provides
1289additional Moose-specific functionality.
6ba6d68c 1290
7854b409 1291To really understand this class, you will need to start with the
1292L<Class::MOP::Attribute> documentation. This class can be understood
1293as a set of additional features on top of the basic feature provided
1294by that parent class.
e522431d 1295
d4b1449e 1296=head1 INHERITANCE
1297
1298C<Moose::Meta::Attribute> is a subclass of L<Class::MOP::Attribute>.
1299
c0e30cf5 1300=head1 METHODS
1301
93a708fd 1302Many of the documented below override methods in
1303L<Class::MOP::Attribute> and add Moose specific features.
6ba6d68c 1304
93a708fd 1305=head2 Creation
6ba6d68c 1306
c0e30cf5 1307=over 4
1308
94d3459a 1309=item B<< Moose::Meta::Attribute->new($name, %options) >>
c0e30cf5 1310
93a708fd 1311This method overrides the L<Class::MOP::Attribute> constructor.
c32c2c61 1312
93a708fd 1313Many of the options below are described in more detail in the
1314L<Moose::Manual::Attributes> document.
6e2840b7 1315
93a708fd 1316It adds the following options to the constructor:
d500266f 1317
93a708fd 1318=over 8
452bac1b 1319
996b8c8d 1320=item * is => 'ro', 'rw', 'bare'
e1d6f0a3 1321
93a708fd 1322This provides a shorthand for specifying the C<reader>, C<writer>, or
1323C<accessor> names. If the attribute is read-only ('ro') then it will
1324have a C<reader> method with the same attribute as the name.
e606ae5f 1325
93a708fd 1326If it is read-write ('rw') then it will have an C<accessor> method
1327with the same name. If you provide an explicit C<writer> for a
1328read-write attribute, then you will have a C<reader> with the same
1329name as the attribute, and a C<writer> with the name you provided.
e1d6f0a3 1330
996b8c8d 1331Use 'bare' when you are deliberately not installing any methods
1332(accessor, reader, etc.) associated with this attribute; otherwise,
1333Moose will issue a deprecation warning when this attribute is added to a
9340e346 1334metaclass.
996b8c8d 1335
93a708fd 1336=item * isa => $type
39b3bc94 1337
93a708fd 1338This option accepts a type. The type can be a string, which should be
1339a type name. If the type name is unknown, it is assumed to be a class
1340name.
1341
1342This option can also accept a L<Moose::Meta::TypeConstraint> object.
1343
1344If you I<also> provide a C<does> option, then your C<isa> option must
1345be a class name, and that class must do the role specified with
1346C<does>.
1347
1348=item * does => $role
1349
1350This is short-hand for saying that the attribute's type must be an
1351object which does the named role.
1352
1353=item * coerce => $bool
1354
1355This option is only valid for objects with a type constraint
3b98ba07 1356(C<isa>) that defined a coercion. If this is true, then coercions will be applied whenever
93a708fd 1357this attribute is set.
1358
1359You can make both this and the C<weak_ref> option true.
1360
1361=item * trigger => $sub
1362
1363This option accepts a subroutine reference, which will be called after
1364the attribute is set.
1365
1366=item * required => $bool
1367
1368An attribute which is required must be provided to the constructor. An
1369attribute which is required can also have a C<default> or C<builder>,
36741534 1370which will satisfy its required-ness.
93a708fd 1371
1372A required attribute must have a C<default>, C<builder> or a
1373non-C<undef> C<init_arg>
1374
1375=item * lazy => $bool
1376
1377A lazy attribute must have a C<default> or C<builder>. When an
1378attribute is lazy, the default value will not be calculated until the
1379attribute is read.
1380
1381=item * weak_ref => $bool
1382
1383If this is true, the attribute's value will be stored as a weak
1384reference.
1385
1386=item * auto_deref => $bool
1387
1388If this is true, then the reader will dereference the value when it is
1389called. The attribute must have a type constraint which defines the
1390attribute as an array or hash reference.
1391
1392=item * lazy_build => $bool
1393
1394Setting this to true makes the attribute lazy and provides a number of
1395default methods.
1396
1397 has 'size' => (
1398 is => 'ro',
1399 lazy_build => 1,
1400 );
1401
1402is equivalent to this:
1403
1404 has 'size' => (
1405 is => 'ro',
1406 lazy => 1,
1407 builder => '_build_size',
1408 clearer => 'clear_size',
1409 predicate => 'has_size',
1410 );
1411
970a92fa 1412
1413If your attribute name starts with an underscore (C<_>), then the clearer
1414and predicate will as well:
1415
1416 has '_size' => (
1417 is => 'ro',
1418 lazy_build => 1,
1419 );
1420
1421becomes:
1422
1423 has '_size' => (
1424 is => 'ro',
1425 lazy => 1,
1426 builder => '_build__size',
1427 clearer => '_clear_size',
1428 predicate => '_has_size',
1429 );
1430
1431Note the doubled underscore in the builder name. Internally, Moose
1432simply prepends the attribute name with "_build_" to come up with the
1433builder name.
1434
93a708fd 1435=item * documentation
1436
1437An arbitrary string that can be retrieved later by calling C<<
1438$attr->documentation >>.
1439
1440=back
1441
1442=item B<< $attr->clone(%options) >>
1443
1444This creates a new attribute based on attribute being cloned. You must
1445supply a C<name> option to provide a new name for the attribute.
1446
1447The C<%options> can only specify options handled by
1448L<Class::MOP::Attribute>.
1449
36741534 1450=back
1451
93a708fd 1452=head2 Value management
1453
36741534 1454=over 4
1455
93a708fd 1456=item B<< $attr->initialize_instance_slot($meta_instance, $instance, $params) >>
1457
1458This method is used internally to initialize the attribute's slot in
1459the object C<$instance>.
1460
1461This overrides the L<Class::MOP::Attribute> method to handle lazy
1462attributes, weak references, and type constraints.
bd1226e2 1463
946289d1 1464=item B<get_value>
1465
1466=item B<set_value>
1467
6549b0d1 1468 eval { $point->meta->get_attribute('x')->set_value($point, 'forty-two') };
bcbaa845 1469 if($@) {
1470 print "Oops: $@\n";
1471 }
1472
6549b0d1 1473I<Attribute (x) does not pass the type constraint (Int) with 'forty-two'>
bcbaa845 1474
1475Before setting the value, a check is made on the type constraint of
1476the attribute, if it has one, to see if the value passes it. If the
6f970df6 1477value fails to pass, the set operation dies.
bcbaa845 1478
1479Any coercion to convert values is done before checking the type constraint.
1480
1481To check a value against a type constraint before setting it, fetch the
ec00fa75 1482attribute instance using L<Class::MOP::Class/find_attribute_by_name>,
bcbaa845 1483fetch the type_constraint from the attribute using L<Moose::Meta::Attribute/type_constraint>
2326164e 1484and call L<Moose::Meta::TypeConstraint/check>. See L<Moose::Cookbook::Basics::Company_Subtypes>
bcbaa845 1485for an example.
1486
a15dff8d 1487=back
1488
93a708fd 1489=head2 Attribute Accessor generation
6ba6d68c 1490
a15dff8d 1491=over 4
1492
93a708fd 1493=item B<< $attr->install_accessors >>
be05faea 1494
93a708fd 1495This method overrides the parent to also install delegation methods.
be05faea 1496
7a582117 1497If, after installing all methods, the attribute object has no associated
1498methods, it throws an error unless C<< is => 'bare' >> was passed to the
1499attribute constructor. (Trying to add an attribute that has no associated
1500methods is almost always an error.)
1501
36741534 1502=item B<< $attr->remove_accessors >>
d5c30e52 1503
93a708fd 1504This method overrides the parent to also remove delegation methods.
d5c30e52 1505
e06951bb 1506=item B<< $attr->inline_set($instance_var, $value_var) >>
d67398ab 1507
e06951bb 1508This method return a code snippet suitable for inlining the relevant
1509operation. It expect strings containing variable names to be used in the
1510inlining, like C<'$self'> or C<'$_[1]'>.
d67398ab 1511
93a708fd 1512=item B<< $attr->install_delegation >>
1513
1514This method adds its delegation methods to the attribute's associated
1515class, if it has any to add.
1516
1517=item B<< $attr->remove_delegation >>
1518
1519This method remove its delegation methods from the attribute's
1520associated class.
d5c30e52 1521
93a708fd 1522=item B<< $attr->accessor_metaclass >>
9e93dd19 1523
93a708fd 1524Returns the accessor metaclass name, which defaults to
1525L<Moose::Meta::Method::Accessor>.
1526
1527=item B<< $attr->delegation_metaclass >>
1528
1529Returns the delegation metaclass name, which defaults to
1530L<Moose::Meta::Method::Delegation>.
1531
1532=back
1533
1534=head2 Additional Moose features
1535
1536These methods are not found in the superclass. They support features
1537provided by Moose.
1538
36741534 1539=over 4
1540
93a708fd 1541=item B<< $attr->does($role) >>
1542
1543This indicates whether the I<attribute itself> does the given
36741534 1544role. The role can be given as a full class name, or as a resolvable
93a708fd 1545trait name.
1546
1547Note that this checks the attribute itself, not its type constraint,
1548so it is checking the attribute's metaclass and any traits applied to
1549the attribute.
1550
1551=item B<< Moose::Meta::Class->interpolate_class_and_new($name, %options) >>
1552
1553This is an alternate constructor that handles the C<metaclass> and
1554C<traits> options.
9e93dd19 1555
93a708fd 1556Effectively, this method is a factory that finds or creates the
36741534 1557appropriate class for the given C<metaclass> and/or C<traits>.
e606ae5f 1558
93a708fd 1559Once it has the appropriate class, it will call C<< $class->new($name,
1560%options) >> on that class.
e606ae5f 1561
93a708fd 1562=item B<< $attr->clone_and_inherit_options(%options) >>
a15dff8d 1563
93a708fd 1564This method supports the C<has '+foo'> feature. It does various bits
1565of processing on the supplied C<%options> before ultimately calling
1566the C<clone> method.
6ba6d68c 1567
93a708fd 1568One of its main tasks is to make sure that the C<%options> provided
7782e1da 1569does not include the options returned by the
1570C<illegal_options_for_inheritance> method.
a15dff8d 1571
7782e1da 1572=item B<< $attr->illegal_options_for_inheritance >>
a15dff8d 1573
7782e1da 1574This returns a blacklist of options that can not be overridden in a
93a708fd 1575subclass's attribute definition.
2b86e02b 1576
93a708fd 1577This exists to allow a custom metaclass to change or add to the list
7782e1da 1578of options which can not be changed.
2b86e02b 1579
93a708fd 1580=item B<< $attr->type_constraint >>
452bac1b 1581
93a708fd 1582Returns the L<Moose::Meta::TypeConstraint> object for this attribute,
1583if it has one.
452bac1b 1584
93a708fd 1585=item B<< $attr->has_type_constraint >>
452bac1b 1586
93a708fd 1587Returns true if this attribute has a type constraint.
452bac1b 1588
93a708fd 1589=item B<< $attr->verify_against_type_constraint($value) >>
a15dff8d 1590
93a708fd 1591Given a value, this method returns true if the value is valid for the
1592attribute's type constraint. If the value is not valid, it throws an
1593error.
4b598ea3 1594
93a708fd 1595=item B<< $attr->handles >>
ca01a97b 1596
93a708fd 1597This returns the value of the C<handles> option passed to the
1598constructor.
ca01a97b 1599
93a708fd 1600=item B<< $attr->has_handles >>
ca01a97b 1601
93a708fd 1602Returns true if this attribute performs delegation.
ca01a97b 1603
93a708fd 1604=item B<< $attr->is_weak_ref >>
26fbace8 1605
93a708fd 1606Returns true if this attribute stores its value as a weak reference.
26fbace8 1607
93a708fd 1608=item B<< $attr->is_required >>
26fbace8 1609
93a708fd 1610Returns true if this attribute is required to have a value.
26fbace8 1611
93a708fd 1612=item B<< $attr->is_lazy >>
58f85113 1613
93a708fd 1614Returns true if this attribute is lazy.
26fbace8 1615
93a708fd 1616=item B<< $attr->is_lazy_build >>
ca01a97b 1617
93a708fd 1618Returns true if the C<lazy_build> option was true when passed to the
1619constructor.
4b598ea3 1620
93a708fd 1621=item B<< $attr->should_coerce >>
6ba6d68c 1622
93a708fd 1623Returns true if the C<coerce> option passed to the constructor was
1624true.
536f0b17 1625
93a708fd 1626=item B<< $attr->should_auto_deref >>
536f0b17 1627
93a708fd 1628Returns true if the C<auto_deref> option passed to the constructor was
1629true.
536f0b17 1630
93a708fd 1631=item B<< $attr->trigger >>
8c9d74e7 1632
93a708fd 1633This is the subroutine reference that was in the C<trigger> option
1634passed to the constructor, if any.
02a0fb52 1635
36741534 1636=item B<< $attr->has_trigger >>
8c9d74e7 1637
93a708fd 1638Returns true if this attribute has a trigger set.
02a0fb52 1639
93a708fd 1640=item B<< $attr->documentation >>
ddbdc0cb 1641
93a708fd 1642Returns the value that was in the C<documentation> option passed to
1643the constructor, if any.
ddbdc0cb 1644
93a708fd 1645=item B<< $attr->has_documentation >>
ddbdc0cb 1646
93a708fd 1647Returns true if this attribute has any documentation.
ddbdc0cb 1648
93a708fd 1649=item B<< $attr->applied_traits >>
88f23977 1650
93a708fd 1651This returns an array reference of all the traits which were applied
1652to this attribute. If none were applied, this returns C<undef>.
88f23977 1653
93a708fd 1654=item B<< $attr->has_applied_traits >>
88f23977 1655
93a708fd 1656Returns true if this attribute has any traits applied.
88f23977 1657
c0e30cf5 1658=back
1659
1660=head1 BUGS
1661
d4048ef3 1662See L<Moose/BUGS> for details on reporting bugs.
c0e30cf5 1663
8a7a9c53 1664=cut