File Coverage

blib/lib/Class/MOP/Method.pm
Criterion Covered Total %
statement 62 62 100.0
branch 21 22 95.4
condition 10 11 90.9
subroutine 22 22 100.0
pod 9 9 100.0
total 124 126 98.4


line stmt bran cond sub pod time code
1             package Class::MOP::Method;
2             our $VERSION = '2.2206';
3              
4 450     450   215546 use strict;
  450         1085  
  450         13297  
5 450     450   2283 use warnings;
  450         937  
  450         13286  
6              
7 450     450   2593 use Scalar::Util 'weaken', 'reftype', 'blessed';
  450         1011  
  450         23992  
8              
9 450     450   2949 use parent 'Class::MOP::Object';
  450         1115  
  450         4541  
10              
11             # NOTE:
12             # if poked in the right way,
13             # they should act like CODE refs.
14             use overload
15 14     14   4980 '&{}' => sub { $_[0]->body },
16 170734     170734   423874 'bool' => sub { 1 },
17 154     154   18571 '""' => sub { overload::StrVal($_[0]) },
18 450     450   47984 fallback => 1;
  450         3067  
  450         5050  
19              
20             # construction
21              
22             sub wrap {
23 90304     90304 1 301325 my ( $class, @args ) = @_;
24              
25 90304 100       271822 unshift @args, 'body' if @args % 2 == 1;
26              
27 90304         330094 my %params = @args;
28 90304         156513 my $code = $params{body};
29              
30 90304 100 100     533224 if (blessed($code) && $code->isa(__PACKAGE__)) {
    100 100        
31 2         14 my $method = $code->clone;
32 2         16 delete $params{body};
33 2         25 Class::MOP::class_of($class)->rebless_instance($method, %params);
34 2         10 return $method;
35             }
36             elsif (!ref $code || 'CODE' ne reftype($code)) {
37 7         43 $class->_throw_exception( WrapTakesACodeRefToBless => params => \%params,
38             class => $class,
39             code => $code
40             );
41             }
42              
43             ($params{package_name} && $params{name})
44 90295 100 100     304642 || $class->_throw_exception( PackageNameAndNameParamsNotGivenToWrap => params => \%params,
45             class => $class,
46             code => $code
47             );
48              
49 90291         501930 my $self = $class->_new(\%params);
50              
51 90291 100       711461 weaken($self->{associated_metaclass}) if $self->{associated_metaclass};
52              
53 90291         467338 return $self;
54             }
55              
56             sub _new {
57 34717     34717   55582 my $class = shift;
58              
59 34717 100       82580 return Class::MOP::Class->initialize($class)->new_object(@_)
60             if $class ne __PACKAGE__;
61              
62 25217 50       51370 my $params = @_ == 1 ? $_[0] : {@_};
63              
64             return bless {
65             'body' => $params->{body},
66             'associated_metaclass' => $params->{associated_metaclass},
67             'package_name' => $params->{package_name},
68             'name' => $params->{name},
69             'original_method' => $params->{original_method},
70 25217         132134 } => $class;
71             }
72              
73             ## accessors
74              
75 5346     5346   19806 sub associated_metaclass { shift->{'associated_metaclass'} }
76              
77             sub attach_to_class {
78 170324     170324 1 303467 my ( $self, $class ) = @_;
79 170324         339041 $self->{associated_metaclass} = $class;
80 170324         496088 weaken($self->{associated_metaclass});
81             }
82              
83             sub detach_from_class {
84 80     80 1 176 my $self = shift;
85 80         720 delete $self->{associated_metaclass};
86             }
87              
88             sub fully_qualified_name {
89 29     29 1 12349 my $self = shift;
90 29         239 $self->package_name . '::' . $self->name;
91             }
92              
93 85     85   1695 sub original_method { (shift)->{'original_method'} }
94              
95 24554     24554   45267 sub _set_original_method { $_[0]->{'original_method'} = $_[1] }
96              
97             # It's possible that this could cause a loop if there is a circular
98             # reference in here. That shouldn't ever happen in normal
99             # circumstances, since original method only gets set when clone is
100             # called. We _could_ check for such a loop, but it'd involve some sort
101             # of package-lexical variable, and wouldn't be terribly subclassable.
102             sub original_package_name {
103 30     30 1 53 my $self = shift;
104              
105 30 100       72 $self->original_method
106             ? $self->original_method->original_package_name
107             : $self->package_name;
108             }
109              
110             sub original_name {
111 6     6 1 13 my $self = shift;
112              
113 6 100       11 $self->original_method
114             ? $self->original_method->original_name
115             : $self->name;
116             }
117              
118             sub original_fully_qualified_name {
119 13     13 1 57 my $self = shift;
120              
121 13 100       26 $self->original_method
122             ? $self->original_method->original_fully_qualified_name
123             : $self->fully_qualified_name;
124             }
125              
126             sub execute {
127 39     39 1 678 my $self = shift;
128 39         311 $self->body->(@_);
129             }
130              
131             # We used to go through use Class::MOP::Class->clone_instance to do this, but
132             # this was awfully slow. This method may be called a number of times when
133             # classes are loaded (especially during Moose role application), so it is
134             # worth optimizing. - DR
135             sub clone {
136 24554     24554 1 40702 my $self = shift;
137              
138 24554         34198 my $clone = bless { %{$self}, @_ }, blessed($self);
  24554         195924  
139 24554 100       116286 weaken($clone->{associated_metaclass}) if $clone->{associated_metaclass};
140              
141 24554         60630 $clone->_set_original_method($self);
142              
143 24554         55889 return $clone;
144             }
145              
146             sub _inline_throw_exception {
147 26043     26043   60398 my ( $self, $exception_type, $throw_args ) = @_;
148             return
149 26043   50     158389 'die Module::Runtime::use_module("Moose::Exception::'
150             . $exception_type
151             . '")->new('
152             . ( $throw_args || '' ) . ')';
153             }
154              
155             1;
156              
157             # ABSTRACT: Method Meta Object
158              
159             __END__
160              
161             =pod
162              
163             =encoding UTF-8
164              
165             =head1 NAME
166              
167             Class::MOP::Method - Method Meta Object
168              
169             =head1 VERSION
170              
171             version 2.2206
172              
173             =head1 DESCRIPTION
174              
175             The Method Protocol is very small, since methods in Perl 5 are just
176             subroutines in a specific package. We provide a very basic
177             introspection interface.
178              
179             =head1 METHODS
180              
181             =over 4
182              
183             =item B<< Class::MOP::Method->wrap($code, %options) >>
184              
185             This is the constructor. It accepts a method body in the form of
186             either a code reference or a L<Class::MOP::Method> instance, followed
187             by a hash of options.
188              
189             The options are:
190              
191             =over 8
192              
193             =item * name
194              
195             The method name (without a package name). This is required if C<$code>
196             is a coderef.
197              
198             =item * package_name
199              
200             The package name for the method. This is required if C<$code> is a
201             coderef.
202              
203             =item * associated_metaclass
204              
205             An optional L<Class::MOP::Class> object. This is the metaclass for the
206             method's class.
207              
208             =back
209              
210             =item B<< $metamethod->clone(%params) >>
211              
212             This makes a shallow clone of the method object. In particular,
213             subroutine reference itself is shared between all clones of a given
214             method.
215              
216             When a method is cloned, the original method object will be available
217             by calling C<original_method> on the clone.
218              
219             =item B<< $metamethod->body >>
220              
221             This returns a reference to the method's subroutine.
222              
223             =item B<< $metamethod->name >>
224              
225             This returns the method's name.
226              
227             =item B<< $metamethod->package_name >>
228              
229             This returns the method's package name.
230              
231             =item B<< $metamethod->fully_qualified_name >>
232              
233             This returns the method's fully qualified name (package name and
234             method name).
235              
236             =item B<< $metamethod->associated_metaclass >>
237              
238             This returns the L<Class::MOP::Class> object for the method, if one
239             exists.
240              
241             =item B<< $metamethod->original_method >>
242              
243             If this method object was created as a clone of some other method
244             object, this returns the object that was cloned.
245              
246             =item B<< $metamethod->original_name >>
247              
248             This returns the method's original name, wherever it was first
249             defined.
250              
251             If this method is a clone of a clone (of a clone, etc.), this method
252             returns the name from the I<first> method in the chain of clones.
253              
254             =item B<< $metamethod->original_package_name >>
255              
256             This returns the method's original package name, wherever it was first
257             defined.
258              
259             If this method is a clone of a clone (of a clone, etc.), this method
260             returns the package name from the I<first> method in the chain of
261             clones.
262              
263             =item B<< $metamethod->original_fully_qualified_name >>
264              
265             This returns the method's original fully qualified name, wherever it
266             was first defined.
267              
268             If this method is a clone of a clone (of a clone, etc.), this method
269             returns the fully qualified name from the I<first> method in the chain
270             of clones.
271              
272             =item B<< $metamethod->is_stub >>
273              
274             Returns true if the method is just a stub:
275              
276             sub foo;
277              
278             =item B<< $metamethod->attach_to_class($metaclass) >>
279              
280             Given a L<Class::MOP::Class> object, this method sets the associated
281             metaclass for the method. This will overwrite any existing associated
282             metaclass.
283              
284             =item B<< $metamethod->detach_from_class >>
285              
286             Removes any associated metaclass object for the method.
287              
288             =item B<< $metamethod->execute(...) >>
289              
290             This executes the method. Any arguments provided will be passed on to
291             the method itself.
292              
293             =item B<< Class::MOP::Method->meta >>
294              
295             This will return a L<Class::MOP::Class> instance for this class.
296              
297             It should also be noted that L<Class::MOP> will actually bootstrap
298             this module by installing a number of attribute meta-objects into its
299             metaclass.
300              
301             =back
302              
303             =head1 AUTHORS
304              
305             =over 4
306              
307             =item *
308              
309             Stevan Little <stevan@cpan.org>
310              
311             =item *
312              
313             Dave Rolsky <autarch@urth.org>
314              
315             =item *
316              
317             Jesse Luehrs <doy@cpan.org>
318              
319             =item *
320              
321             Shawn M Moore <sartak@cpan.org>
322              
323             =item *
324              
325             יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
326              
327             =item *
328              
329             Karen Etheridge <ether@cpan.org>
330              
331             =item *
332              
333             Florian Ragwitz <rafl@debian.org>
334              
335             =item *
336              
337             Hans Dieter Pearcey <hdp@cpan.org>
338              
339             =item *
340              
341             Chris Prather <chris@prather.org>
342              
343             =item *
344              
345             Matt S Trout <mstrout@cpan.org>
346              
347             =back
348              
349             =head1 COPYRIGHT AND LICENSE
350              
351             This software is copyright (c) 2006 by Infinity Interactive, Inc.
352              
353             This is free software; you can redistribute it and/or modify it under
354             the same terms as the Perl 5 programming language system itself.
355              
356             =cut