line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=head1 NAME |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
Devel::PerlySense::Document::Meta - Document information generated |
4
|
|
|
|
|
|
|
during a parse |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=cut |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
12
|
68
|
|
|
68
|
|
249
|
use strict; |
|
68
|
|
|
|
|
84
|
|
|
68
|
|
|
|
|
1641
|
|
13
|
68
|
|
|
68
|
|
212
|
use warnings; |
|
68
|
|
|
|
|
82
|
|
|
68
|
|
|
|
|
1342
|
|
14
|
68
|
|
|
68
|
|
206
|
use utf8; |
|
68
|
|
|
|
|
71
|
|
|
68
|
|
|
|
|
325
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
package Devel::PerlySense::Document::Meta; |
17
|
|
|
|
|
|
|
$Devel::PerlySense::Document::Meta::VERSION = '0.0218'; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
|
23
|
68
|
|
|
68
|
|
2817
|
use Spiffy -Base; |
|
68
|
|
|
|
|
73
|
|
|
68
|
|
|
|
|
340
|
|
24
|
68
|
|
|
68
|
|
114982
|
use Carp; |
|
68
|
|
|
68
|
|
82
|
|
|
68
|
|
|
68
|
|
1022
|
|
|
68
|
|
|
|
|
188
|
|
|
68
|
|
|
|
|
74
|
|
|
68
|
|
|
|
|
1239
|
|
|
68
|
|
|
|
|
184
|
|
|
68
|
|
|
|
|
68
|
|
|
68
|
|
|
|
|
2902
|
|
25
|
68
|
|
|
68
|
|
233
|
use File::Basename; |
|
68
|
|
|
|
|
75
|
|
|
68
|
|
|
|
|
2627
|
|
26
|
68
|
|
|
68
|
|
220
|
use Path::Class; |
|
68
|
|
|
|
|
80
|
|
|
68
|
|
|
|
|
2199
|
|
27
|
68
|
|
|
68
|
|
213
|
use Data::Dumper; |
|
68
|
|
|
|
|
89
|
|
|
68
|
|
|
|
|
1931
|
|
28
|
68
|
|
|
68
|
|
247
|
use PPI::Document; |
|
68
|
|
|
|
|
76
|
|
|
68
|
|
|
|
|
1092
|
|
29
|
68
|
|
|
68
|
|
27072
|
use PPI::Dumper; |
|
68
|
|
|
|
|
48948
|
|
|
68
|
|
|
|
|
5109
|
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 PROPERTIES |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head2 raPackage |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
Package declarations. |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Array ref with cloned PPI::Statement::Package objects. |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Default: [] |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=cut |
46
|
|
|
|
|
|
|
field "raPackage" => []; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=head2 raNameModuleUse |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
Array ref with module names that are "use"d. |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
Default: [] |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=cut |
59
|
|
|
|
|
|
|
field "raNameModuleUse" => []; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=head2 raNameModuleBase |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Array ref with module names that are base classes. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
Default: [] |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=cut |
72
|
|
|
|
|
|
|
field "raNameModuleBase" => []; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head2 rhRowColModule |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Module names. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
Hash ref with (keys: row, values: |
83
|
|
|
|
|
|
|
hash ref with (keys: col, values: |
84
|
|
|
|
|
|
|
hash with keys: |
85
|
|
|
|
|
|
|
oNode => cloned PPI::Node objects |
86
|
|
|
|
|
|
|
module => module name string |
87
|
|
|
|
|
|
|
) |
88
|
|
|
|
|
|
|
) |
89
|
|
|
|
|
|
|
) |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
rhRowColModule->{43}->{2}-> node |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
Default: {} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=cut |
96
|
|
|
|
|
|
|
field "rhRowColModule" => {}; |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head2 rhRowColMethod |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
Method calls. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
Hash ref with (keys: row, values: |
107
|
|
|
|
|
|
|
hash ref with (keys: col, values: |
108
|
|
|
|
|
|
|
{ |
109
|
|
|
|
|
|
|
oNode => cloned PPI::Node object, |
110
|
|
|
|
|
|
|
oNodePrev => node to the left of the -> |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
) |
113
|
|
|
|
|
|
|
) |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
rhRowColModule->{43}->{2}-> node |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
Default: {} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=cut |
120
|
|
|
|
|
|
|
field "rhRowColMethod" => {}; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=head2 raLocationPod |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
POD blocks. |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Array ref with Location objects, representing each pod chunk that is a |
131
|
|
|
|
|
|
|
heading/item. They have the following properties: |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
podSection |
134
|
|
|
|
|
|
|
pod |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Default: [] |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=cut |
139
|
|
|
|
|
|
|
field "raLocationPod" => []; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=head2 raLocationSub |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub definition. |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
Array ref with Location objects, representing each sub |
150
|
|
|
|
|
|
|
declaration. They have the following properties: |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
nameSub |
153
|
|
|
|
|
|
|
source |
154
|
|
|
|
|
|
|
namePackage |
155
|
|
|
|
|
|
|
oLocationEnd |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Default: [] |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
160
|
|
|
|
|
|
|
field "raLocationSub" => []; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=head2 aPluginSyntax |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Array ref with Devel::PerlySense::Plugin::Syntax objects. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Return whatever plugins under Devel::PerlySense::Plugin::Syntax::* are |
174
|
|
|
|
|
|
|
found. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Readonly. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=cut |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
use Module::Pluggable ( |
181
|
68
|
|
|
|
|
706
|
sub_name => "raPluginSyntax", |
182
|
|
|
|
|
|
|
search_path => [ "Devel::PerlySense::Plugin::Syntax" ], |
183
|
|
|
|
|
|
|
instantiate => "new", |
184
|
68
|
|
|
68
|
|
355
|
); |
|
68
|
|
|
|
|
87
|
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
my $raPluginSyntax; |
187
|
337
|
|
|
337
|
1
|
498
|
sub aPluginSyntax { |
188
|
337
|
|
100
|
|
|
1233
|
$raPluginSyntax ||= [ $self->raPluginSyntax ]; |
189
|
337
|
|
|
|
|
60604
|
return @$raPluginSyntax; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=head1 API METHODS |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=head2 new() |
199
|
|
|
|
|
|
|
Create new empty Meta object |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=cut |
202
|
|
|
|
|
|
|
sub new(@) { |
203
|
336
|
|
|
336
|
1
|
1060
|
my $pkg = shift; |
204
|
|
|
|
|
|
|
|
205
|
336
|
|
|
|
|
872
|
my $self = bless {}, $pkg; |
206
|
|
|
|
|
|
|
|
207
|
336
|
|
|
|
|
754
|
return($self); |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=head2 parse($oDocument) |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Parse the Devel::PerlySense::Document and extract metadata. Fill |
217
|
|
|
|
|
|
|
appropriate data structures. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Return 1 or die on errors. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=cut |
222
|
|
|
|
|
|
|
sub _setRowColNodeModule(\%$$$$) { |
223
|
6230
|
|
|
6230
|
|
19159
|
my ($rhRowCol, $row, $col, $oNode, $module) = @_; |
224
|
|
|
|
|
|
|
|
225
|
6230
|
|
|
|
|
25749
|
$rhRowCol->{$row}->{$col} = { |
226
|
|
|
|
|
|
|
oNode => $oNode, |
227
|
|
|
|
|
|
|
module => $module, |
228
|
|
|
|
|
|
|
}; |
229
|
|
|
|
|
|
|
|
230
|
6230
|
|
|
|
|
9165
|
return; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
335
|
|
|
335
|
1
|
491
|
sub parse { |
234
|
335
|
|
|
|
|
450
|
my ($oDocument) = @_; |
235
|
|
|
|
|
|
|
#PPI::Dumper->new($oDocument->oDocument)->print; use PPI::Dumper; |
236
|
|
|
|
|
|
|
|
237
|
335
|
|
|
|
|
509
|
my @aToken; |
238
|
|
|
|
|
|
|
my @aPackage; |
239
|
0
|
|
|
|
|
0
|
my %hNameModuleUse; |
240
|
0
|
|
|
|
|
0
|
my %hNameModuleBase; |
241
|
0
|
|
|
|
|
0
|
my %hRowColModule; |
242
|
0
|
|
|
|
|
0
|
my %hRowColMethod; |
243
|
0
|
|
|
|
|
0
|
my @aLocationPod; |
244
|
0
|
|
|
|
|
0
|
my @aPodHeadingCurrent; |
245
|
335
|
|
|
|
|
599
|
my $packageCurrent = "main"; |
246
|
335
|
|
|
|
|
2377
|
my $rhDataDocument = { |
247
|
|
|
|
|
|
|
raPackage => \@aPackage, |
248
|
|
|
|
|
|
|
rhNameModuleUse => \%hNameModuleUse, |
249
|
|
|
|
|
|
|
rhNameModuleBase => \%hNameModuleBase, |
250
|
|
|
|
|
|
|
rhRowColModule => \%hRowColModule, |
251
|
|
|
|
|
|
|
rhRowColMethod => \%hRowColMethod, |
252
|
|
|
|
|
|
|
raLocationPod => \@aLocationPod, |
253
|
|
|
|
|
|
|
}; |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
#Optimization, avoid the method call inside the loop |
256
|
335
|
|
|
|
|
1098
|
my @aPluginSyntax = $self->aPluginSyntax(); |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
$oDocument->aDocumentFind( |
259
|
|
|
|
|
|
|
sub { |
260
|
523635
|
|
|
523635
|
|
3540591
|
my ($oTop, $oNode) = @_; |
261
|
523635
|
50
|
|
|
|
821728
|
my $oLocation = $oNode->location or return(0); |
262
|
523635
|
|
|
|
|
3500876
|
eval { |
263
|
|
|
|
|
|
|
|
264
|
523635
|
|
|
|
|
456079
|
my ($row, $col) = ($oLocation->[0], $oLocation->[1]); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
#Optimization: compare against the string instead of |
267
|
|
|
|
|
|
|
#doing insanely many ->isa(). This is slightly fragile |
268
|
|
|
|
|
|
|
#wrt changes in subclasses in PPI. |
269
|
523635
|
|
|
|
|
432393
|
my $pkgNode = ref($oNode); |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
#Collect tokens |
274
|
523635
|
100
|
66
|
|
|
1486131
|
if($pkgNode =~ /^PPI::Token/ && $oNode->location) { |
275
|
431136
|
100
|
100
|
|
|
3378852
|
if($pkgNode =~ /^PPI::Token::QuoteLike/ || $pkgNode =~ /^PPI::Token::Quote/) { |
276
|
5350
|
|
|
|
|
6494
|
push(@aToken, $oNode); |
277
|
|
|
|
|
|
|
} else { |
278
|
|
|
|
|
|
|
#...we're only interested in nodes which are single words |
279
|
425786
|
100
|
|
|
|
617908
|
if( $oNode !~ /\s/) { |
280
|
247677
|
|
|
|
|
787551
|
push(@aToken, $oNode); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
#package |
289
|
523635
|
100
|
|
|
|
1261433
|
if($pkgNode eq "PPI::Statement::Package") { |
290
|
332
|
|
|
|
|
568
|
push(@aPackage, $oNode); |
291
|
332
|
|
|
|
|
1543
|
$packageCurrent = $oNode->namespace; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
#use |
297
|
523635
|
100
|
|
|
|
611556
|
if($pkgNode eq "PPI::Statement::Include") { |
298
|
3144
|
100
|
|
|
|
5017
|
$hNameModuleUse{$1}++ if($oNode =~ /^ use \s+ ( [A-Z][\w:]* ) /xs); |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
#base class |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
# use base |
307
|
523635
|
100
|
|
|
|
689837
|
if($pkgNode eq "PPI::Statement::Include") { |
308
|
3144
|
100
|
|
|
|
4931
|
if($oNode =~ /^ use \s+ (?:base|parent) \s+ (?:qw)? \s* (.+);$/xs) { |
309
|
157
|
|
|
|
|
2978
|
my $modules = $1; |
310
|
157
|
|
|
|
|
736
|
for my $module (grep { $_ ne "qw" } $modules =~ /([\w:]+)/gs) { |
|
169
|
|
|
|
|
494
|
|
311
|
169
|
|
|
|
|
456
|
$hNameModuleBase{$module}++ ; |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
# @ISA = ... |
318
|
|
|
|
|
|
|
## fragile: stuff to the right... |
319
|
523635
|
100
|
100
|
|
|
821223
|
if($pkgNode eq "PPI::Token::Symbol" && $oNode eq '@ISA') { |
320
|
25
|
|
|
|
|
404
|
my $oStatement = $oNode->statement; |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
###TODO: ignore module names with interpolated variables |
323
|
25
|
100
|
|
|
|
356
|
if($oStatement =~ /\@ISA \s* = \s* (.+);$/xs) { |
324
|
17
|
|
|
|
|
520
|
my $modules = $1; |
325
|
17
|
|
|
|
|
87
|
for my $module (grep { $_ ne "qw" } $modules =~ /([\w:]+)/gs) { |
|
34
|
|
|
|
|
344
|
|
326
|
29
|
|
|
|
|
67
|
$hNameModuleBase{$module}++ ; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
#push(@ISA, ) |
332
|
|
|
|
|
|
|
## fragile: "push() if(sdfkjs)" doesn't work |
333
|
523635
|
100
|
100
|
|
|
1059864
|
if($pkgNode eq "PPI::Token::Symbol" && $oNode eq '@ISA' && @aToken > 2) { |
|
|
|
66
|
|
|
|
|
334
|
25
|
|
|
|
|
333
|
my $prev = -1; #last one is the '@ISA' |
335
|
|
|
|
|
|
|
|
336
|
25
|
100
|
66
|
|
|
59
|
if($aToken[--$prev] eq "push" || $aToken[--$prev] eq "push") { |
337
|
8
|
|
|
|
|
188
|
my $oStatement = $oNode->parent->parent; |
338
|
8
|
50
|
|
|
|
83
|
$oStatement =~ /\@ISA \s* , \s* (.+)/xs or next; |
339
|
8
|
|
|
|
|
292
|
my $modules = $1; |
340
|
|
|
|
|
|
|
|
341
|
8
|
|
|
|
|
62
|
$hNameModuleBase{$_}++ for($modules =~ /([\w:]+)/gs); |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
#module |
349
|
523635
|
100
|
100
|
|
|
1345549
|
if( |
|
|
100
|
|
|
|
|
|
350
|
|
|
|
|
|
|
$pkgNode eq "PPI::Token::Word" && |
351
|
|
|
|
|
|
|
$oNode =~ /^[A-Z][\w:]*$/ #Word chars and ::, Starts with uppercase, is pragma or number |
352
|
|
|
|
|
|
|
) { |
353
|
7835
|
100
|
100
|
|
|
58155
|
if( ! ($aToken[-2]->isa("PPI::Token::Operator") && $aToken[-2] eq "->") ) { |
354
|
5820
|
|
|
|
|
16461
|
_setRowColNodeModule(%hRowColModule, $row, $col, $oNode, "$oNode"); |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
elsif( |
358
|
|
|
|
|
|
|
$pkgNode =~ /^PPI::Token::Quote::/ |
359
|
|
|
|
|
|
|
# || $pkgNode =~ /^PPI::Token::QuoteLike/ ##TODO: enable when PPI gets "string" method on these classes |
360
|
|
|
|
|
|
|
) { |
361
|
5070
|
|
|
|
|
15083
|
my $module = $oNode->string; |
362
|
5070
|
100
|
|
|
|
37134
|
if($module =~ /^ [A-Z]\w* (?: :: [A-Z]\w* )+ $/x) { |
|
|
100
|
|
|
|
|
|
363
|
|
|
|
|
|
|
#Well formed, likely module, i.e. at least one :: separator |
364
|
355
|
|
|
|
|
1063
|
_setRowColNodeModule(%hRowColModule, $row, $col, $oNode, $module); |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
elsif($module =~ /^[A-Z][\w]*$/) { |
367
|
|
|
|
|
|
|
#Check whether there is a file anywhere matching the name (because only the string contents is a weak indicator of module-ness). |
368
|
526
|
100
|
|
|
|
2362
|
if($oDocument->fileFindModule(nameModule => $module)) { |
369
|
55
|
|
|
|
|
207
|
_setRowColNodeModule(%hRowColModule, $row, $col, $oNode, $module); |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
#method |
378
|
523635
|
100
|
100
|
|
|
981113
|
if($pkgNode eq "PPI::Token::Word" && @aToken > 2) { |
379
|
60118
|
|
|
|
|
71819
|
my ($oObject, $oOperator) = @aToken[-3, -2]; |
380
|
60118
|
100
|
100
|
|
|
183306
|
if($oOperator->isa("PPI::Token::Operator") && $oOperator eq "->") { |
381
|
17837
|
100
|
100
|
|
|
208317
|
$oObject->isa("PPI::Token::Symbol") || $oObject->isa("PPI::Token::Word") or $oObject = undef; |
382
|
|
|
|
|
|
|
#print "$row/$col: ($oObject$oOperator$oNode)\n"; |
383
|
17837
|
|
|
|
|
66443
|
$hRowColMethod{$row}->{$col} = { |
384
|
|
|
|
|
|
|
oNode => $oNode, |
385
|
|
|
|
|
|
|
oNodeObject => $oObject, |
386
|
|
|
|
|
|
|
}; |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
#pod |
394
|
523635
|
100
|
|
|
|
652516
|
if($pkgNode eq "PPI::Token::Pod") { |
395
|
4915
|
|
|
|
|
12954
|
$self->parsePod($oDocument, $oNode, \@aLocationPod, \@aPodHeadingCurrent); |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
#sub |
401
|
523635
|
|
|
|
|
380215
|
my $nameSub = ""; |
402
|
523635
|
100
|
100
|
|
|
692116
|
$pkgNode eq "PPI::Statement::Sub" && !$oNode->forward and $nameSub = $oNode->name; |
403
|
523635
|
100
|
|
|
|
729162
|
$pkgNode eq "PPI::Statement::Scheduled" and $nameSub = $oNode->type; |
404
|
523635
|
100
|
|
|
|
559493
|
if($nameSub) { |
405
|
|
|
|
|
|
|
push( |
406
|
3429
|
|
|
|
|
3262
|
@{$self->raLocationSub}, |
|
3429
|
|
|
|
|
66054
|
|
407
|
|
|
|
|
|
|
$self->oLocationSub( |
408
|
|
|
|
|
|
|
$oDocument, |
409
|
|
|
|
|
|
|
$oNode, |
410
|
|
|
|
|
|
|
$nameSub, |
411
|
|
|
|
|
|
|
$packageCurrent, |
412
|
|
|
|
|
|
|
), |
413
|
|
|
|
|
|
|
); |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
|
417
|
523635
|
|
|
|
|
482465
|
for my $plugin (@aPluginSyntax) { |
418
|
|
|
|
|
|
|
#TODO: Set new $packageCurrent if needed |
419
|
521049
|
|
|
|
|
900743
|
$plugin->parse( |
420
|
|
|
|
|
|
|
rhDataDocument => $rhDataDocument, |
421
|
|
|
|
|
|
|
oMeta => $self, |
422
|
|
|
|
|
|
|
oDocument => $oDocument, |
423
|
|
|
|
|
|
|
oNode => $oNode, |
424
|
|
|
|
|
|
|
pkgNode => $pkgNode, |
425
|
|
|
|
|
|
|
row => $row, |
426
|
|
|
|
|
|
|
col => $col, |
427
|
|
|
|
|
|
|
packageCurrent => $packageCurrent, |
428
|
|
|
|
|
|
|
raToken => \@aToken, |
429
|
|
|
|
|
|
|
); |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
}; |
432
|
523635
|
50
|
|
|
|
589360
|
$@ and warn($@); |
433
|
|
|
|
|
|
|
|
434
|
523635
|
|
|
|
|
745023
|
return(0); |
435
|
335
|
|
|
|
|
4143
|
}); |
436
|
|
|
|
|
|
|
|
437
|
335
|
|
|
|
|
21850
|
$self->raPackage(\@aPackage); |
438
|
335
|
|
|
|
|
10785
|
$self->raNameModuleUse([sort keys %hNameModuleUse]); |
439
|
335
|
|
|
|
|
8302
|
$self->raNameModuleBase([sort keys %hNameModuleBase]); |
440
|
335
|
|
|
|
|
7261
|
$self->rhRowColModule(\%hRowColModule); |
441
|
335
|
|
|
|
|
6999
|
$self->rhRowColMethod(\%hRowColMethod); |
442
|
335
|
|
|
|
|
6945
|
$self->raLocationPod(\@aLocationPod); |
443
|
|
|
|
|
|
|
|
444
|
335
|
|
|
|
|
27351
|
return(1); |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=head2 moduleAt(row => $row, col => $col) |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
Find the module mentioned on line $row (1..) at $col (1..). |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
Return string like "My::Module" or "Module", or undef if none was |
456
|
|
|
|
|
|
|
found. |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
=cut |
459
|
38
|
|
|
38
|
1
|
160
|
sub moduleAt { |
460
|
38
|
|
|
|
|
96
|
my ($row, $col) = Devel::PerlySense::Util::aNamedArg(["row", "col"], @_); |
461
|
38
|
100
|
|
|
|
506
|
my $rhToken = $self->rhTokenOfAt($self->rhRowColModule, $row, $col) or return(undef); |
462
|
12
|
|
|
|
|
62
|
return( $rhToken->{module} ); |
463
|
|
|
|
|
|
|
} |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
=head2 rhMethodAt(row => $row, col => $col) |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
Find the module mentioned on line $row (1..) at $col (1..). |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
Return hash ref with { oNode, oNodeObject } or undef if none was |
474
|
|
|
|
|
|
|
found. |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
=cut |
477
|
88
|
|
|
88
|
1
|
356
|
sub rhMethodAt { |
478
|
88
|
|
|
|
|
213
|
my ($row, $col) = Devel::PerlySense::Util::aNamedArg(["row", "col"], @_); |
479
|
88
|
|
|
|
|
1441
|
return($self->rhTokenOfAt($self->rhRowColMethod, $row, $col)); |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
=head2 rhTokenOfAt($rhRowCol, $row, $col) |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
Find the token mentioned in $rhRowCol on line $row (1..) at $col (1..). |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
Return hash ref with keys oNode and possibly oNodeObject, or undef if |
491
|
|
|
|
|
|
|
none was found. |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=cut |
494
|
126
|
|
|
126
|
1
|
564
|
sub rhTokenOfAt { |
495
|
126
|
|
|
|
|
136
|
my ($rhRowCol, $row, $col) = @_; |
496
|
|
|
|
|
|
|
|
497
|
126
|
100
|
|
|
|
430
|
my $rhCol = $rhRowCol->{$row} or return(undef); |
498
|
69
|
|
|
|
|
189
|
for my $colToken (keys %$rhCol) { |
499
|
88
|
|
|
|
|
101
|
my $rhToken = $rhCol->{$colToken}; |
500
|
88
|
|
|
|
|
95
|
my $oNode = $rhToken->{oNode}; |
501
|
88
|
|
|
|
|
290
|
my $colTokenEnd = $colToken + length($oNode); |
502
|
88
|
100
|
100
|
|
|
620
|
if($col >= $colToken && $col < $colTokenEnd) { |
503
|
57
|
|
|
|
|
225
|
return($rhToken); |
504
|
|
|
|
|
|
|
} |
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
|
507
|
12
|
|
|
|
|
45
|
return(undef); |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=head2 parsePod($oDocument, $oNode, $raLocationPod, $raPodHeadingCurrent) |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
Parse $oNode and add one or more Location objects to $raLocationPod. |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
Add pod chunks that are =head or =item. Prefix the pod chunks with |
519
|
|
|
|
|
|
|
their immediate pod heading level. |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
Return 1 on success, die on errors. |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=cut |
524
|
4915
|
|
|
4915
|
1
|
4607
|
sub parsePod { |
525
|
4915
|
|
|
|
|
5505
|
my ($oDocument, $oNode, $raLocationPod, $raPodHeadingCurrent) = @_; |
526
|
|
|
|
|
|
|
|
527
|
4915
|
|
|
|
|
8709
|
my @aLine = split(/\n/, $oNode); |
528
|
4915
|
|
|
|
|
26491
|
my $lineCur = -1; |
529
|
4915
|
|
|
|
|
6464
|
for my $line (@aLine) { |
530
|
53830
|
|
|
|
|
31302
|
$lineCur++; |
531
|
|
|
|
|
|
|
|
532
|
53830
|
100
|
|
|
|
143023
|
if($line =~ /^ (?: =head(\d+)\b ) | (?: =item\b )/x) { |
533
|
7202
|
|
100
|
|
|
21408
|
my $headingLevel = $1 || 0; |
534
|
7202
|
100
|
|
|
|
9859
|
if($headingLevel) { |
535
|
6865
|
100
|
|
|
|
17794
|
@$raPodHeadingCurrent > $headingLevel and splice(@$raPodHeadingCurrent, $headingLevel); #Remove everything below this heading |
536
|
6865
|
|
|
|
|
11670
|
$raPodHeadingCurrent->[$headingLevel - 1] = $line; |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
7202
|
|
|
|
|
6121
|
my $podSection = ""; |
540
|
7202
|
|
|
|
|
5312
|
my $level = 0; |
541
|
7202
|
|
|
|
|
8345
|
for my $heading (@$raPodHeadingCurrent) { |
542
|
12298
|
50
|
|
|
|
15581
|
defined($heading) or $heading = ""; # Silence undef warning, is this the right thing to do? |
543
|
12298
|
100
|
100
|
|
|
37934
|
($level < $headingLevel - 1) || ($headingLevel == 0) and $podSection .= "$heading\n\n"; |
544
|
12298
|
|
|
|
|
12347
|
$level++; |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
|
548
|
7202
|
|
|
|
|
10005
|
my $pod = "$line\n"; |
549
|
7202
|
|
|
|
|
7309
|
my $linePod = $lineCur + 1; |
550
|
7202
|
|
66
|
|
|
26022
|
while(defined($aLine[$linePod]) && $aLine[$linePod] !~ /^=/) { |
551
|
41264
|
|
|
|
|
125275
|
$pod .= $aLine[$linePod++] . "\n"; |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
|
554
|
7202
|
|
|
|
|
147628
|
my $oLocation = Devel::PerlySense::Document::Location->new( |
555
|
|
|
|
|
|
|
file => $oDocument->file, |
556
|
|
|
|
|
|
|
row => $oNode->location->[0] + $lineCur, |
557
|
|
|
|
|
|
|
col => 1, |
558
|
|
|
|
|
|
|
); |
559
|
7202
|
|
|
|
|
91844
|
$oLocation->rhProperty->{pod} = $pod; |
560
|
7202
|
|
|
|
|
108176
|
$oLocation->rhProperty->{podSection} = $podSection; |
561
|
|
|
|
|
|
|
|
562
|
7202
|
|
|
|
|
31969
|
push(@$raLocationPod, $oLocation); |
563
|
|
|
|
|
|
|
} |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
|
566
|
4915
|
|
|
|
|
10111
|
return(1); |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
=head2 oLocationSub($oDocument, $oNode, $nameSub, $packageCurrent) |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
Create a Document::Location object from the sub $nameSub consisting of |
576
|
|
|
|
|
|
|
$oNode, found in $oDocument in $packageCurrent. |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
Set appropriate Location->rhProperty keys: |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
nameSub |
581
|
|
|
|
|
|
|
source |
582
|
|
|
|
|
|
|
namePackage |
583
|
|
|
|
|
|
|
oLocationEnd |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
Return the new Location object. |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
=cut |
588
|
3440
|
|
|
3440
|
1
|
21456
|
sub oLocationSub { |
589
|
3440
|
|
|
|
|
5206
|
my ($oDocument, $oNode, $nameSub, $packageCurrent) = @_; |
590
|
|
|
|
|
|
|
|
591
|
3440
|
|
|
|
|
45732
|
my $oLocation = Devel::PerlySense::Document::Location->new( |
592
|
|
|
|
|
|
|
file => $oDocument->file, |
593
|
|
|
|
|
|
|
row => $oNode->location->[0], |
594
|
|
|
|
|
|
|
col => $oNode->location->[1], |
595
|
|
|
|
|
|
|
); |
596
|
3440
|
|
|
|
|
45625
|
$oLocation->rhProperty->{nameSub} = $nameSub; |
597
|
3440
|
|
|
|
|
17694
|
$oLocation->rhProperty->{source} = "$oNode"; |
598
|
3440
|
|
|
|
|
1203165
|
$oLocation->rhProperty->{namePackage} = $packageCurrent; |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
|
601
|
3440
|
|
|
|
|
16260
|
my $countNewline =()= $oNode =~ /\n/g; |
602
|
3440
|
|
|
|
|
866180
|
my ($rowEnd, $colEnd) = ($oNode->location->[0] + $countNewline, 1); |
603
|
3440
|
100
|
|
|
|
38098
|
if ($countNewline) { |
604
|
3420
|
50
|
|
|
|
5309
|
$oNode =~ /\n([^\n]+?)\z/ and $colEnd += length($1); |
605
|
|
|
|
|
|
|
} else { |
606
|
20
|
|
|
|
|
42
|
$colEnd = length($oNode); |
607
|
|
|
|
|
|
|
} |
608
|
|
|
|
|
|
|
|
609
|
3440
|
|
|
|
|
940018
|
my $oLocationEnd = Devel::PerlySense::Document::Location->new( |
610
|
|
|
|
|
|
|
file => $oDocument->file, |
611
|
|
|
|
|
|
|
row => $rowEnd, |
612
|
|
|
|
|
|
|
col => $colEnd, |
613
|
|
|
|
|
|
|
); |
614
|
3440
|
|
|
|
|
42905
|
$oLocation->rhProperty->{oLocationEnd} = $oLocationEnd; |
615
|
|
|
|
|
|
|
|
616
|
3440
|
|
|
|
|
16509
|
return($oLocation); |
617
|
|
|
|
|
|
|
} |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
1; |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
__END__ |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
=encoding utf8 |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
=head1 AUTHOR |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
Johan Lindstrom, C<< <johanl@cpan.org> >> |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
=head1 BUGS |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
640
|
|
|
|
|
|
|
C<bug-devel-perlysense@rt.cpan.org>, or through the web interface at |
641
|
|
|
|
|
|
|
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Devel-PerlySense>. |
642
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
643
|
|
|
|
|
|
|
your bug as I make changes. |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
Copyright 2005 Johan Lindstrom, All Rights Reserved. |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
652
|
|
|
|
|
|
|
under the same terms as Perl itself. |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
=cut |