line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
6
|
|
|
6
|
|
361807
|
use 5.008; |
|
6
|
|
|
|
|
57
|
|
2
|
6
|
|
|
6
|
|
30
|
use strict; |
|
6
|
|
|
|
|
7
|
|
|
6
|
|
|
|
|
120
|
|
3
|
6
|
|
|
6
|
|
23
|
use warnings; |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
209
|
|
4
|
6
|
|
|
6
|
|
35
|
no strict qw(refs); |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
202
|
|
5
|
6
|
|
|
6
|
|
28
|
no warnings qw(redefine prototype); |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
381
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
package Subclass::Of; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
BEGIN { |
10
|
6
|
|
|
6
|
|
28
|
$Subclass::Of::AUTHORITY = 'cpan:TOBYINK'; |
11
|
6
|
|
|
|
|
162
|
$Subclass::Of::VERSION = '0.009'; |
12
|
|
|
|
|
|
|
} |
13
|
|
|
|
|
|
|
|
14
|
6
|
|
|
6
|
|
35
|
use B qw(perlstring); |
|
6
|
|
|
|
|
7
|
|
|
6
|
|
|
|
|
362
|
|
15
|
6
|
|
|
6
|
|
34
|
use Carp qw(carp croak); |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
343
|
|
16
|
6
|
|
|
6
|
|
2070
|
use Module::Runtime qw(use_package_optimistically module_notional_filename); |
|
6
|
|
|
|
|
6970
|
|
|
6
|
|
|
|
|
31
|
|
17
|
6
|
|
|
6
|
|
481
|
use List::Util 1.33 qw(all); |
|
6
|
|
|
|
|
123
|
|
|
6
|
|
|
|
|
598
|
|
18
|
6
|
|
|
6
|
|
39
|
use Scalar::Util qw(refaddr blessed weaken); |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
304
|
|
19
|
6
|
|
|
6
|
|
1721
|
use Sub::Util qw(set_subname); |
|
6
|
|
|
|
|
1092
|
|
|
6
|
|
|
|
|
333
|
|
20
|
6
|
|
|
6
|
|
2744
|
use namespace::clean; |
|
6
|
|
|
|
|
71742
|
|
|
6
|
|
|
|
|
41
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
our ($SUPER_PKG, $SUPER_SUB, $SUPER_ARG); |
23
|
|
|
|
|
|
|
our @EXPORT = qw(subclass_of); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $_v; |
26
|
|
|
|
|
|
|
sub import |
27
|
|
|
|
|
|
|
{ |
28
|
20
|
|
|
20
|
|
5239
|
my $me = shift; |
29
|
|
|
|
|
|
|
|
30
|
20
|
100
|
|
|
|
124
|
return $me->install(@_, -into => scalar caller) if @_; |
31
|
|
|
|
|
|
|
|
32
|
3
|
|
|
|
|
837
|
require Exporter::Tiny; |
33
|
3
|
|
|
|
|
6328
|
our @ISA = "Exporter::Tiny"; |
34
|
3
|
|
|
|
|
12
|
@_ = $me; |
35
|
3
|
|
|
|
|
12
|
goto \&Exporter::Tiny::import; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
{ |
39
|
|
|
|
|
|
|
my %i_made_this; |
40
|
|
|
|
|
|
|
sub install |
41
|
|
|
|
|
|
|
{ |
42
|
17
|
|
|
17
|
1
|
413
|
my $me = shift; |
43
|
17
|
50
|
|
|
|
52
|
my $base = shift or croak "Subclass::Of what?"; |
44
|
17
|
|
|
|
|
41
|
my %opts = $me->_parse_opts(@_); |
45
|
|
|
|
|
|
|
|
46
|
17
|
|
|
|
|
37
|
my $caller = $opts{-into}[0]; |
47
|
17
|
100
|
|
|
|
95
|
my @aliases = $opts{-as} ? @{$opts{-as}} : ($base =~ /(\w+)$/); |
|
3
|
|
|
|
|
7
|
|
48
|
|
|
|
|
|
|
|
49
|
17
|
|
|
|
|
29
|
my $constant; |
50
|
|
|
|
|
|
|
my $subclass; |
51
|
17
|
100
|
|
|
|
35
|
if ($opts{-lazy}) { |
52
|
5
|
|
|
|
|
7
|
my $current_sub; |
53
|
|
|
|
|
|
|
$constant = sub () { |
54
|
2
|
|
66
|
2
|
|
10
|
$subclass ||= do { |
55
|
1
|
|
|
|
|
8
|
my $built = $me->_build_subclass($base, \%opts); |
56
|
1
|
|
|
|
|
5
|
$i_made_this{refaddr($current_sub)} = $built; |
57
|
1
|
|
|
|
|
6
|
$built; |
58
|
|
|
|
|
|
|
}; |
59
|
5
|
|
|
|
|
20
|
}; |
60
|
5
|
|
|
|
|
23
|
weaken( $current_sub = $constant ); |
61
|
5
|
|
|
|
|
18
|
$i_made_this{refaddr($constant)} = '(unknown package)'; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
else { |
64
|
12
|
|
|
|
|
37
|
$subclass = $me->_build_subclass($base, \%opts); |
65
|
12
|
|
|
|
|
1082
|
$constant = eval sprintf(q/sub () { %s if $] }/, perlstring($subclass)); |
66
|
12
|
|
|
|
|
71
|
$i_made_this{refaddr($constant)} = $subclass; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
17
|
|
|
|
|
39
|
for my $a (@aliases) |
70
|
|
|
|
|
|
|
{ |
71
|
17
|
100
|
|
|
|
21
|
if (exists &{"$caller\::$a"}) |
|
17
|
|
|
|
|
86
|
|
72
|
|
|
|
|
|
|
{ |
73
|
5
|
|
|
|
|
5
|
my $old = $i_made_this{refaddr(\&{"$caller\::$a"})}; |
|
5
|
|
|
|
|
16
|
|
74
|
5
|
100
|
|
|
|
75
|
carp( |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
75
|
|
|
|
|
|
|
$old |
76
|
|
|
|
|
|
|
? "Subclass::Of is overwriting alias '$a'" |
77
|
|
|
|
|
|
|
.($old eq '(unknown package)'?"":"; was '$old'") |
78
|
|
|
|
|
|
|
.($subclass?"; now '$subclass'":"") |
79
|
|
|
|
|
|
|
: "Subclass::Of is overwriting function '$a'", |
80
|
|
|
|
|
|
|
); |
81
|
|
|
|
|
|
|
} |
82
|
17
|
|
|
|
|
2722
|
*{"$caller\::$a"} = $constant; |
|
17
|
|
|
|
|
137
|
|
83
|
|
|
|
|
|
|
} |
84
|
17
|
|
|
|
|
86
|
"namespace::clean"->import(-cleanee => $caller, @aliases); |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub _alias_to_package_name { |
88
|
2
|
50
|
|
2
|
|
873
|
shift unless ref $_[0]; # allow call as class method |
89
|
2
|
|
|
|
|
14
|
my @r = map $i_made_this{refaddr($_)}, @_; |
90
|
2
|
0
|
33
|
|
|
8
|
croak('_alias_to_package_name(LIST) returns a list') |
|
|
|
33
|
|
|
|
|
91
|
|
|
|
|
|
|
if @r != 1 and defined(wantarray) and !wantarray; |
92
|
2
|
50
|
|
|
|
12
|
wantarray ? @r : $r[0]; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub subclass_of |
97
|
|
|
|
|
|
|
{ |
98
|
3
|
50
|
|
3
|
1
|
1395
|
my $base = shift or croak "Subclass::Of what?"; |
99
|
3
|
|
|
|
|
16
|
my %opts = __PACKAGE__->_parse_opts(@_); |
100
|
|
|
|
|
|
|
|
101
|
3
|
|
|
|
|
10
|
return __PACKAGE__->_build_subclass($base, \%opts); |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub _parse_opts |
105
|
|
|
|
|
|
|
{ |
106
|
20
|
|
|
20
|
|
29
|
shift; |
107
|
|
|
|
|
|
|
|
108
|
20
|
50
|
33
|
|
|
64
|
if (@_==1 and ref($_[0]) eq q(HASH)) |
109
|
|
|
|
|
|
|
{ |
110
|
0
|
|
|
|
|
0
|
return %{$_[0]}; |
|
0
|
|
|
|
|
0
|
|
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
20
|
|
|
|
|
27
|
my %opts; |
114
|
20
|
|
|
|
|
30
|
my $key = undef; |
115
|
20
|
|
|
|
|
46
|
while (@_) |
116
|
|
|
|
|
|
|
{ |
117
|
71
|
|
|
|
|
97
|
$_ = shift; |
118
|
|
|
|
|
|
|
|
119
|
71
|
100
|
66
|
|
|
362
|
if (defined and !ref and /^-/) { |
|
|
|
100
|
|
|
|
|
120
|
38
|
|
|
|
|
59
|
$key = $_; |
121
|
38
|
|
50
|
|
|
147
|
$opts{$key} ||= []; |
122
|
38
|
|
|
|
|
115
|
next; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
33
|
100
|
|
|
|
58
|
push @{$opts{$key}}, ref eq q(ARRAY) ? @$_ : $_; |
|
33
|
|
|
|
|
148
|
|
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
20
|
|
|
|
|
91
|
return %opts; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
{ |
132
|
|
|
|
|
|
|
my %_detect_oo; # memoize |
133
|
|
|
|
|
|
|
sub _detect_oo |
134
|
|
|
|
|
|
|
{ |
135
|
19
|
|
|
19
|
|
3136
|
my $pkg = $_[0]; |
136
|
|
|
|
|
|
|
|
137
|
19
|
100
|
|
|
|
60
|
return $_detect_oo{$pkg} if exists $_detect_oo{$pkg}; |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# Use metaclass to determine the OO framework in use. |
140
|
|
|
|
|
|
|
# |
141
|
13
|
100
|
|
|
|
172
|
return $_detect_oo{$pkg} = "" |
142
|
|
|
|
|
|
|
unless $pkg->can("meta"); |
143
|
3
|
50
|
|
|
|
10
|
return $_detect_oo{$pkg} = "Moo" |
144
|
|
|
|
|
|
|
if ref($pkg->meta) eq "Moo::HandleMoose::FakeMetaClass"; |
145
|
0
|
0
|
|
|
|
0
|
return $_detect_oo{$pkg} = "Mouse" |
146
|
|
|
|
|
|
|
if $pkg->meta->isa("Mouse::Meta::Module"); |
147
|
0
|
0
|
|
|
|
0
|
return $_detect_oo{$pkg} = "Moose" |
148
|
|
|
|
|
|
|
if $pkg->meta->isa("Moose::Meta::Class"); |
149
|
0
|
0
|
|
|
|
0
|
return $_detect_oo{$pkg} = "Moose" |
150
|
|
|
|
|
|
|
if $pkg->meta->isa("Moose::Meta::Role"); |
151
|
0
|
|
|
|
|
0
|
return $_detect_oo{$pkg} = ""; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
{ |
156
|
|
|
|
|
|
|
my %count; |
157
|
|
|
|
|
|
|
sub _build_subclass |
158
|
|
|
|
|
|
|
{ |
159
|
16
|
|
|
16
|
|
26
|
my $me = shift; |
160
|
16
|
|
|
|
|
29
|
my ($parent, $opts) = @_; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
my $child = ( |
163
|
16
|
|
50
|
|
|
151
|
$opts->{-package} ||= [ sprintf('%s::__SUBCLASS__::%04d', $parent, ++$count{$parent}) ] |
164
|
|
|
|
|
|
|
)->[0]; |
165
|
|
|
|
|
|
|
|
166
|
16
|
|
|
|
|
62
|
my $oo = _detect_oo(use_package_optimistically($parent)); |
167
|
|
|
|
|
|
|
|
168
|
16
|
100
|
|
|
|
956
|
my $subclasser_method = $oo ? lc "_build_subclass_$oo" : "_build_subclass_raw"; |
169
|
16
|
100
|
|
|
|
34
|
my $attributes_method = $oo ? lc "_apply_attributes_$oo" : "_apply_attributes_raw"; |
170
|
|
|
|
|
|
|
|
171
|
16
|
|
|
|
|
63
|
$me->$subclasser_method($parent, $child, $opts); |
172
|
16
|
|
|
|
|
406
|
$me->$attributes_method($child, $opts); |
173
|
14
|
|
|
|
|
341
|
$me->_apply_methods($child, $opts); |
174
|
14
|
|
|
|
|
43
|
$me->_apply_roles($child, $opts); |
175
|
|
|
|
|
|
|
|
176
|
14
|
|
|
|
|
17616
|
my $i = 0; $i++ while caller($i) eq __PACKAGE__; |
|
14
|
|
|
|
|
61
|
|
177
|
14
|
|
|
|
|
764
|
$INC{module_notional_filename($child)} = (caller($i))[1]; |
178
|
|
|
|
|
|
|
|
179
|
14
|
|
|
|
|
598
|
return $child; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
sub _build_subclass_moose |
184
|
|
|
|
|
|
|
{ |
185
|
0
|
|
|
0
|
|
0
|
my $me = shift; |
186
|
0
|
|
|
|
|
0
|
my ($parent, $child, $opts) = @_; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# "Moose::Meta::Class"->initialize($child, superclasses => [$parent]); |
189
|
|
|
|
|
|
|
|
190
|
0
|
|
|
|
|
0
|
eval sprintf(q{ |
191
|
|
|
|
|
|
|
package %s; |
192
|
|
|
|
|
|
|
use Moose; |
193
|
|
|
|
|
|
|
extends %s; |
194
|
|
|
|
|
|
|
use namespace::clean; |
195
|
|
|
|
|
|
|
}, $child, perlstring($parent)); |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
sub _build_subclass_mouse |
199
|
|
|
|
|
|
|
{ |
200
|
0
|
|
|
0
|
|
0
|
my $me = shift; |
201
|
0
|
|
|
|
|
0
|
my ($parent, $child, $opts) = @_; |
202
|
|
|
|
|
|
|
|
203
|
0
|
|
|
|
|
0
|
eval sprintf(q{ |
204
|
|
|
|
|
|
|
package %s; |
205
|
|
|
|
|
|
|
use Mouse; |
206
|
|
|
|
|
|
|
extends %s; |
207
|
|
|
|
|
|
|
use namespace::clean; |
208
|
|
|
|
|
|
|
}, $child, perlstring($parent)); |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub _build_subclass_moo |
212
|
|
|
|
|
|
|
{ |
213
|
2
|
|
|
2
|
|
3
|
my $me = shift; |
214
|
2
|
|
|
|
|
4
|
my ($parent, $child, $opts) = @_; |
215
|
|
|
|
|
|
|
|
216
|
2
|
|
|
12
|
|
141
|
eval sprintf(q{ |
|
1
|
|
|
4
|
|
8
|
|
|
1
|
|
|
4
|
|
2
|
|
|
1
|
|
|
1
|
|
4
|
|
|
1
|
|
|
|
|
355
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
15
|
|
|
1
|
|
|
|
|
374
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
217
|
|
|
|
|
|
|
package %s; |
218
|
|
|
|
|
|
|
use Moo; |
219
|
|
|
|
|
|
|
extends %s; |
220
|
|
|
|
|
|
|
use namespace::clean; |
221
|
|
|
|
|
|
|
}, $child, perlstring($parent)); |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub _build_subclass_raw |
225
|
|
|
|
|
|
|
{ |
226
|
14
|
|
|
14
|
|
21
|
my $me = shift; |
227
|
14
|
|
|
|
|
29
|
my ($parent, $child, $opts) = @_; |
228
|
|
|
|
|
|
|
|
229
|
14
|
|
|
|
|
22
|
@{"$child\::ISA"} = $parent; |
|
14
|
|
|
|
|
332
|
|
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub _apply_attributes_moose |
233
|
|
|
|
|
|
|
{ |
234
|
0
|
|
|
0
|
|
0
|
my $me = shift; |
235
|
0
|
|
|
|
|
0
|
my ($child, $opts) = @_; |
236
|
|
|
|
|
|
|
|
237
|
0
|
0
|
|
|
|
0
|
return unless $opts->{-has}; |
238
|
|
|
|
|
|
|
|
239
|
0
|
|
|
|
|
0
|
my $meta = $child->meta; |
240
|
0
|
|
|
0
|
|
0
|
my $has = sub { $meta->add_attribute(@_) }; |
|
0
|
|
|
|
|
0
|
|
241
|
|
|
|
|
|
|
|
242
|
0
|
|
|
|
|
0
|
$me->_apply_attributes_generic($has, $opts); |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
*_apply_attributes_mouse = \&_apply_attributes_moose; |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub _apply_attributes_moo |
248
|
|
|
|
|
|
|
{ |
249
|
2
|
|
|
2
|
|
5
|
my $me = shift; |
250
|
2
|
|
|
|
|
4
|
my ($child, $opts) = @_; |
251
|
|
|
|
|
|
|
|
252
|
2
|
100
|
|
|
|
6
|
return unless $opts->{-has}; |
253
|
|
|
|
|
|
|
|
254
|
1
|
|
|
1
|
|
66
|
my $raw = eval sprintf(q{ |
|
1
|
|
|
1
|
|
7
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
282
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
255
|
|
|
|
|
|
|
package %s; |
256
|
|
|
|
|
|
|
use Moo; |
257
|
|
|
|
|
|
|
my $sub = \&has; |
258
|
|
|
|
|
|
|
use namespace::clean; |
259
|
|
|
|
|
|
|
return $sub; |
260
|
|
|
|
|
|
|
}, $child); |
261
|
1
|
|
|
3
|
|
5
|
my $has = sub { $raw->($_[0], %{$_[1]}) }; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
12
|
|
262
|
|
|
|
|
|
|
|
263
|
1
|
|
|
|
|
4
|
$me->_apply_attributes_generic($has, $opts); |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
my $fieldhash; |
267
|
|
|
|
|
|
|
sub _apply_attributes_raw |
268
|
|
|
|
|
|
|
{ |
269
|
14
|
|
|
14
|
|
26
|
my $me = shift; |
270
|
14
|
|
|
|
|
27
|
my ($child, $opts) = @_; |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
my $has = sub { |
273
|
6
|
|
|
6
|
|
11
|
my ($name, $opts) = @_; |
274
|
6
|
|
|
|
|
25
|
for my $key (sort keys %$opts) |
275
|
|
|
|
|
|
|
{ |
276
|
8
|
100
|
|
|
|
264
|
croak "Option '$key' in attribute specification not supported" |
277
|
|
|
|
|
|
|
unless $key =~ /^(is|isa|default|lazy|fieldhash)$/; |
278
|
|
|
|
|
|
|
} |
279
|
5
|
50
|
33
|
|
|
18
|
if (exists $opts->{lazy} and not $opts->{lazy}) |
280
|
|
|
|
|
|
|
{ |
281
|
0
|
|
|
|
|
0
|
carp "Attribute '$name' will be lazy anyway."; |
282
|
|
|
|
|
|
|
} |
283
|
5
|
50
|
66
|
|
|
32
|
if (exists $opts->{is} and $opts->{is} !~ /^(ro|rw|lazy)$/) |
284
|
|
|
|
|
|
|
{ |
285
|
0
|
|
|
|
|
0
|
croak "Option 'is' => '$opts->{is}' in attribute specification not supported" |
286
|
|
|
|
|
|
|
} |
287
|
5
|
100
|
|
|
|
11
|
if (exists $opts->{isa}) |
288
|
|
|
|
|
|
|
{ |
289
|
|
|
|
|
|
|
croak "Option 'isa' in attribute specification must be a blessed type constraint object with 'assert_valid' method" |
290
|
1
|
50
|
33
|
|
|
122
|
unless blessed $opts->{isa} && $opts->{isa}->can('assert_valid'); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
4
|
|
|
|
|
5
|
my $code; |
294
|
4
|
100
|
66
|
|
|
11
|
if (exists $opts->{fieldhash} and $opts->{fieldhash}) |
295
|
|
|
|
|
|
|
{ |
296
|
1
|
|
33
|
|
|
3
|
$fieldhash ||= do { |
297
|
1
|
|
|
|
|
2
|
my $impl; |
298
|
1
|
|
33
|
|
|
2
|
$impl ||= eval { require Hash::FieldHash; 'Hash::FieldHash' }; |
|
1
|
|
|
|
|
272
|
|
|
0
|
|
|
|
|
0
|
|
299
|
1
|
|
33
|
|
|
5
|
$impl ||= eval { require Hash::Util::FieldHash; 'Hash::Util::FieldHash' }; |
|
1
|
|
|
|
|
528
|
|
|
1
|
|
|
|
|
895
|
|
300
|
1
|
|
33
|
|
|
6
|
$impl ||= do { require Hash::Util::FieldHash::Compat; 'Hash::Util::FieldHash::Compat' }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
301
|
1
|
|
|
|
|
10
|
$impl->can('fieldhash'); |
302
|
|
|
|
|
|
|
}; |
303
|
1
|
|
|
|
|
2
|
my %data; |
304
|
1
|
|
|
|
|
3
|
$fieldhash->(\%data); |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
$code = sub |
307
|
|
|
|
|
|
|
{ |
308
|
2
|
|
|
|
|
552
|
my $self = shift; |
309
|
2
|
100
|
|
|
|
6
|
if (@_) |
310
|
|
|
|
|
|
|
{ |
311
|
1
|
50
|
|
|
|
5
|
croak "read-only accessor" unless $opts->{is} eq 'rw'; |
312
|
1
|
50
|
|
|
|
4
|
$opts->{isa}->assert_valid($_[0]) if $opts->{isa}; |
313
|
1
|
|
|
|
|
10
|
$data{$self} = $_[0]; |
314
|
|
|
|
|
|
|
} |
315
|
2
|
50
|
33
|
|
|
8
|
if (exists $opts->{default} and not exists $self->{$name}) |
316
|
|
|
|
|
|
|
{ |
317
|
|
|
|
|
|
|
my $tmp = ref($opts->{default}) eq q(CODE) |
318
|
|
|
|
|
|
|
? $opts->{default}->($self) |
319
|
0
|
0
|
|
|
|
0
|
: $opts->{default}; |
320
|
0
|
0
|
|
|
|
0
|
$opts->{isa}->assert_valid($tmp) if $opts->{isa}; |
321
|
0
|
|
|
|
|
0
|
$data{$self} = $tmp; |
322
|
|
|
|
|
|
|
} |
323
|
2
|
|
|
|
|
8
|
$data{$self}; |
324
|
1
|
|
|
|
|
16
|
}; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
else |
327
|
|
|
|
|
|
|
{ |
328
|
|
|
|
|
|
|
$code = sub |
329
|
|
|
|
|
|
|
{ |
330
|
3
|
|
|
|
|
15
|
my $self = shift; |
331
|
3
|
50
|
|
|
|
10
|
if (@_) |
332
|
|
|
|
|
|
|
{ |
333
|
0
|
0
|
|
|
|
0
|
croak "read-only accessor" unless $opts->{is} eq 'rw'; |
334
|
0
|
0
|
|
|
|
0
|
$opts->{isa}->assert_valid($_[0]) if $opts->{isa}; |
335
|
0
|
|
|
|
|
0
|
$self->{$name} = $_[0]; |
336
|
|
|
|
|
|
|
} |
337
|
3
|
100
|
66
|
|
|
12
|
if (exists $opts->{default} and not exists $self->{$name}) |
338
|
|
|
|
|
|
|
{ |
339
|
|
|
|
|
|
|
my $tmp = ref($opts->{default}) eq q(CODE) |
340
|
|
|
|
|
|
|
? $opts->{default}->($self) |
341
|
1
|
50
|
|
|
|
8
|
: $opts->{default}; |
342
|
1
|
50
|
|
|
|
6
|
$opts->{isa}->assert_valid($tmp) if $opts->{isa}; |
343
|
1
|
|
|
|
|
2
|
$self->{$name} = $tmp; |
344
|
|
|
|
|
|
|
} |
345
|
3
|
|
|
|
|
20
|
$self->{$name}; |
346
|
3
|
|
|
|
|
12
|
}; |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
4
|
|
|
|
|
28
|
*{"$child\::$name"} = set_subname("$child\::$name", $code); |
|
4
|
|
|
|
|
36
|
|
350
|
14
|
|
|
|
|
94
|
}; |
351
|
|
|
|
|
|
|
|
352
|
14
|
|
|
|
|
41
|
$me->_apply_attributes_generic($has, $opts); |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
sub _apply_attributes_generic |
356
|
|
|
|
|
|
|
{ |
357
|
15
|
|
|
15
|
|
22
|
my $me = shift; |
358
|
15
|
|
|
|
|
27
|
my ($has, $opts) = @_; |
359
|
|
|
|
|
|
|
|
360
|
15
|
100
|
|
|
|
21
|
my @attrs = @{ $opts->{-has} || [] }; |
|
15
|
|
|
|
|
70
|
|
361
|
15
|
|
|
|
|
152
|
while (@attrs) |
362
|
|
|
|
|
|
|
{ |
363
|
9
|
|
|
|
|
6962
|
my $name = shift(@attrs); |
364
|
9
|
50
|
|
|
|
37
|
$name =~ /^\w+/ or croak("Not a valid attribute name: $name"); |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
my $spec = |
367
|
9
|
100
|
|
|
|
48
|
ref($attrs[0]) eq q(ARRAY) ? +{@{shift(@attrs)}} : |
|
5
|
50
|
|
|
|
14
|
|
|
|
100
|
|
|
|
|
|
368
|
|
|
|
|
|
|
ref($attrs[0]) eq q(HASH) ? shift(@attrs) : |
369
|
|
|
|
|
|
|
ref($attrs[0]) eq q(CODE) ? { is => "rw", default => shift(@attrs) } : |
370
|
|
|
|
|
|
|
{ is => "rw" }; |
371
|
|
|
|
|
|
|
|
372
|
9
|
|
|
|
|
19
|
$has->($name, $spec); |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub _apply_methods |
377
|
|
|
|
|
|
|
{ |
378
|
14
|
|
|
14
|
|
22
|
my $me = shift; |
379
|
14
|
|
|
|
|
26
|
my ($pkg, $opts) = @_; |
380
|
|
|
|
|
|
|
|
381
|
14
|
|
|
|
|
33
|
my $methods = $me->_make_method_hash($pkg, $opts); |
382
|
14
|
|
|
|
|
66
|
for my $name (sort keys %$methods) |
383
|
|
|
|
|
|
|
{ |
384
|
10
|
|
|
|
|
17
|
*{"$pkg\::$name"} = $methods->{$name}; |
|
10
|
|
|
|
|
61
|
|
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
sub _apply_roles |
389
|
|
|
|
|
|
|
{ |
390
|
14
|
|
|
14
|
|
31
|
my $me = shift; |
391
|
14
|
|
|
|
|
26
|
my ($pkg, $opts) = @_; |
392
|
14
|
100
|
|
|
|
19
|
my @roles = map use_package_optimistically($_), @{ $opts->{-with} || [] }; |
|
14
|
|
|
|
|
66
|
|
393
|
|
|
|
|
|
|
|
394
|
14
|
100
|
|
|
|
10486
|
return unless @roles; |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# All roles appear to be Role::Tiny; use Role::Tiny to |
397
|
|
|
|
|
|
|
# handle composition. |
398
|
|
|
|
|
|
|
# |
399
|
2
|
100
|
|
2
|
|
13
|
if (all { _detect_oo($_) eq "" } @roles) |
|
2
|
|
|
|
|
6
|
|
400
|
|
|
|
|
|
|
{ |
401
|
1
|
|
|
|
|
6
|
require Role::Tiny; |
402
|
1
|
|
|
|
|
6
|
return "Role::Tiny"->apply_roles_to_package($pkg, @roles); |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
# Otherwise, role composition is determined by the OO framework |
406
|
|
|
|
|
|
|
# of the base class. |
407
|
|
|
|
|
|
|
# |
408
|
1
|
|
|
|
|
16
|
my $oo = _detect_oo($pkg); |
409
|
|
|
|
|
|
|
|
410
|
1
|
50
|
|
|
|
12
|
if ($oo eq "Moo") |
411
|
|
|
|
|
|
|
{ |
412
|
1
|
|
|
|
|
3
|
return "Moo::Role"->apply_roles_to_package($pkg, @roles); |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
0
|
0
|
|
|
|
0
|
if ($oo eq "Moose") |
416
|
|
|
|
|
|
|
{ |
417
|
0
|
|
|
|
|
0
|
return Moose::Util::apply_all_roles($pkg, @roles); |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
0
|
0
|
|
|
|
0
|
if ($oo eq "Mouse") |
421
|
|
|
|
|
|
|
{ |
422
|
0
|
|
|
|
|
0
|
return Mouse::Util::apply_all_roles($pkg, @roles); |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
# If all else fails, try using Moo because it understands quite |
426
|
|
|
|
|
|
|
# a lot about Moose and Mouse. |
427
|
|
|
|
|
|
|
# |
428
|
0
|
|
|
|
|
0
|
require Moo::Role; |
429
|
0
|
|
|
|
|
0
|
"Moo::Role"->apply_roles_to_package($pkg, @roles); |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
sub _make_method_hash |
433
|
|
|
|
|
|
|
{ |
434
|
14
|
|
|
14
|
|
17
|
shift; |
435
|
|
|
|
|
|
|
|
436
|
14
|
|
|
|
|
22
|
my $pkg = $_[0]; |
437
|
14
|
|
|
|
|
21
|
my $r = {}; |
438
|
14
|
100
|
|
|
|
17
|
my @methods = @{ $_[1]{-methods} || [] }; |
|
14
|
|
|
|
|
64
|
|
439
|
|
|
|
|
|
|
|
440
|
14
|
|
|
|
|
38
|
while (@methods) |
441
|
|
|
|
|
|
|
{ |
442
|
10
|
|
|
|
|
22
|
my ($name, $code) = splice(@methods, 0, 2); |
443
|
|
|
|
|
|
|
|
444
|
10
|
50
|
|
|
|
42
|
$name =~ /^\w+/ or croak("Not a valid method name: $name"); |
445
|
10
|
50
|
|
|
|
31
|
ref($code) eq q(CODE) or croak("Not a code reference: $code"); |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
$r->{$name} = set_subname "$pkg\::$name", sub { |
448
|
7
|
|
|
7
|
|
7031
|
local $SUPER_PKG = $pkg; |
|
|
|
|
7
|
|
|
|
449
|
7
|
|
|
|
|
14
|
local $SUPER_SUB = $name; |
450
|
7
|
|
|
|
|
14
|
local $SUPER_ARG = \@_; |
451
|
7
|
|
|
|
|
52
|
$code->(@_); |
452
|
10
|
|
|
|
|
107
|
}; |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
|
455
|
14
|
|
|
|
|
29
|
return $r; |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
sub ::SUPER |
459
|
|
|
|
|
|
|
{ |
460
|
2
|
50
|
|
8
|
|
24
|
eval { require mro } or do { require MRO::Compat }; |
|
2
|
|
|
|
|
18
|
|
|
0
|
|
|
|
|
0
|
|
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
my ($super) = |
463
|
2
|
|
|
|
|
3
|
map { \&{ "$_\::$SUPER_SUB" } } |
|
2
|
|
|
|
|
10
|
|
464
|
3
|
|
|
|
|
5
|
grep { exists &{"$_\::$SUPER_SUB"} } |
|
3
|
|
|
|
|
13
|
|
465
|
5
|
|
|
|
|
11
|
grep { $_ ne $SUPER_PKG } |
466
|
2
|
|
|
|
|
5
|
@{ mro::get_linear_isa($SUPER_PKG) }; |
|
2
|
|
|
|
|
9
|
|
467
|
|
|
|
|
|
|
|
468
|
2
|
50
|
|
|
|
17
|
croak qq[Can't locate object method "$SUPER_SUB" via package "$SUPER_PKG"] |
469
|
|
|
|
|
|
|
unless $super; |
470
|
|
|
|
|
|
|
|
471
|
2
|
50
|
|
|
|
9
|
@_ = @$SUPER_ARG unless @_; |
472
|
2
|
|
|
|
|
12
|
goto $super; |
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
1; |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
__END__ |