line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Perl::Tidy::Sweetened::Keyword::Block; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# ABSTRACT: Perl::Tidy::Sweetened filter plugin to define new subroutine and class keywords |
4
|
|
|
|
|
|
|
|
5
|
15
|
|
|
15
|
|
370
|
use 5.010; # Needed for balanced parens matching with qr/(?-1)/ |
|
15
|
|
|
|
|
56
|
|
6
|
15
|
|
|
15
|
|
83
|
use strict; |
|
15
|
|
|
|
|
31
|
|
|
15
|
|
|
|
|
301
|
|
7
|
15
|
|
|
15
|
|
65
|
use warnings; |
|
15
|
|
|
|
|
46
|
|
|
15
|
|
|
|
|
361
|
|
8
|
15
|
|
|
15
|
|
95
|
use Carp; |
|
15
|
|
|
|
|
43
|
|
|
15
|
|
|
|
|
16026
|
|
9
|
|
|
|
|
|
|
$|++; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '1.20'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# Regex to match balanced params. Reproduced from Regexp::Common to avoid |
14
|
|
|
|
|
|
|
# adding a non-core dependency. |
15
|
|
|
|
|
|
|
# $RE{balanced}{-parens=>'()'}; |
16
|
|
|
|
|
|
|
# The (?-1) construct requires 5.010 |
17
|
|
|
|
|
|
|
our $Paren = '(?:((?:\((?:(?>[^\(\)]+)|(?-1))*\))))'; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new { |
20
|
180
|
|
|
180
|
0
|
697
|
my ( $class, %args ) = @_; |
21
|
180
|
50
|
|
|
|
440
|
croak 'keyword not specified' if not exists $args{keyword}; |
22
|
180
|
50
|
|
|
|
341
|
croak 'marker not specified' if not exists $args{marker}; |
23
|
180
|
50
|
|
|
|
342
|
croak 'replacement not specified' if not exists $args{replacement}; |
24
|
180
|
50
|
|
|
|
318
|
$args{clauses} = [] unless exists $args{clauses}; |
25
|
180
|
|
|
|
|
1110
|
return bless {%args}, $class; |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
1459
|
|
|
1459
|
1
|
4140
|
sub keyword { return $_[0]->{keyword} } |
29
|
1446
|
|
|
1446
|
1
|
3151
|
sub marker { return $_[0]->{marker} } |
30
|
1446
|
|
|
1446
|
1
|
3209
|
sub replacement { return $_[0]->{replacement} } |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub emit_placeholder { |
33
|
138
|
|
|
138
|
0
|
824
|
my ( $self, $subname, $brace, $clauses ) = @_; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Store the signature and returns() for later use |
36
|
138
|
|
|
|
|
736
|
my $id = sprintf "%03d", $self->{counter}++; |
37
|
138
|
|
|
|
|
432
|
$self->{store_clause}->{$id} = $clauses; |
38
|
138
|
|
|
|
|
340
|
$self->{store_sub}->{$id} = $subname; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# Turns 'my_method_name' into 'SUB004hod_name' |
41
|
138
|
|
|
|
|
337
|
my $marker = $self->marker . $id; |
42
|
138
|
|
|
|
|
399
|
substr( $subname, 0, length($marker), $marker ); |
43
|
|
|
|
|
|
|
|
44
|
138
|
|
|
|
|
327
|
return sprintf '%s %s %s', $self->replacement, $marker, $brace; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub emit_keyword { |
48
|
138
|
|
|
138
|
0
|
640
|
my ( $self, $brace, $id ) = @_; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Get the signature and returns() from store |
51
|
138
|
|
|
|
|
407
|
my $clauses = $self->{store_clause}->{$id}; |
52
|
|
|
|
|
|
|
|
53
|
138
|
|
|
|
|
354
|
my $subname = $self->{store_sub}->{$id}; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# Combine clauses (parameter list, returns(), etc) into a string separate |
56
|
|
|
|
|
|
|
# each with a space and lead with a space if there are any |
57
|
138
|
|
|
|
|
380
|
my $clause = join ' ', grep { length $_ } @$clauses; |
|
651
|
|
|
|
|
1285
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# FIXME: This forces space between sub/func/method name and clauses list |
60
|
|
|
|
|
|
|
# (ignores perltidy settings) |
61
|
138
|
100
|
|
|
|
674
|
$clause = ' ' . $clause if length $clause; |
62
|
|
|
|
|
|
|
|
63
|
138
|
|
|
|
|
387
|
return sprintf '%s %s%s%s', $self->keyword, $subname, $clause, $brace; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub emit_csc { |
67
|
13
|
|
|
13
|
0
|
29
|
my ( $self, $id, $cscp ) = @_; |
68
|
13
|
|
|
|
|
28
|
return sprintf "%s %s %s", $cscp, $self->keyword, $self->{store_sub}->{$_}; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub clauses { |
72
|
1308
|
|
|
1308
|
1
|
1916
|
my $self = shift; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# Create a regex (as a string) for all the clauses (ie, parameter list, |
75
|
|
|
|
|
|
|
# returns(), etc). |
76
|
1308
|
|
|
|
|
2026
|
my $clause_re = ''; |
77
|
1308
|
|
|
|
|
1971
|
my $i = 0; |
78
|
1308
|
|
|
|
|
1814
|
for my $clause ( @{ $self->{clauses} } ) { |
|
1308
|
|
|
|
|
2925
|
|
79
|
2943
|
|
|
|
|
5443
|
$clause =~ s{PAREN}{$Paren}g; |
80
|
|
|
|
|
|
|
|
81
|
2943
|
|
|
|
|
5955
|
$clause_re .= "(?<clause_$i> $clause ) \\s* \n"; |
82
|
2943
|
|
|
|
|
5119
|
$i++; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
1308
|
|
|
|
|
76183
|
return $clause_re; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub identifier { # method or package identifier |
89
|
2616
|
|
|
2616
|
0
|
4118
|
my $self = shift; |
90
|
|
|
|
|
|
|
|
91
|
2616
|
|
|
|
|
4525
|
return '[$@%]? \w+ (?: ::\w+ )*'; # words, possibly with twigil and/or separated by :: |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub prefilter { |
95
|
1308
|
|
|
1308
|
0
|
2792
|
my ( $self, $code ) = @_; |
96
|
1308
|
|
|
|
|
2425
|
my $keyword = $self->keyword; |
97
|
1308
|
|
|
|
|
2456
|
my $subname = $self->identifier; |
98
|
|
|
|
|
|
|
|
99
|
1308
|
|
|
|
|
2189
|
$code =~ s{ |
100
|
|
|
|
|
|
|
^\s*\K # okay to have leading whitespace (preserve) |
101
|
|
|
|
|
|
|
$keyword \s+ # the "func/method" keyword |
102
|
|
|
|
|
|
|
(?<subname> $subname) # the function name or class name (needs ::) |
103
|
|
|
|
|
|
|
(?!\w|\s*=>) \s* # check to make sure this isn't a sub call with params |
104
|
1308
|
|
|
|
|
2384
|
@{[ $self->clauses ]} # any clauses defined (ie, a parameter list) |
105
|
|
|
|
|
|
|
(?<brace> .*?) # anything else (ie, comments) including brace |
106
|
|
|
|
|
|
|
$ |
107
|
|
|
|
|
|
|
}{ |
108
|
138
|
|
|
|
|
432
|
my $i = 0; |
109
|
138
|
|
|
|
|
283
|
my $clauses = []; |
110
|
138
|
|
|
|
|
1336
|
while( exists $+{"clause_$i"} ){ |
111
|
|
|
|
|
|
|
## warn "# clause_$i: " . $+{"clause_$i"} . "\n"; |
112
|
651
|
|
|
|
|
2790
|
push @$clauses, $+{"clause_$i"}; |
113
|
651
|
|
|
|
|
2847
|
$i++; |
114
|
|
|
|
|
|
|
} |
115
|
138
|
|
|
|
|
726
|
$self->emit_placeholder( $+{subname}, $+{brace}, $clauses ) |
116
|
|
|
|
|
|
|
}egmx; |
117
|
|
|
|
|
|
|
|
118
|
1308
|
|
|
|
|
7210
|
return $code; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub postfilter { |
122
|
1308
|
|
|
1308
|
0
|
2820
|
my ( $self, $code, $args ) = @_; |
123
|
1308
|
|
|
|
|
2509
|
my $marker = $self->marker; |
124
|
1308
|
|
|
|
|
2830
|
my $replacement = $self->replacement; |
125
|
1308
|
|
|
|
|
2413
|
my $subname = $self->identifier; |
126
|
1308
|
|
|
|
|
1955
|
my @ids; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# Convert back to method |
129
|
1308
|
|
|
|
|
64299
|
$code =~ s{ |
130
|
|
|
|
|
|
|
^\s*\K # preserve leading whitespace |
131
|
|
|
|
|
|
|
$replacement \s+ # keyword was converted to sub/package |
132
|
|
|
|
|
|
|
$marker # |
133
|
|
|
|
|
|
|
(?<id> \d\d\d) # the identifier |
134
|
|
|
|
|
|
|
[\w:]* \b # the rest of the orignal sub/package name |
135
|
|
|
|
|
|
|
(?<newline> \n? \s* ) # possible newline and indentation |
136
|
|
|
|
|
|
|
(?<brace> .*? ) [ ]* # opening brace on followed orig comments |
137
|
|
|
|
|
|
|
[ ]* # trailing spaces (not all whitespace) |
138
|
|
|
|
|
|
|
}{ |
139
|
138
|
|
|
|
|
1216
|
push @ids, $+{id}; |
140
|
138
|
|
|
|
|
1581
|
$self->emit_keyword( $+{newline} . $+{brace}, $+{id} ); |
141
|
|
|
|
|
|
|
}egmx; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# Restore the orig sub name when inserted via the -csc flag |
144
|
1308
|
|
100
|
|
|
7375
|
my $cscp = $args->{'-cscp'} || '## end'; |
145
|
|
|
|
|
|
|
$code =~ s{ |
146
|
|
|
|
|
|
|
\Q${cscp}\E \s sub \s ${marker} $_ |
147
|
|
|
|
|
|
|
}{ |
148
|
13
|
|
|
|
|
46
|
$self->emit_csc( $_, $cscp ); |
149
|
1308
|
|
|
|
|
5075
|
}egx for @ids; |
150
|
|
|
|
|
|
|
|
151
|
1308
|
|
|
|
|
4989
|
return $code; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
1; |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
__END__ |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=pod |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head1 NAME |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Perl::Tidy::Sweetened::Keyword::Block - Perl::Tidy::Sweetened filter plugin to define new subroutine and class keywords |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=head1 VERSION |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
version 1.20 |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head1 SYNOPSIS |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
our $plugins = Perl::Tidy::Sweetened::Pluggable->new(); |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
$plugins->add_filter( |
173
|
|
|
|
|
|
|
Perl::Tidy::Sweetened::Keyword::Block->new( |
174
|
|
|
|
|
|
|
keyword => 'method', |
175
|
|
|
|
|
|
|
marker => 'METHOD', |
176
|
|
|
|
|
|
|
replacement => 'sub', |
177
|
|
|
|
|
|
|
clauses => [ 'PAREN?', '(returns \s* PAREN)?' ], |
178
|
|
|
|
|
|
|
) ); |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=head1 DESCRIPTION |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
This is a Perl::Tidy::Sweetened filter which enables the definition of |
183
|
|
|
|
|
|
|
arbitrary keywords for subroutines with any number of potential signature |
184
|
|
|
|
|
|
|
definitions. New accepts: |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=over 4 |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=item keyword |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
keyword => 'method' |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Declares a new keyword (in this example the "method" keyword). |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=item marker |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
marker => 'METHOD' |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Provides a text marker to be used to flag the new keywords during |
199
|
|
|
|
|
|
|
C<prefilter>. The source code will be filtered prior to formatting by |
200
|
|
|
|
|
|
|
Perl::Tidy such that: |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
method foo { |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
is turned into: |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub foo { # __METHOD 1 |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=item replacement |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
replacement => 'sub' |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Will convert the keyword to a C<sub> as shown above. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=item clauses |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
clauses => [ 'PAREN?' ] |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Provides a list of strings which will be turned into a regex to capture |
221
|
|
|
|
|
|
|
additional clauses. The regex will include the 'xm' flags (so be sure to escape |
222
|
|
|
|
|
|
|
spaces). The clause can be marked optional with '?'. The special text "PAREN" |
223
|
|
|
|
|
|
|
can be used to capture a balanced parenthetical. |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
This example will capture a parameter list enclosed by parenthesis, ie: |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
method foo (Int $i) { |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
No formatting is done on the clauses at this time. The order of declaration |
231
|
|
|
|
|
|
|
is significant. |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=back |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=head1 AUTHOR |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
Mark Grimes <mgrimes@cpan.org> |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=head1 SOURCE |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Source repository is at L<https://github.com/mvgrimes/Perl-Tidy-Sweetened>. |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=head1 BUGS |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
Please report any bugs or feature requests on the bugtracker website L<https://github.com/mvgrimes/Perl-Tidy-Sweetened/issues> |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
When submitting a bug or request, please include a test-file or a |
248
|
|
|
|
|
|
|
patch to an existing test-file that illustrates the bug or desired |
249
|
|
|
|
|
|
|
feature. |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
This software is copyright (c) 2023 by Mark Grimes <mgrimes@cpan.org>. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
256
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=cut |