line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::MOP::Mixin::HasMethods; |
2
|
|
|
|
|
|
|
our $VERSION = '2.2203'; |
3
|
|
|
|
|
|
|
|
4
|
462
|
|
|
462
|
|
94084
|
use strict; |
|
462
|
|
|
|
|
910
|
|
|
462
|
|
|
|
|
12264
|
|
5
|
462
|
|
|
462
|
|
2033
|
use warnings; |
|
462
|
|
|
|
|
804
|
|
|
462
|
|
|
|
|
9979
|
|
6
|
|
|
|
|
|
|
|
7
|
462
|
|
|
462
|
|
179945
|
use Class::MOP::Method::Meta; |
|
462
|
|
|
|
|
1074
|
|
|
462
|
|
|
|
|
14003
|
|
8
|
|
|
|
|
|
|
|
9
|
462
|
|
|
462
|
|
2746
|
use Scalar::Util 'blessed', 'reftype'; |
|
462
|
|
|
|
|
914
|
|
|
462
|
|
|
|
|
21003
|
|
10
|
462
|
|
|
462
|
|
2366
|
use Sub::Util 1.40 'set_subname'; |
|
462
|
|
|
|
|
8492
|
|
|
462
|
|
|
|
|
21575
|
|
11
|
|
|
|
|
|
|
|
12
|
462
|
|
|
462
|
|
2599
|
use parent 'Class::MOP::Mixin'; |
|
462
|
|
|
|
|
855
|
|
|
462
|
|
|
|
|
1975
|
|
13
|
|
|
|
|
|
|
|
14
|
10296
|
|
|
10296
|
|
59660
|
sub _meta_method_class { 'Class::MOP::Method::Meta' } |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub _add_meta_method { |
17
|
13363
|
|
|
13363
|
|
23640
|
my $self = shift; |
18
|
13363
|
|
|
|
|
25107
|
my ($name) = @_; |
19
|
13363
|
50
|
|
|
|
71368
|
my $existing_method = $self->can('find_method_by_name') |
20
|
|
|
|
|
|
|
? $self->find_method_by_name($name) |
21
|
|
|
|
|
|
|
: $self->get_method($name); |
22
|
13363
|
100
|
100
|
|
|
35494
|
return if $existing_method |
23
|
|
|
|
|
|
|
&& $existing_method->isa($self->_meta_method_class); |
24
|
13256
|
|
|
|
|
37002
|
$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
|
29959
|
|
|
29959
|
0
|
80273
|
my ( $self, %args ) = @_; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
( $args{body} && 'CODE' eq reftype $args{body} ) |
37
|
29959
|
100
|
66
|
|
|
116742
|
|| $self->_throw_exception( CodeBlockMustBeACodeRef => instance => $self, |
38
|
|
|
|
|
|
|
params => \%args |
39
|
|
|
|
|
|
|
); |
40
|
29958
|
|
|
|
|
205542
|
$self->method_metaclass->wrap( |
41
|
|
|
|
|
|
|
package_name => $self->name, |
42
|
|
|
|
|
|
|
%args, |
43
|
|
|
|
|
|
|
); |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub add_method { |
47
|
183632
|
|
|
183632
|
0
|
335902
|
my ( $self, $method_name, $method ) = @_; |
48
|
183632
|
100
|
100
|
|
|
618150
|
( defined $method_name && length $method_name ) |
49
|
|
|
|
|
|
|
|| $self->_throw_exception( MustDefineAMethodName => instance => $self ); |
50
|
|
|
|
|
|
|
|
51
|
183629
|
|
|
|
|
426969
|
my $package_name = $self->name; |
52
|
|
|
|
|
|
|
|
53
|
183627
|
|
|
|
|
236095
|
my $body; |
54
|
183627
|
100
|
100
|
|
|
878179
|
if ( blessed($method) && $method->isa('Class::MOP::Method') ) { |
55
|
174533
|
|
|
|
|
367362
|
$body = $method->body; |
56
|
174533
|
100
|
|
|
|
421362
|
if ( $method->package_name ne $package_name ) { |
57
|
18541
|
|
|
|
|
44941
|
$method = $method->clone( |
58
|
|
|
|
|
|
|
package_name => $package_name, |
59
|
|
|
|
|
|
|
name => $method_name, |
60
|
|
|
|
|
|
|
); |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
174533
|
|
|
|
|
392477
|
$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
|
9094
|
|
|
|
|
12959
|
$body = $method; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
183627
|
|
|
|
|
927541
|
$self->_method_map->{$method_name} = $method; |
72
|
|
|
|
|
|
|
|
73
|
183627
|
|
|
|
|
653283
|
my ($current_package, $current_name) = Class::MOP::get_code_info($body); |
74
|
|
|
|
|
|
|
|
75
|
183627
|
100
|
66
|
|
|
1528631
|
set_subname($package_name . '::' . $method_name, $body) |
76
|
|
|
|
|
|
|
unless defined $current_name && $current_name !~ /^__ANON__/; |
77
|
|
|
|
|
|
|
|
78
|
183627
|
|
|
|
|
700858
|
$self->add_package_symbol("&$method_name", $body); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# we added the method to the method map too, so it's still valid |
81
|
183627
|
|
|
|
|
480032
|
$self->update_package_cache_flag; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub _code_is_mine { |
85
|
54134
|
|
|
54134
|
|
87397
|
my ( $self, $code ) = @_; |
86
|
|
|
|
|
|
|
|
87
|
54134
|
|
|
|
|
161074
|
my ( $code_package, $code_name ) = Class::MOP::get_code_info($code); |
88
|
|
|
|
|
|
|
|
89
|
54134
|
|
66
|
|
|
311299
|
return ( $code_package && $code_package eq $self->name ) |
90
|
|
|
|
|
|
|
|| ( $code_package eq 'constant' && $code_name eq '__ANON__' ); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub has_method { |
94
|
26229
|
|
|
26229
|
0
|
174566
|
my ( $self, $method_name ) = @_; |
95
|
|
|
|
|
|
|
|
96
|
26229
|
100
|
100
|
|
|
90547
|
( defined $method_name && length $method_name ) |
97
|
|
|
|
|
|
|
|| $self->_throw_exception( MustDefineAMethodName => instance => $self ); |
98
|
|
|
|
|
|
|
|
99
|
26225
|
|
|
|
|
53381
|
my $method = $self->_get_maybe_raw_method($method_name); |
100
|
26225
|
100
|
|
|
|
100841
|
return if not $method; |
101
|
|
|
|
|
|
|
|
102
|
1470
|
|
|
|
|
8197
|
return defined($self->_method_map->{$method_name} = $method); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub get_method { |
106
|
275521
|
|
|
275521
|
0
|
465476
|
my ( $self, $method_name ) = @_; |
107
|
|
|
|
|
|
|
|
108
|
275521
|
100
|
100
|
|
|
725330
|
( defined $method_name && length $method_name ) |
109
|
|
|
|
|
|
|
|| $self->_throw_exception( MustDefineAMethodName => instance => $self ); |
110
|
|
|
|
|
|
|
|
111
|
275518
|
|
|
|
|
458969
|
my $method = $self->_get_maybe_raw_method($method_name); |
112
|
275518
|
100
|
|
|
|
645219
|
return if not $method; |
113
|
|
|
|
|
|
|
|
114
|
83110
|
100
|
100
|
|
|
392693
|
return $method if blessed($method) && $method->isa('Class::MOP::Method'); |
115
|
|
|
|
|
|
|
|
116
|
29958
|
|
|
|
|
64448
|
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
|
301743
|
|
|
301743
|
|
420549
|
my ( $self, $method_name ) = @_; |
125
|
|
|
|
|
|
|
|
126
|
301743
|
|
|
|
|
953152
|
my $map_entry = $self->_method_map->{$method_name}; |
127
|
301743
|
100
|
|
|
|
570083
|
return $map_entry if defined $map_entry; |
128
|
|
|
|
|
|
|
|
129
|
247107
|
|
|
|
|
627025
|
my $code = $self->get_package_symbol("&$method_name"); |
130
|
|
|
|
|
|
|
|
131
|
247107
|
100
|
100
|
|
|
642245
|
return unless $code && $self->_code_is_mine($code); |
132
|
|
|
|
|
|
|
|
133
|
29944
|
|
|
|
|
53690
|
return $code; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub remove_method { |
137
|
86
|
|
|
86
|
0
|
1274
|
my ( $self, $method_name ) = @_; |
138
|
|
|
|
|
|
|
|
139
|
86
|
100
|
100
|
|
|
416
|
( defined $method_name && length $method_name ) |
140
|
|
|
|
|
|
|
|| $self->_throw_exception( MustDefineAMethodName => instance => $self ); |
141
|
|
|
|
|
|
|
|
142
|
83
|
|
|
|
|
610
|
my $removed_method = delete $self->_method_map->{$method_name}; |
143
|
|
|
|
|
|
|
|
144
|
83
|
|
|
|
|
444
|
$self->remove_package_symbol("&$method_name"); |
145
|
|
|
|
|
|
|
|
146
|
83
|
100
|
66
|
|
|
880
|
$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
|
83
|
|
|
|
|
246
|
$self->update_package_cache_flag; |
151
|
|
|
|
|
|
|
|
152
|
83
|
|
|
|
|
232
|
return $removed_method; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub get_method_list { |
156
|
215
|
|
|
215
|
0
|
5426
|
my $self = shift; |
157
|
|
|
|
|
|
|
|
158
|
215
|
|
|
|
|
303
|
return keys %{ $self->_full_method_map }; |
|
215
|
|
|
|
|
571
|
|
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub _get_local_methods { |
162
|
7857
|
|
|
7857
|
|
12425
|
my $self = shift; |
163
|
|
|
|
|
|
|
|
164
|
7857
|
|
|
|
|
10456
|
return values %{ $self->_full_method_map }; |
|
7857
|
|
|
|
|
18089
|
|
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
sub _restore_metamethods_from { |
168
|
134
|
|
|
134
|
|
1555
|
my $self = shift; |
169
|
134
|
|
|
|
|
270
|
my ($old_meta) = @_; |
170
|
|
|
|
|
|
|
|
171
|
134
|
|
|
|
|
907
|
my $package_name = $self->name; |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# Check if Perl debugger is enabled |
174
|
134
|
|
|
|
|
1153
|
my $debugger_enabled = ($^P & 0x10); |
175
|
134
|
|
|
|
|
465
|
my $debug_method_info; |
176
|
|
|
|
|
|
|
|
177
|
134
|
|
|
|
|
474
|
for my $method ($old_meta->_get_local_methods) { |
178
|
167
|
|
|
|
|
594
|
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
|
167
|
|
|
|
|
549
|
$debug_method_info = ''; |
183
|
167
|
100
|
|
|
|
917
|
if ($debugger_enabled) { |
184
|
8
|
|
|
|
|
22
|
$debug_method_info = $DB::sub{$package_name . "::" . $method_name} |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
167
|
|
|
|
|
1851
|
$method->_make_compatible_with($self->method_metaclass); |
188
|
164
|
|
|
|
|
862
|
$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
|
164
|
100
|
66
|
|
|
708
|
if ($debugger_enabled && $debug_method_info) { |
195
|
8
|
|
|
|
|
25
|
$DB::sub{$package_name . "::" . $method_name} = $debug_method_info; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
1593
|
|
|
1593
|
0
|
7483
|
sub reset_package_cache_flag { (shift)->{'_package_cache_flag'} = undef } |
201
|
|
|
|
|
|
|
sub update_package_cache_flag { |
202
|
183710
|
|
|
183710
|
0
|
260003
|
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
|
183710
|
|
|
|
|
1201270
|
$self->{'_package_cache_flag'} = Class::MOP::check_package_cache_flag($self->name); |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub _full_method_map { |
213
|
8072
|
|
|
8072
|
|
11294
|
my $self = shift; |
214
|
|
|
|
|
|
|
|
215
|
8072
|
|
|
|
|
26545
|
my $pkg_gen = Class::MOP::check_package_cache_flag($self->name); |
216
|
|
|
|
|
|
|
|
217
|
8072
|
100
|
100
|
|
|
31257
|
if (($self->{_package_cache_flag_full} || -1) != $pkg_gen) { |
218
|
|
|
|
|
|
|
# forcibly reify all method map entries |
219
|
|
|
|
|
|
|
$self->get_method($_) |
220
|
3483
|
|
|
|
|
13035
|
for $self->list_all_package_symbols('CODE'); |
221
|
3483
|
|
|
|
|
11058
|
$self->{_package_cache_flag_full} = $pkg_gen; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
8072
|
|
|
|
|
77690
|
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.2203 |
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 |