Change clearers to return true for compatibility
[gitmo/Class-MOP.git] / lib / Class / MOP / Method / Accessor.pm
CommitLineData
ba38bf08 1
2package Class::MOP::Method::Accessor;
3
4use strict;
5use warnings;
6
7use Carp 'confess';
8use Scalar::Util 'blessed', 'weaken';
9
4b18c1b3 10our $VERSION = '0.91';
d519662a 11$VERSION = eval $VERSION;
ba38bf08 12our $AUTHORITY = 'cpan:STEVAN';
13
565f0cbb 14use base 'Class::MOP::Method::Generated';
ba38bf08 15
ba38bf08 16sub new {
17 my $class = shift;
18 my %options = @_;
8d2d4c67 19
ba38bf08 20 (exists $options{attribute})
21 || confess "You must supply an attribute to construct with";
8d2d4c67 22
ba38bf08 23 (exists $options{accessor_type})
8d2d4c67 24 || confess "You must supply an accessor_type to construct with";
25
ba38bf08 26 (blessed($options{attribute}) && $options{attribute}->isa('Class::MOP::Attribute'))
8d2d4c67 27 || confess "You must supply an attribute which is a 'Class::MOP::Attribute' instance";
28
b38f3848 29 ($options{package_name} && $options{name})
32202ce2 30 || confess "You must supply the package_name and name parameters $Class::MOP::Method::UPGRADE_ERROR_TEXT";
b38f3848 31
0bfc85b8 32 my $self = $class->_new(\%options);
8d2d4c67 33
34 # we don't want this creating
35 # a cycle in the code, if not
ba38bf08 36 # needed
8683db0e 37 weaken($self->{'attribute'});
8d2d4c67 38
e9497117 39 $self->_initialize_body;
8d2d4c67 40
ba38bf08 41 return $self;
42}
43
a9e38dc7 44sub _new {
0bfc85b8 45 my $class = shift;
a9e38dc7 46
ec9e38e5 47 return Class::MOP::Class->initialize($class)->new_object(@_)
812d58f9 48 if $class ne __PACKAGE__;
a9e38dc7 49
ec9e38e5 50 my $params = @_ == 1 ? $_[0] : {@_};
51
52 return bless {
53 # inherited from Class::MOP::Method
54 body => $params->{body},
55 associated_metaclass => $params->{associated_metaclass},
56 package_name => $params->{package_name},
57 name => $params->{name},
58 original_method => $params->{original_method},
59
60 # inherit from Class::MOP::Generated
61 is_inline => $params->{is_inline} || 0,
62 definition_context => $params->{definition_context},
63
64 # defined in this class
65 attribute => $params->{attribute},
66 accessor_type => $params->{accessor_type},
67 } => $class;
a9e38dc7 68}
69
ba38bf08 70## accessors
71
8683db0e 72sub associated_attribute { (shift)->{'attribute'} }
73sub accessor_type { (shift)->{'accessor_type'} }
ba38bf08 74
8d2d4c67 75## factory
ba38bf08 76
565f0cbb 77sub initialize_body {
c7e28c19 78 Carp::cluck('The initialize_body method has been made private.'
79 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 80 shift->_initialize_body;
e9497117 81}
82
83sub _initialize_body {
ba38bf08 84 my $self = shift;
8d2d4c67 85
ba38bf08 86 my $method_name = join "_" => (
afc92ac6 87 '_generate',
8d2d4c67 88 $self->accessor_type,
ba38bf08 89 'method',
d90b42a6 90 ($self->is_inline ? 'inline' : ())
ba38bf08 91 );
8d2d4c67 92
1be5f78f 93 $self->{'body'} = $self->$method_name();
ba38bf08 94}
95
96## generators
97
98sub generate_accessor_method {
c7e28c19 99 Carp::cluck('The generate_accessor_method method has been made private.'
100 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 101 shift->_generate_accessor_method;
afc92ac6 102}
103
104sub _generate_accessor_method {
8d2d4c67 105 my $attr = (shift)->associated_attribute;
ba38bf08 106 return sub {
107 $attr->set_value($_[0], $_[1]) if scalar(@_) == 2;
108 $attr->get_value($_[0]);
109 };
110}
111
112sub generate_reader_method {
c7e28c19 113 Carp::cluck('The generate_reader_method method has been made private.'
114 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 115 shift->_generate_reader_method;
afc92ac6 116}
117
118sub _generate_reader_method {
8d2d4c67 119 my $attr = (shift)->associated_attribute;
120 return sub {
ba38bf08 121 confess "Cannot assign a value to a read-only accessor" if @_ > 1;
122 $attr->get_value($_[0]);
8d2d4c67 123 };
ba38bf08 124}
125
126sub generate_writer_method {
c7e28c19 127 Carp::cluck('The generate_writer_method method has been made private.'
128 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 129 shift->_generate_writer_method;
afc92ac6 130}
131
132sub _generate_writer_method {
8d2d4c67 133 my $attr = (shift)->associated_attribute;
ba38bf08 134 return sub {
135 $attr->set_value($_[0], $_[1]);
136 };
137}
138
139sub generate_predicate_method {
c7e28c19 140 Carp::cluck('The generate_predicate_method method has been made private.'
141 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 142 shift->_generate_predicate_method;
afc92ac6 143}
144
145sub _generate_predicate_method {
8d2d4c67 146 my $attr = (shift)->associated_attribute;
147 return sub {
3545c727 148 $attr->has_value($_[0])
ba38bf08 149 };
150}
151
152sub generate_clearer_method {
c7e28c19 153 Carp::cluck('The generate_clearer_method method has been made private.'
154 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 155 shift->_generate_clearer_method;
afc92ac6 156}
157
158sub _generate_clearer_method {
8d2d4c67 159 my $attr = (shift)->associated_attribute;
160 return sub {
3545c727 161 $attr->clear_value($_[0])
ba38bf08 162 };
163}
164
165## Inline methods
166
7813a0c5 167
168sub _inline_call_trigger {
169 my ($self, $attr, $instance, $value) = @_;
170 return '' unless $attr->has_trigger;
171 return defined($value)
172 ? sprintf('$attr->call_trigger(%s, %s);', $instance, $value)
173 : sprintf('$attr->call_trigger(%s);', $instance);
174}
175
176
ba38bf08 177sub generate_accessor_method_inline {
c7e28c19 178 Carp::cluck('The generate_accessor_method_inline method has been made private.'
179 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 180 shift->_generate_accessor_method_inline;
afc92ac6 181}
182
183sub _generate_accessor_method_inline {
7f8de9b4 184 my $self = shift;
185 my $attr = $self->associated_attribute;
ba38bf08 186 my $attr_name = $attr->name;
187 my $meta_instance = $attr->associated_class->instance_metaclass;
188
e24b19fb 189 my ( $code, $e ) = $self->_eval_closure(
7813a0c5 190 {'$attr' => \$attr},
7f8de9b4 191 'sub {'
7813a0c5 192 . 'if(scalar(@_) == 2){'
193 . 'my $value = ' . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]') . ';'
194 . $self->_inline_call_trigger($attr, '$_[0]', '$value')
195 . '}'
a71a4ccb 196 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
7f8de9b4 197 . '}'
198 );
e24b19fb 199 confess "Could not generate inline accessor because : $e" if $e;
a6eef5a3 200
201 return $code;
ba38bf08 202}
203
204sub generate_reader_method_inline {
c7e28c19 205 Carp::cluck('The generate_reader_method_inline method has been made private.'
206 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 207 shift->_generate_reader_method_inline;
afc92ac6 208}
209
210sub _generate_reader_method_inline {
7f8de9b4 211 my $self = shift;
212 my $attr = $self->associated_attribute;
ba38bf08 213 my $attr_name = $attr->name;
214 my $meta_instance = $attr->associated_class->instance_metaclass;
215
e24b19fb 216 my ( $code, $e ) = $self->_eval_closure(
0c6f3280 217 {},
7f8de9b4 218 'sub {'
ba38bf08 219 . 'confess "Cannot assign a value to a read-only accessor" if @_ > 1;'
e9a19694 220 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
7f8de9b4 221 . '}'
222 );
e24b19fb 223 confess "Could not generate inline reader because : $e" if $e;
a6eef5a3 224
225 return $code;
ba38bf08 226}
227
228sub generate_writer_method_inline {
c7e28c19 229 Carp::cluck('The generate_writer_method_inline method has been made private.'
230 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 231 shift->_generate_writer_method_inline;
afc92ac6 232}
233
234sub _generate_writer_method_inline {
7f8de9b4 235 my $self = shift;
236 my $attr = $self->associated_attribute;
ba38bf08 237 my $attr_name = $attr->name;
238 my $meta_instance = $attr->associated_class->instance_metaclass;
239
e24b19fb 240 my ( $code, $e ) = $self->_eval_closure(
7813a0c5 241 {'$attr' => \$attr},
7f8de9b4 242 'sub {'
7813a0c5 243 . 'my $value = ' . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]') . ';'
244 . $self->_inline_call_trigger($attr, '$_[0]', '$value')
245 . 'return $value;'
7f8de9b4 246 . '}'
247 );
e24b19fb 248 confess "Could not generate inline writer because : $e" if $e;
a6eef5a3 249
250 return $code;
ba38bf08 251}
252
ba38bf08 253sub generate_predicate_method_inline {
c7e28c19 254 Carp::cluck('The generate_predicate_method_inline method has been made private.'
255 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 256 shift->_generate_predicate_method_inline;
afc92ac6 257}
258
259sub _generate_predicate_method_inline {
7f8de9b4 260 my $self = shift;
261 my $attr = $self->associated_attribute;
ba38bf08 262 my $attr_name = $attr->name;
263 my $meta_instance = $attr->associated_class->instance_metaclass;
264
e24b19fb 265 my ( $code, $e ) = $self->_eval_closure(
0c6f3280 266 {},
7f8de9b4 267 'sub {'
e9a19694 268 . $meta_instance->inline_is_slot_initialized('$_[0]', $attr_name)
7f8de9b4 269 . '}'
270 );
e24b19fb 271 confess "Could not generate inline predicate because : $e" if $e;
a6eef5a3 272
273 return $code;
ba38bf08 274}
275
276sub generate_clearer_method_inline {
c7e28c19 277 Carp::cluck('The generate_clearer_method_inline method has been made private.'
278 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 279 shift->_generate_clearer_method_inline;
afc92ac6 280}
281
282sub _generate_clearer_method_inline {
7f8de9b4 283 my $self = shift;
284 my $attr = $self->associated_attribute;
ba38bf08 285 my $attr_name = $attr->name;
286 my $meta_instance = $attr->associated_class->instance_metaclass;
287
e24b19fb 288 my ( $code, $e ) = $self->_eval_closure(
7813a0c5 289 {'$attr' => \$attr},
7f8de9b4 290 'sub {'
7813a0c5 291 . $meta_instance->inline_deinitialize_slot('$_[0]', $attr_name) . ';'
292 . $self->_inline_call_trigger($attr, '$_[0]')
7771c1b3 293 . 'return 1;'
7813a0c5 294 . '}',
7f8de9b4 295 );
e24b19fb 296 confess "Could not generate inline clearer because : $e" if $e;
a6eef5a3 297
298 return $code;
ba38bf08 299}
300
3011;
302
303__END__
304
305=pod
306
8d2d4c67 307=head1 NAME
ba38bf08 308
309Class::MOP::Method::Accessor - Method Meta Object for accessors
310
311=head1 SYNOPSIS
312
96e38ba6 313 use Class::MOP::Method::Accessor;
314
315 my $reader = Class::MOP::Method::Accessor->new(
316 attribute => $attribute,
317 is_inline => 1,
318 accessor_type => 'reader',
319 );
8d2d4c67 320
b7045e66 321 $reader->body->execute($instance); # call the reader method
ba38bf08 322
323=head1 DESCRIPTION
324
1385ad9d 325This is a subclass of <Class::MOP::Method> which is used by
326C<Class::MOP::Attribute> to generate accessor code. It handles
327generation of readers, writers, predicates and clearers. For each type
328of method, it can either create a subroutine reference, or actually
329inline code by generating a string and C<eval>'ing it.
96e38ba6 330
ba38bf08 331=head1 METHODS
332
333=over 4
334
1385ad9d 335=item B<< Class::MOP::Method::Accessor->new(%options) >>
ba38bf08 336
1385ad9d 337This returns a new C<Class::MOP::Method::Accessor> based on the
338C<%options> provided.
96e38ba6 339
340=over 4
341
9258c369 342=item * attribute
96e38ba6 343
1385ad9d 344This is the C<Class::MOP::Attribute> for which accessors are being
345generated. This option is required.
96e38ba6 346
9258c369 347=item * accessor_type
96e38ba6 348
1385ad9d 349This is a string which should be one of "reader", "writer",
350"accessor", "predicate", or "clearer". This is the type of method
351being generated. This option is required.
96e38ba6 352
9258c369 353=item * is_inline
96e38ba6 354
1385ad9d 355This indicates whether or not the accessor should be inlined. This
cb8d08c6 356defaults to false.
96e38ba6 357
9258c369 358=item * name
359
360The method name (without a package name). This is required.
361
362=item * package_name
363
364The package name for the method. This is required.
365
96e38ba6 366=back
ba38bf08 367
1385ad9d 368=item B<< $metamethod->accessor_type >>
ba38bf08 369
1385ad9d 370Returns the accessor type which was passed to C<new>.
96e38ba6 371
1385ad9d 372=item B<< $metamethod->is_inline >>
ba38bf08 373
1385ad9d 374Returns a boolean indicating whether or not the accessor is inlined.
96e38ba6 375
1385ad9d 376=item B<< $metamethod->associated_attribute >>
ba38bf08 377
1385ad9d 378This returns the L<Class::MOP::Attribute> object which was passed to
379C<new>.
96e38ba6 380
1385ad9d 381=item B<< $metamethod->body >>
96e38ba6 382
1385ad9d 383The method itself is I<generated> when the accessor object is
384constructed.
ba38bf08 385
386=back
387
388=head1 AUTHORS
389
390Stevan Little E<lt>stevan@iinteractive.comE<gt>
391
ba38bf08 392=head1 COPYRIGHT AND LICENSE
393
070bb6c9 394Copyright 2006-2009 by Infinity Interactive, Inc.
ba38bf08 395
396L<http://www.iinteractive.com>
397
398This library is free software; you can redistribute it and/or modify
8d2d4c67 399it under the same terms as Perl itself.
ba38bf08 400
401=cut
402