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