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