line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Perl::Tags::Naive; |
2
|
|
|
|
|
|
|
|
3
|
7
|
|
|
7
|
|
4268
|
use strict; use warnings; |
|
7
|
|
|
7
|
|
14
|
|
|
7
|
|
|
|
|
221
|
|
|
7
|
|
|
|
|
35
|
|
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
224
|
|
4
|
7
|
|
|
7
|
|
34
|
use parent 'Perl::Tags'; |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
59
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.32'; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 C<Perl::Tags::Naive> |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
A naive implementation. That is to say, it's based on the classic C<pltags.pl> |
11
|
|
|
|
|
|
|
script distributed with Perl, which is by and large a better bet than the |
12
|
|
|
|
|
|
|
results produced by C<ctags>. But a "better" approach may be to integrate this |
13
|
|
|
|
|
|
|
with PPI. |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head2 Subclassing |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
See L<TodoTagger> in the C<t/> directory of the distribution for a fully |
18
|
|
|
|
|
|
|
working example (tested in <t/02_subclass.t>). You may want to reuse parsers |
19
|
|
|
|
|
|
|
in the ::Naive package, or use all of the existing parsers and add your own. |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
package My::Tagger; |
22
|
|
|
|
|
|
|
use Perl::Tags; |
23
|
|
|
|
|
|
|
use parent 'Perl::Tags::Naive'; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub get_parsers { |
26
|
|
|
|
|
|
|
my $self = shift; |
27
|
|
|
|
|
|
|
return ( |
28
|
|
|
|
|
|
|
$self->can('todo_line'), # a new parser |
29
|
|
|
|
|
|
|
$self->SUPER::get_parsers(), # all ::Naive's parsers |
30
|
|
|
|
|
|
|
# or maybe... |
31
|
|
|
|
|
|
|
$self->can('variable'), # one of ::Naive's parsers |
32
|
|
|
|
|
|
|
); |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub todo_line { |
36
|
|
|
|
|
|
|
# your new parser code here! |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
sub package_line { |
39
|
|
|
|
|
|
|
# override one of ::Naive's parsers |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Because ::Naive uses C<can('parser')> instead of C<\&parser>, you |
43
|
|
|
|
|
|
|
can just override a particular parser by redefining in the subclass. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=head2 C<get_tags_for_file> |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
::Naive uses a simple line-by-line analysis of Perl code, comparing |
48
|
|
|
|
|
|
|
each line against an array of parsers returned by the L<get_parsers> method. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
The first of these parsers that matches (if any) will return the |
51
|
|
|
|
|
|
|
tag/control to be registred by the tagger. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=cut |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
{ |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
my @start_tags = qw(pod head1 head2 head3 head4 over item back begin |
58
|
|
|
|
|
|
|
end for encoding); |
59
|
|
|
|
|
|
|
my @end_tags = qw(cut); |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
my $startpod = '^=(?:' . join('|', @start_tags) . ')\b'; |
62
|
|
|
|
|
|
|
my $endpod = '^=(?:' . join('|', @end_tags) . ')\b'; |
63
|
|
|
|
|
|
|
|
64
|
12
|
|
|
12
|
0
|
459
|
sub STARTPOD { qr/$startpod/ } |
65
|
12
|
|
|
12
|
0
|
93
|
sub ENDPOD { qr/$endpod/ } |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub get_tags_for_file { |
69
|
12
|
|
|
12
|
1
|
23
|
my ($self, $file) = @_; |
70
|
|
|
|
|
|
|
|
71
|
12
|
|
|
|
|
59
|
my @parsers = $self->get_parsers(); |
72
|
|
|
|
|
|
|
|
73
|
12
|
50
|
|
|
|
781
|
open (my $IN, '<', $file) or die "Couldn't open file `$file`: $!\n"; |
74
|
|
|
|
|
|
|
|
75
|
12
|
|
|
|
|
37
|
my $start = STARTPOD(); |
76
|
12
|
|
|
|
|
34
|
my $end = ENDPOD(); |
77
|
|
|
|
|
|
|
|
78
|
12
|
|
|
|
|
21
|
my @all_tags; |
79
|
|
|
|
|
|
|
|
80
|
12
|
|
|
|
|
266
|
while (<$IN>) { |
81
|
190
|
100
|
|
|
|
534
|
next if (/$start/o .. /$end/o); |
82
|
141
|
|
|
|
|
171
|
chomp; |
83
|
141
|
|
|
|
|
213
|
my $statement = my $line = $_; |
84
|
141
|
|
|
|
|
199
|
PARSELOOP: for my $parser (@parsers) { |
85
|
1398
|
|
|
|
|
2401
|
my @tags = $parser->( |
86
|
|
|
|
|
|
|
$self, |
87
|
|
|
|
|
|
|
$line, |
88
|
|
|
|
|
|
|
$statement, |
89
|
|
|
|
|
|
|
$file |
90
|
|
|
|
|
|
|
); |
91
|
1398
|
|
|
|
|
2389
|
push @all_tags, @tags; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
} |
94
|
12
|
|
|
|
|
290
|
return @all_tags; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=head2 C<get_parsers> |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
The following parsers are defined by this module. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=over 4 |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=cut |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub get_parsers { |
106
|
12
|
|
|
12
|
1
|
42
|
my $self = shift; |
107
|
|
|
|
|
|
|
return ( |
108
|
12
|
|
|
|
|
307
|
$self->can('trim'), |
109
|
|
|
|
|
|
|
$self->can('variable'), |
110
|
|
|
|
|
|
|
$self->can('package_line'), |
111
|
|
|
|
|
|
|
$self->can('sub_line'), |
112
|
|
|
|
|
|
|
$self->can('use_constant'), |
113
|
|
|
|
|
|
|
$self->can('use_line'), |
114
|
|
|
|
|
|
|
$self->can('label_line'), |
115
|
|
|
|
|
|
|
); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=item C<trim> |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
A filter rather than a parser, removes whitespace and comments. |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=cut |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub trim { |
125
|
141
|
|
|
141
|
1
|
149
|
shift; |
126
|
|
|
|
|
|
|
|
127
|
141
|
|
|
|
|
236
|
$_[1] =~ s/#.*//; |
128
|
141
|
|
|
|
|
419
|
$_[1] =~ s/^\s*//; |
129
|
141
|
|
|
|
|
638
|
$_[1] =~ s/\s*$//; |
130
|
|
|
|
|
|
|
|
131
|
141
|
|
|
|
|
240
|
return; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=item C<variable> |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Tags definitions of C<my>, C<our>, and C<local> variables. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Returns a L<Perl::Tags::Tag::Var> if found |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=cut |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub variable { |
143
|
|
|
|
|
|
|
|
144
|
141
|
|
|
141
|
1
|
223
|
my ($self, $line, $statement, $file) = @_; |
145
|
|
|
|
|
|
|
|
146
|
141
|
50
|
|
|
|
424
|
return unless $self->{do_variables}; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
|
149
|
141
|
100
|
66
|
|
|
666
|
if ($self->{var_continues} || $statement =~/^(my|our|local)\b/) { |
150
|
|
|
|
|
|
|
|
151
|
7
|
|
|
|
|
43
|
$self->{current}{var_continues} = ! ($statement=~/;$/); |
152
|
7
|
|
|
|
|
18
|
$statement =~s/=.*$//; |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
|
157
|
7
|
|
|
|
|
55
|
my @vars = $statement=~/[\$@%]((?:\w|:)+)\b/g; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
|
162
|
14
|
|
|
|
|
107
|
return map { |
163
|
7
|
|
|
|
|
16
|
Perl::Tags::Tag::Var->new( |
164
|
|
|
|
|
|
|
name => $_, |
165
|
|
|
|
|
|
|
file => $file, |
166
|
|
|
|
|
|
|
line => $line, |
167
|
|
|
|
|
|
|
linenum => $., |
168
|
|
|
|
|
|
|
); |
169
|
|
|
|
|
|
|
} @vars; |
170
|
|
|
|
|
|
|
} |
171
|
134
|
|
|
|
|
246
|
return; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=item C<package_line> |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Parse a package declaration, returning a L<Perl::Tags::Tag::Package> if found. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=cut |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
sub package_line { |
181
|
141
|
|
|
141
|
1
|
210
|
my ($self, $line, $statement, $file) = @_; |
182
|
|
|
|
|
|
|
|
183
|
141
|
100
|
|
|
|
338
|
if ($statement=~/^package\s+((?:\w|:)+)\b/) { |
184
|
|
|
|
|
|
|
return ( |
185
|
12
|
|
|
|
|
148
|
Perl::Tags::Tag::Package->new( |
186
|
|
|
|
|
|
|
name => $1, |
187
|
|
|
|
|
|
|
file => $file, |
188
|
|
|
|
|
|
|
line => $line, |
189
|
|
|
|
|
|
|
linenum => $., |
190
|
|
|
|
|
|
|
) |
191
|
|
|
|
|
|
|
); |
192
|
|
|
|
|
|
|
} |
193
|
129
|
|
|
|
|
240
|
return; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=item C<sub_line> |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Parse the declaration of a subroutine, returning a L<Perl::Tags::Tag::Sub> if found. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=cut |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub sub_line { |
203
|
141
|
|
|
141
|
1
|
207
|
my ($self, $line, $statement, $file) = @_; |
204
|
141
|
100
|
|
|
|
314
|
if ($statement=~/sub\s+(\w+)\b/) { |
205
|
|
|
|
|
|
|
return ( |
206
|
7
|
|
|
|
|
75
|
Perl::Tags::Tag::Sub->new( |
207
|
|
|
|
|
|
|
name => $1, |
208
|
|
|
|
|
|
|
file => $file, |
209
|
|
|
|
|
|
|
line => $line, |
210
|
|
|
|
|
|
|
linenum => $., |
211
|
|
|
|
|
|
|
) |
212
|
|
|
|
|
|
|
); |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
134
|
|
|
|
|
217
|
return; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=item C<use_constant> |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Parse a use constant directive |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=cut |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub use_constant { |
225
|
141
|
|
|
141
|
1
|
213
|
my ($self, $line, $statement, $file) = @_; |
226
|
141
|
50
|
|
|
|
274
|
if ($statement =~/^\s*use\s+constant\s+([^=[:space:]]+)/) { |
227
|
|
|
|
|
|
|
return ( |
228
|
0
|
|
|
|
|
0
|
Perl::Tags::Tag::Constant->new( |
229
|
|
|
|
|
|
|
name => $1, |
230
|
|
|
|
|
|
|
file => $file, |
231
|
|
|
|
|
|
|
line => $line, |
232
|
|
|
|
|
|
|
linenum => $., |
233
|
|
|
|
|
|
|
) |
234
|
|
|
|
|
|
|
); |
235
|
|
|
|
|
|
|
} |
236
|
141
|
|
|
|
|
284
|
return; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=item C<use_line> |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Parse a use, require, and also a use_ok line (from Test::More). |
242
|
|
|
|
|
|
|
Uses a dummy tag (L<Perl::Tags::Tag::Recurse> to do so). |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=cut |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub use_line { |
247
|
141
|
|
|
141
|
1
|
196
|
my ($self, $line, $statement, $file) = @_; |
248
|
|
|
|
|
|
|
|
249
|
141
|
|
|
|
|
149
|
my @ret; |
250
|
141
|
100
|
|
|
|
359
|
if ($statement=~/^(?:use|require)(_ok\(?)?\s+(.*)/) { |
251
|
19
|
|
|
|
|
78
|
my @packages = split /\s+/, $2; |
252
|
19
|
50
|
|
|
|
66
|
@packages = ($packages[0]) if $1; |
253
|
|
|
|
|
|
|
|
254
|
19
|
|
|
|
|
37
|
for (@packages) { |
255
|
33
|
|
|
|
|
60
|
s/^q[wq]?[[:punct:]]//; |
256
|
33
|
|
|
|
|
117
|
/((?:\w|:)+)/; |
257
|
33
|
50
|
|
|
|
259
|
$1 and push @ret, Perl::Tags::Tag::Recurse->new( |
258
|
|
|
|
|
|
|
name => $1, |
259
|
|
|
|
|
|
|
line=>'dummy' ); |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
} |
262
|
141
|
|
|
|
|
276
|
return @ret; |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=item C<label_line> |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
Parse label declaration |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=cut |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub label_line { |
272
|
141
|
|
|
141
|
1
|
208
|
my ($self, $line, $statement, $file) = @_; |
273
|
141
|
50
|
|
|
|
340
|
if ($statement=~/^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:(?:[^:]|$)/) { |
274
|
|
|
|
|
|
|
return ( |
275
|
0
|
|
|
|
|
0
|
Perl::Tags::Tag::Label->new( |
276
|
|
|
|
|
|
|
name => $1, |
277
|
|
|
|
|
|
|
file => $file, |
278
|
|
|
|
|
|
|
line => $line, |
279
|
|
|
|
|
|
|
linenum => $., |
280
|
|
|
|
|
|
|
) |
281
|
|
|
|
|
|
|
); |
282
|
|
|
|
|
|
|
} |
283
|
141
|
|
|
|
|
231
|
return; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=back |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=cut |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
1; |
291
|
|
|
|
|
|
|
|