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