2 package Moose::Meta::Method::Accessor;
10 $VERSION = eval $VERSION;
11 our $AUTHORITY = 'cpan:STEVAN';
13 use base 'Moose::Meta::Method',
14 'Class::MOP::Method::Accessor';
18 return $self->associated_attribute
19 if ref($self) && defined($self->associated_attribute);
20 return $self->SUPER::_error_thrower;
27 $self->SUPER::_compile_code(@args);
31 'Could not create writer for '
32 . "'" . $self->associated_attribute->name . "' "
39 sub _eval_environment {
42 my $attr = $self->associated_attribute;
43 my $type_constraint_obj = $attr->type_constraint;
48 '$type_constraint_obj' => \$type_constraint_obj,
49 '$type_constraint' => \(
51 ? $type_constraint_obj->_compiled_type_constraint
57 sub _generate_accessor_method_inline {
61 my $slot_access = $self->_get_value($inv);
62 my $value = $self->_value_needs_copy ? '$val' : '$_[1]';
65 $self->_compile_code([
67 $self->_inline_pre_body(@_),
68 'if (scalar(@_) >= 2) {',
69 $self->_inline_copy_value($value),
70 $self->_inline_check_required,
71 $self->_inline_tc_code($value),
72 $self->_inline_get_old_value_for_trigger($inv, $old),
73 $self->_inline_store_value($inv, $value),
74 $self->_inline_trigger($inv, $value, $old),
76 $self->_inline_check_lazy($inv),
77 $self->_inline_post_body(@_),
78 $self->_inline_return_auto_deref($slot_access),
83 sub _generate_writer_method_inline {
87 my $value = $self->_value_needs_copy ? '$val' : '$_[1]';
90 $self->_compile_code([
92 $self->_inline_pre_body(@_),
93 $self->_inline_copy_value($value),
94 $self->_inline_check_required,
95 $self->_inline_tc_code($value),
96 $self->_inline_get_old_value_for_trigger($inv, $old),
97 $self->_inline_store_value($inv, $value),
98 $self->_inline_post_body(@_),
99 $self->_inline_trigger($inv, $value, $old),
104 sub _generate_reader_method_inline {
108 my $slot_access = $self->_get_value($inv);
110 $self->_compile_code([
112 $self->_inline_pre_body(@_),
114 $self->_inline_throw_error(
115 '"Cannot assign a value to a read-only accessor"',
119 $self->_inline_check_lazy($inv),
120 $self->_inline_post_body(@_),
121 $self->_inline_return_auto_deref($slot_access),
126 sub _inline_copy_value {
130 return unless $self->_value_needs_copy;
131 return 'my ' . $value . ' = $_[1];'
134 sub _value_needs_copy {
136 return $self->associated_attribute->should_coerce;
139 sub _instance_is_inlinable {
141 return $self->associated_attribute->associated_class->instance_metaclass->is_inlinable;
144 sub _generate_reader_method {
146 $self->_instance_is_inlinable ? $self->_generate_reader_method_inline(@_)
147 : $self->SUPER::_generate_reader_method(@_);
150 sub _generate_writer_method {
152 $self->_instance_is_inlinable ? $self->_generate_writer_method_inline(@_)
153 : $self->SUPER::_generate_writer_method(@_);
156 sub _generate_accessor_method {
158 $self->_instance_is_inlinable ? $self->_generate_accessor_method_inline(@_)
159 : $self->SUPER::_generate_accessor_method(@_);
162 sub _generate_predicate_method {
164 $self->_instance_is_inlinable ? $self->_generate_predicate_method_inline(@_)
165 : $self->SUPER::_generate_predicate_method(@_);
168 sub _generate_clearer_method {
170 $self->_instance_is_inlinable ? $self->_generate_clearer_method_inline(@_)
171 : $self->SUPER::_generate_clearer_method(@_);
174 sub _inline_pre_body { return }
175 sub _inline_post_body { return }
177 sub _inline_tc_code {
180 $self->_inline_check_coercion(@_),
181 $self->_inline_check_constraint(@_),
185 sub _inline_check_constraint {
189 my $attr = $self->associated_attribute;
190 return unless $attr->has_type_constraint;
192 my $attr_name = quotemeta($attr->name);
195 'if (!$type_constraint->(' . $value . ')) {',
196 $self->_inline_throw_error(
197 '"Attribute (' . $attr_name . ') does not pass the type '
198 . 'constraint because: " . '
199 . '$type_constraint_obj->get_message(' . $value . ')',
206 sub _inline_check_coercion {
210 my $attr = $self->associated_attribute;
211 return unless $attr->should_coerce && $attr->type_constraint->has_coercion;
213 return $value . ' = $type_constraint_obj->coerce(' . $value . ');';
216 sub _inline_check_required {
219 my $attr = $self->associated_attribute;
220 return unless $attr->is_required;
222 my $attr_name = quotemeta($attr->name);
226 $self->_inline_throw_error(
227 '"Attribute (' . $attr_name . ') is required, so cannot '
228 . 'be set to undef"' # defined $_[1] is not good enough
234 sub _inline_check_lazy {
236 my ($instance, $default) = @_;
238 my $attr = $self->associated_attribute;
239 return unless $attr->is_lazy;
241 my $slot_exists = $self->_has_value($instance);
244 'if (!' . $slot_exists . ') {',
245 $self->_inline_init_from_default($instance, '$default', 'lazy'),
250 sub _inline_init_from_default {
252 my ($instance, $default, $for_lazy) = @_;
254 my $attr = $self->associated_attribute;
255 # XXX: should this throw an error instead?
256 return $self->_inline_init_slot($attr, $instance, 'undef')
257 unless $attr->has_default || $attr->has_builder;
260 $self->_inline_generate_default($instance, $default),
261 # intentionally not using _inline_tc_code, since that can be overridden
262 # to do things like possibly only do member tc checks, which isn't
263 # appropriate for checking the result of a default
264 $attr->has_type_constraint
265 ? ($self->_inline_check_coercion($default, $for_lazy),
266 $self->_inline_check_constraint($default, $for_lazy))
268 $self->_inline_init_slot($attr, $instance, $default),
272 sub _inline_generate_default {
274 my ($instance, $default) = @_;
276 my $attr = $self->associated_attribute;
278 if ($attr->has_default) {
279 return 'my ' . $default . ' = $attr->default(' . $instance . ');';
281 elsif ($attr->has_builder) {
283 'my ' . $default . ';',
284 'if (my $builder = ' . $instance . '->can($attr->builder)) {',
285 $default . ' = ' . $instance . '->$builder;',
288 'my $class = ref(' . $instance . ') || ' . $instance . ';',
289 'my $builder_name = $attr->builder;',
290 'my $attr_name = $attr->name;',
291 $self->_inline_throw_error(
292 '"$class does not support builder method '
293 . '\'$builder_name\' for attribute \'$attr_name\'"'
300 "Can't generate a default for " . $attr->name
301 . " since no default or builder was specified"
306 sub _inline_init_slot {
308 my ($attr, $inv, $value) = @_;
310 if ($attr->has_initializer) {
311 return '$attr->set_initial_value(' . $inv . ', ' . $value . ');';
314 return $self->_inline_store_value($inv, $value);
318 sub _inline_store_value {
320 my ($inv, $value) = @_;
322 return $self->_store_value($inv, $value) . ';';
325 sub _inline_get_old_value_for_trigger {
327 my ($instance, $old) = @_;
329 my $attr = $self->associated_attribute;
330 return unless $attr->has_trigger;
333 'my ' . $old . ' = ' . $self->_has_value($instance),
334 '? ' . $self->_get_value($instance),
339 sub _inline_trigger {
341 my ($instance, $value, $old) = @_;
343 my $attr = $self->associated_attribute;
344 return unless $attr->has_trigger;
346 return '$attr->trigger->(' . $instance . ', ' . $value . ', ' . $old . ');';
349 sub _inline_return_auto_deref {
352 return 'return ' . $self->_auto_deref(@_) . ';';
359 my ($instance, $value) = @_;
361 return $self->associated_attribute->inline_set($instance, $value) . ';';
365 my ($self, $instance) = @_;
367 return $self->associated_attribute->inline_get($instance);
371 my ($self, $instance) = @_;
373 return $self->associated_attribute->inline_has($instance);
378 my ($ref_value) = @_;
380 my $attr = $self->associated_attribute;
381 return $ref_value unless $attr->should_auto_deref;
383 my $type_constraint = $attr->type_constraint;
386 if ($type_constraint->is_a_type_of('ArrayRef')) {
389 elsif ($type_constraint->is_a_type_of('HashRef')) {
394 'Can not auto de-reference the type constraint \''
395 . $type_constraint->name
397 type_constraint => $type_constraint,
402 . '? ' . $sigil . '{ (' . $ref_value . ') || return } '
403 . ': (' . $ref_value . ')';
414 Moose::Meta::Method::Accessor - A Moose Method metaclass for accessors
418 This class is a subclass of L<Class::MOP::Method::Accessor> that
419 provides additional Moose-specific functionality, all of which is
422 To understand this class, you should read the the
423 L<Class::MOP::Method::Accessor> documentation.
427 See L<Moose/BUGS> for details on reporting bugs.
431 Stevan Little E<lt>stevan@iinteractive.comE<gt>
433 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
435 =head1 COPYRIGHT AND LICENSE
437 Copyright 2006-2010 by Infinity Interactive, Inc.
439 L<http://www.iinteractive.com>
441 This library is free software; you can redistribute it and/or modify
442 it under the same terms as Perl itself.