File Coverage

blib/lib/Class/MOP/Mixin/HasMethods.pm
Criterion Covered Total %
statement 98 98 100.0
branch 37 38 97.3
condition 36 41 87.8
subroutine 21 21 100.0
pod 0 8 0.0
total 192 206 93.2


line stmt bran cond sub pod time code
1             package Class::MOP::Mixin::HasMethods;
2             our $VERSION = '2.2205';
3              
4 450     450   76882 use strict;
  450         1019  
  450         13550  
5 450     450   2363 use warnings;
  450         1060  
  450         13084  
6              
7 450     450   207241 use Class::MOP::Method::Meta;
  450         1282  
  450         15359  
8              
9 450     450   3145 use Scalar::Util 'blessed', 'reftype';
  450         1039  
  450         23801  
10 450     450   2851 use Sub::Util 1.40 'set_subname';
  450         9738  
  450         21155  
11              
12 450     450   2886 use parent 'Class::MOP::Mixin';
  450         1033  
  450         2198  
13              
14 10021     10021   67134 sub _meta_method_class { 'Class::MOP::Method::Meta' }
15              
16             sub _add_meta_method {
17 13044     13044   26773 my $self = shift;
18 13044         29009 my ($name) = @_;
19 13044 50       75551 my $existing_method = $self->can('find_method_by_name')
20             ? $self->find_method_by_name($name)
21             : $self->get_method($name);
22 13044 100 100     42070 return if $existing_method
23             && $existing_method->isa($self->_meta_method_class);
24 12939         44562 $self->add_method(
25             $name => $self->_meta_method_class->wrap(
26             name => $name,
27             package_name => $self->name,
28             associated_metaclass => $self,
29             )
30             );
31             }
32              
33             sub wrap_method_body {
34 29251     29251 0 90381 my ( $self, %args ) = @_;
35              
36             ( $args{body} && 'CODE' eq reftype $args{body} )
37 29251 100 66     133763 || $self->_throw_exception( CodeBlockMustBeACodeRef => instance => $self,
38             params => \%args
39             );
40 29250         231769 $self->method_metaclass->wrap(
41             package_name => $self->name,
42             %args,
43             );
44             }
45              
46             sub add_method {
47 179171     179171 0 376607 my ( $self, $method_name, $method ) = @_;
48 179171 100 100     689489 ( defined $method_name && length $method_name )
49             || $self->_throw_exception( MustDefineAMethodName => instance => $self );
50              
51 179168         473099 my $package_name = $self->name;
52              
53 179166         256213 my $body;
54 179166 100 100     973788 if ( blessed($method) && $method->isa('Class::MOP::Method') ) {
55 170326         411235 $body = $method->body;
56 170326 100       464279 if ( $method->package_name ne $package_name ) {
57 18407         49875 $method = $method->clone(
58             package_name => $package_name,
59             name => $method_name,
60             );
61             }
62              
63 170326         433044 $method->attach_to_class($self);
64             }
65             else {
66             # If a raw code reference is supplied, its method object is not created.
67             # The method object won't be created until required.
68 8840         15127 $body = $method;
69             }
70              
71 179166         1075827 $self->_method_map->{$method_name} = $method;
72              
73 179166         741232 my ($current_package, $current_name) = Class::MOP::get_code_info($body);
74              
75 179166 100 66     1721730 set_subname($package_name . '::' . $method_name, $body)
76             unless defined $current_name && $current_name !~ /^__ANON__/;
77              
78 179166         785256 $self->add_package_symbol("&$method_name", $body);
79              
80             # we added the method to the method map too, so it's still valid
81 179166         538619 $self->update_package_cache_flag;
82             }
83              
84             sub _code_is_mine {
85 53036     53036   96357 my ( $self, $code ) = @_;
86              
87 53036         192525 my ( $code_package, $code_name ) = Class::MOP::get_code_info($code);
88              
89 53036   66     350544 return ( $code_package && $code_package eq $self->name )
90             || ( $code_package eq 'constant' && $code_name eq '__ANON__' );
91             }
92              
93             sub has_method {
94 25682     25682 0 167334 my ( $self, $method_name ) = @_;
95              
96 25682 100 100     101418 ( defined $method_name && length $method_name )
97             || $self->_throw_exception( MustDefineAMethodName => instance => $self );
98              
99 25678         59876 my $method = $self->_get_maybe_raw_method($method_name);
100 25678 100       119925 return if not $method;
101              
102 1439         10774 return defined($self->_method_map->{$method_name} = $method);
103             }
104              
105             sub get_method {
106 269517     269517 0 523190 my ( $self, $method_name ) = @_;
107              
108 269517 100 100     817356 ( defined $method_name && length $method_name )
109             || $self->_throw_exception( MustDefineAMethodName => instance => $self );
110              
111 269514         514960 my $method = $self->_get_maybe_raw_method($method_name);
112 269514 100       727937 return if not $method;
113              
114 81353 100 100     444331 return $method if blessed($method) && $method->isa('Class::MOP::Method');
115              
116 29250         73312 return $self->_method_map->{$method_name} = $self->wrap_method_body(
117             body => $method,
118             name => $method_name,
119             associated_metaclass => $self,
120             );
121             }
122              
123             sub _get_maybe_raw_method {
124 295192     295192   473103 my ( $self, $method_name ) = @_;
125              
126 295192         1094833 my $map_entry = $self->_method_map->{$method_name};
127 295192 100       646861 return $map_entry if defined $map_entry;
128              
129 241635         709827 my $code = $self->get_package_symbol("&$method_name");
130              
131 241635 100 100     738964 return unless $code && $self->_code_is_mine($code);
132              
133 29235         61228 return $code;
134             }
135              
136             sub remove_method {
137 84     84 0 1352 my ( $self, $method_name ) = @_;
138              
139 84 100 100     430 ( defined $method_name && length $method_name )
140             || $self->_throw_exception( MustDefineAMethodName => instance => $self );
141              
142 81         477 my $removed_method = delete $self->_method_map->{$method_name};
143              
144 81         523 $self->remove_package_symbol("&$method_name");
145              
146 81 100 66     1066 $removed_method->detach_from_class
147             if blessed($removed_method) && $removed_method->isa('Class::MOP::Method');
148              
149             # still valid, since we just removed the method from the map
150 81         289 $self->update_package_cache_flag;
151              
152 81         258 return $removed_method;
153             }
154              
155             sub get_method_list {
156 215     215 0 4470 my $self = shift;
157              
158 215         386 return keys %{ $self->_full_method_map };
  215         687  
159             }
160              
161             sub _get_local_methods {
162 7695     7695   14535 my $self = shift;
163              
164 7695         11591 return values %{ $self->_full_method_map };
  7695         20363  
165             }
166              
167             sub _restore_metamethods_from {
168 133     133   1723 my $self = shift;
169 133         326 my ($old_meta) = @_;
170              
171 133         501 my $package_name = $self->name;
172              
173             # Check if Perl debugger is enabled
174 133         1232 my $debugger_enabled = ($^P & 0x10);
175 133         548 my $debug_method_info;
176              
177 133         537 for my $method ($old_meta->_get_local_methods) {
178 166         717 my $method_name = $method->name;
179              
180             # Track DB::sub information for this method if debugger is enabled.
181             # This contains original method filename and line numbers.
182 166         322 $debug_method_info = '';
183 166 100       955 if ($debugger_enabled) {
184 8         29 $debug_method_info = $DB::sub{$package_name . "::" . $method_name}
185             }
186              
187 166         2016 $method->_make_compatible_with($self->method_metaclass);
188 163         997 $self->add_method($method_name => $method);
189              
190             # Restore method debug information, which can be clobbered by add_method.
191             # Note that we handle this here instead of in add_method, because we
192             # only want to preserve the original debug info in cases where we are
193             # restoring a method, not overwriting a method.
194 163 100 66     921 if ($debugger_enabled && $debug_method_info) {
195 8         34 $DB::sub{$package_name . "::" . $method_name} = $debug_method_info;
196             }
197             }
198             }
199              
200 1584     1584 0 8108 sub reset_package_cache_flag { (shift)->{'_package_cache_flag'} = undef }
201             sub update_package_cache_flag {
202 179247     179247 0 288322 my $self = shift;
203             # NOTE:
204             # we can manually update the cache number
205             # since we are actually adding the method
206             # to our cache as well. This avoids us
207             # having to regenerate the method_map.
208             # - SL
209 179247         1347632 $self->{'_package_cache_flag'} = Class::MOP::check_package_cache_flag($self->name);
210             }
211              
212             sub _full_method_map {
213 7910     7910   12800 my $self = shift;
214              
215 7910         30068 my $pkg_gen = Class::MOP::check_package_cache_flag($self->name);
216              
217 7910 100 100     35881 if (($self->{_package_cache_flag_full} || -1) != $pkg_gen) {
218             # forcibly reify all method map entries
219             $self->get_method($_)
220 3424         15306 for $self->list_all_package_symbols('CODE');
221 3424         13591 $self->{_package_cache_flag_full} = $pkg_gen;
222             }
223              
224 7910         90182 return $self->_method_map;
225             }
226              
227             1;
228              
229             # ABSTRACT: Methods for metaclasses which have methods
230              
231             __END__
232              
233             =pod
234              
235             =encoding UTF-8
236              
237             =head1 NAME
238              
239             Class::MOP::Mixin::HasMethods - Methods for metaclasses which have methods
240              
241             =head1 VERSION
242              
243             version 2.2205
244              
245             =head1 DESCRIPTION
246              
247             This class implements methods for metaclasses which have methods
248             (L<Class::MOP::Class> and L<Moose::Meta::Role>). See L<Class::MOP::Class> for
249             API details.
250              
251             =head1 AUTHORS
252              
253             =over 4
254              
255             =item *
256              
257             Stevan Little <stevan@cpan.org>
258              
259             =item *
260              
261             Dave Rolsky <autarch@urth.org>
262              
263             =item *
264              
265             Jesse Luehrs <doy@cpan.org>
266              
267             =item *
268              
269             Shawn M Moore <sartak@cpan.org>
270              
271             =item *
272              
273             יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
274              
275             =item *
276              
277             Karen Etheridge <ether@cpan.org>
278              
279             =item *
280              
281             Florian Ragwitz <rafl@debian.org>
282              
283             =item *
284              
285             Hans Dieter Pearcey <hdp@cpan.org>
286              
287             =item *
288              
289             Chris Prather <chris@prather.org>
290              
291             =item *
292              
293             Matt S Trout <mstrout@cpan.org>
294              
295             =back
296              
297             =head1 COPYRIGHT AND LICENSE
298              
299             This software is copyright (c) 2006 by Infinity Interactive, Inc.
300              
301             This is free software; you can redistribute it and/or modify it under
302             the same terms as the Perl 5 programming language system itself.
303              
304             =cut