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