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