line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package PPIx::Refactor; |
2
|
|
|
|
|
|
|
$PPIx::Refactor::VERSION = '0.08'; |
3
|
|
|
|
|
|
|
|
4
|
2
|
|
|
2
|
|
30748
|
use Moo; |
|
2
|
|
|
|
|
19331
|
|
|
2
|
|
|
|
|
8
|
|
5
|
2
|
|
|
2
|
|
3348
|
use Path::Tiny; |
|
2
|
|
|
|
|
19631
|
|
|
2
|
|
|
|
|
111
|
|
6
|
|
|
|
|
|
|
BEGIN { |
7
|
2
|
|
|
2
|
|
13
|
use File::Path; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
82
|
|
8
|
2
|
|
|
2
|
|
6
|
use constant { CACHE => '/tmp/ppix-refactor_cache', }; |
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
144
|
|
9
|
2
|
|
|
2
|
|
4
|
our $cache = CACHE; |
10
|
2
|
100
|
|
|
|
333
|
File::Path::mkpath($cache) unless -e CACHE; |
11
|
|
|
|
|
|
|
} |
12
|
|
|
|
|
|
|
|
13
|
2
|
|
|
2
|
|
912
|
use PPI; |
|
2
|
|
|
|
|
175777
|
|
|
2
|
|
|
|
|
73
|
|
14
|
2
|
|
|
2
|
|
733
|
use PPI::Cache path => CACHE; |
|
2
|
|
|
|
|
7463
|
|
|
2
|
|
|
|
|
11
|
|
15
|
2
|
|
|
2
|
|
992
|
use PPI::Find; |
|
2
|
|
|
|
|
1361
|
|
|
2
|
|
|
|
|
570
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 NAME |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
PPIx::Refactor - Hooks for refactoring perl via L |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use PPIx::Refactor; |
24
|
|
|
|
|
|
|
my $p = PPIx::Refactor->new(file => '/path/to/perl/code/file.pl', |
25
|
|
|
|
|
|
|
ppi_find => sub { |
26
|
|
|
|
|
|
|
my ($elem, $doc) = @_; |
27
|
|
|
|
|
|
|
return 1 if $elem->class eq 'PPI::Statement::Sub', |
28
|
|
|
|
|
|
|
return 0; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
[ writer => \&found ]); |
31
|
|
|
|
|
|
|
my $finds = $p->finds; # for examining them interactively |
32
|
|
|
|
|
|
|
$p->rewrite; # rewrites the file in place. You are using version control yes? |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 SUMMARY |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
This is a really simple module to make rewriting perl code via L |
37
|
|
|
|
|
|
|
debugger friendly and easy. See the test in |
38
|
|
|
|
|
|
|
L |
39
|
|
|
|
|
|
|
of this distribution for a working example. Pretty much all the real work |
40
|
|
|
|
|
|
|
happens in the coderef you set up in C<< $p->ppi_find >> and C<< $p->writer >>. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
For an example of a simple script for checking statements in code for being |
43
|
|
|
|
|
|
|
syntactically identical (i.e. a crude copypasta detector) see C< |
44
|
|
|
|
|
|
|
similar_statements.pl > in the examples directory of the distribution. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
NOTE L is used to store a cached representation of the source |
47
|
|
|
|
|
|
|
parse in C |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=head2 RATIONALE |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
Rewriting code via ppi is a fiddly pain. L provides a |
52
|
|
|
|
|
|
|
minimal interface so you can concentrate on the fiddlyness and minimise the |
53
|
|
|
|
|
|
|
pain. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head2 TODO |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
Would be nice to specify a rewriter via roles, and it would be nice to have |
58
|
|
|
|
|
|
|
$self in C<< $p->ppi_find >>. On the other hand rewrite/refactoring code like |
59
|
|
|
|
|
|
|
this can either be simple throwaways, or really really complicated. This |
60
|
|
|
|
|
|
|
code is so far optimised for the throwaway case. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=cut |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head2 ATTRIBUTES |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=head3 file |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
required string that coerces into a Path::Tiny |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=cut |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
has file => ( |
73
|
|
|
|
|
|
|
is => 'ro', |
74
|
|
|
|
|
|
|
coerce => sub { |
75
|
|
|
|
|
|
|
path($_[0]); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=head3 doc |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
lazily built PPI::Document |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=cut |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
has doc => ( |
86
|
|
|
|
|
|
|
is => 'ro', |
87
|
|
|
|
|
|
|
lazy => 1, |
88
|
|
|
|
|
|
|
default => sub { |
89
|
|
|
|
|
|
|
my ($self) = @_; |
90
|
|
|
|
|
|
|
return PPI::Document::File->new($self->file->stringify); |
91
|
|
|
|
|
|
|
}, |
92
|
|
|
|
|
|
|
); |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=head3 element |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
If you're using prior finds (e.g. subroutines you're trying to analyse) |
97
|
|
|
|
|
|
|
you'll want to pass an element into new rather than a doc. Element |
98
|
|
|
|
|
|
|
defaults to the document you passed in. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=cut |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
has element => ( |
103
|
|
|
|
|
|
|
is => 'ro', |
104
|
|
|
|
|
|
|
lazy => 1, |
105
|
|
|
|
|
|
|
builder => sub { |
106
|
2
|
|
|
2
|
|
38
|
$_[0]->doc; |
107
|
|
|
|
|
|
|
}, |
108
|
|
|
|
|
|
|
); |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=head3 ppi_find |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
required coderef with which to find the elements of interest |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=cut |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
has ppi_find => ( |
117
|
|
|
|
|
|
|
is => 'ro', |
118
|
|
|
|
|
|
|
# isa CodeRef |
119
|
|
|
|
|
|
|
required => 1, |
120
|
|
|
|
|
|
|
); |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head3 writer |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
optional coderef with which to rewrite the code. |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=cut |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
has writer => ( |
130
|
|
|
|
|
|
|
is => 'ro', |
131
|
|
|
|
|
|
|
default => sub {}, |
132
|
|
|
|
|
|
|
); |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head3 finds |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
lazy built arrayref of all the elements of interest found |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=cut |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
has finds => ( |
141
|
|
|
|
|
|
|
is => 'ro', |
142
|
|
|
|
|
|
|
lazy => 1, |
143
|
|
|
|
|
|
|
default => sub { |
144
|
|
|
|
|
|
|
my ($self) = @_; |
145
|
|
|
|
|
|
|
my $find = PPI::Find->new($self->ppi_find); |
146
|
|
|
|
|
|
|
my @results = $find->in($self->element); |
147
|
|
|
|
|
|
|
return \@results; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
); |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=head1 METHODS |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head2 $self->rewrite |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
Worker sub that rewrites the code. Operates on what it finds in |
156
|
|
|
|
|
|
|
C<<$self->finds>> |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=cut |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub rewrite { |
161
|
1
|
|
|
1
|
1
|
240
|
my ($self) = @_; |
162
|
1
|
|
|
|
|
18
|
$self->writer->($self->finds); |
163
|
1
|
|
|
|
|
40
|
$self->element->save($self->file); |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=head2 $self->dump($elem, $whitespace); |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
For debugging. Prints a dump of the passed in element. If C<$whitespace> |
169
|
|
|
|
|
|
|
is true it will include whitespace in the dump. Defaults to false. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=cut |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub dump { |
174
|
0
|
|
|
0
|
1
|
|
my ($self, $doc, $whitespace) = @_; |
175
|
0
|
|
0
|
|
|
|
$whitespace ||=0; |
176
|
0
|
|
|
|
|
|
my $dump = PPI::Dumper->new($doc, whitespace => $whitespace); |
177
|
0
|
|
|
|
|
|
$dump->print; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head1 AUTHOR |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Kieren Diment, C<< >> |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=head1 BUGS |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
Please report any bugs or feature requests via github: |
188
|
|
|
|
|
|
|
L. |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=head1 SUPPORT |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Jump on to #web-simple on irc.perl.org |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
Copyright 2015 Kieren Diment. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
202
|
|
|
|
|
|
|
under the same terms as perl itself. |
203
|
|
|
|
|
|
|
=cut |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
1; |