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