| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package PPI::Document; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=pod |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
PPI::Document - Object representation of a Perl document |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 INHERITANCE |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
PPI::Document |
|
12
|
|
|
|
|
|
|
isa PPI::Node |
|
13
|
|
|
|
|
|
|
isa PPI::Element |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
use PPI; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# Load a document from a file |
|
20
|
|
|
|
|
|
|
my $Document = PPI::Document->new('My/Module.pm'); |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Strip out comments |
|
23
|
|
|
|
|
|
|
$Document->prune('PPI::Token::Comment'); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# Find all the named subroutines |
|
26
|
|
|
|
|
|
|
my $sub_nodes = $Document->find( |
|
27
|
|
|
|
|
|
|
sub { $_[1]->isa('PPI::Statement::Sub') and $_[1]->name } |
|
28
|
|
|
|
|
|
|
); |
|
29
|
|
|
|
|
|
|
my @sub_names = map { $_->name } @$sub_nodes; |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Save the file |
|
32
|
|
|
|
|
|
|
$Document->save('My/Module.pm.stripped'); |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
The C class represents a single Perl "document". A |
|
37
|
|
|
|
|
|
|
C object acts as a root L, with some |
|
38
|
|
|
|
|
|
|
additional methods for loading and saving, and working with |
|
39
|
|
|
|
|
|
|
the line/column locations of Elements within a file. |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
The exemption to its L-like behavior this is that a |
|
42
|
|
|
|
|
|
|
C object can NEVER have a parent node, and is always |
|
43
|
|
|
|
|
|
|
the root node in a tree. |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=head2 Storable Support |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
C implements the necessary C and |
|
48
|
|
|
|
|
|
|
C hooks to provide native support for L, |
|
49
|
|
|
|
|
|
|
if you have it installed. |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
However if you want to clone a Document, you are highly recommended |
|
52
|
|
|
|
|
|
|
to use the C<$Document-Eclone> method rather than Storable's |
|
53
|
|
|
|
|
|
|
C function (although C should still work). |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head1 METHODS |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
Most of the things you are likely to want to do with a Document are |
|
58
|
|
|
|
|
|
|
probably going to involve the methods from L class, of which |
|
59
|
|
|
|
|
|
|
this is a subclass. |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
The methods listed here are the remaining few methods that are truly |
|
62
|
|
|
|
|
|
|
Document-specific. |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=cut |
|
65
|
|
|
|
|
|
|
|
|
66
|
63
|
|
|
63
|
|
621951
|
use strict; |
|
|
63
|
|
|
|
|
201
|
|
|
|
63
|
|
|
|
|
1427
|
|
|
67
|
63
|
|
|
63
|
|
251
|
use Carp (); |
|
|
63
|
|
|
|
|
108
|
|
|
|
63
|
|
|
|
|
1196
|
|
|
68
|
63
|
|
|
63
|
|
249
|
use List::Util 1.33 (); |
|
|
63
|
|
|
|
|
1134
|
|
|
|
63
|
|
|
|
|
1360
|
|
|
69
|
63
|
|
|
63
|
|
3770
|
use Params::Util 1.00 qw{_SCALAR0 _ARRAY0 _INSTANCE}; |
|
|
63
|
|
|
|
|
47300
|
|
|
|
63
|
|
|
|
|
2898
|
|
|
70
|
63
|
|
|
63
|
|
329
|
use Digest::MD5 (); |
|
|
63
|
|
|
|
|
100
|
|
|
|
63
|
|
|
|
|
1163
|
|
|
71
|
63
|
|
|
63
|
|
4555
|
use PPI::Util (); |
|
|
63
|
|
|
|
|
119
|
|
|
|
63
|
|
|
|
|
978
|
|
|
72
|
63
|
|
|
63
|
|
5747
|
use PPI (); |
|
|
63
|
|
|
|
|
133
|
|
|
|
63
|
|
|
|
|
1023
|
|
|
73
|
63
|
|
|
63
|
|
269
|
use PPI::Node (); |
|
|
63
|
|
|
|
|
103
|
|
|
|
63
|
|
|
|
|
2033
|
|
|
74
|
|
|
|
|
|
|
|
|
75
|
63
|
|
|
63
|
|
301
|
use overload 'bool' => \&PPI::Util::TRUE; |
|
|
63
|
|
|
|
|
110
|
|
|
|
63
|
|
|
|
|
505
|
|
|
76
|
63
|
|
|
63
|
|
3912
|
use overload '""' => 'content'; |
|
|
63
|
|
|
|
|
169
|
|
|
|
63
|
|
|
|
|
236
|
|
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
our $VERSION = '1.275'; |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
our ( $errstr, @ISA ) = ( "", "PPI::Node" ); |
|
81
|
|
|
|
|
|
|
|
|
82
|
63
|
|
|
63
|
|
22265
|
use PPI::Document::Fragment (); |
|
|
63
|
|
|
|
|
173
|
|
|
|
63
|
|
|
|
|
1564
|
|
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# Document cache |
|
85
|
|
|
|
|
|
|
my $CACHE; |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Convenience constants related to constants |
|
88
|
63
|
|
|
63
|
|
323
|
use constant LOCATION_LINE => 0; |
|
|
63
|
|
|
|
|
95
|
|
|
|
63
|
|
|
|
|
3183
|
|
|
89
|
63
|
|
|
63
|
|
297
|
use constant LOCATION_CHARACTER => 1; |
|
|
63
|
|
|
|
|
102
|
|
|
|
63
|
|
|
|
|
2290
|
|
|
90
|
63
|
|
|
63
|
|
282
|
use constant LOCATION_COLUMN => 2; |
|
|
63
|
|
|
|
|
96
|
|
|
|
63
|
|
|
|
|
2254
|
|
|
91
|
63
|
|
|
63
|
|
283
|
use constant LOCATION_LOGICAL_LINE => 3; |
|
|
63
|
|
|
|
|
108
|
|
|
|
63
|
|
|
|
|
2298
|
|
|
92
|
63
|
|
|
63
|
|
284
|
use constant LOCATION_LOGICAL_FILE => 4; |
|
|
63
|
|
|
|
|
90
|
|
|
|
63
|
|
|
|
|
157862
|
|
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
##################################################################### |
|
99
|
|
|
|
|
|
|
# Constructor and Static Methods |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=pod |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=head2 new |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# Simple construction |
|
106
|
|
|
|
|
|
|
$doc = PPI::Document->new( $filename ); |
|
107
|
|
|
|
|
|
|
$doc = PPI::Document->new( \$source ); |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# With the readonly attribute set |
|
110
|
|
|
|
|
|
|
$doc = PPI::Document->new( $filename, |
|
111
|
|
|
|
|
|
|
readonly => 1, |
|
112
|
|
|
|
|
|
|
); |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
The C constructor takes as argument a variety of different sources of |
|
115
|
|
|
|
|
|
|
Perl code, and creates a single cohesive Perl C |
|
116
|
|
|
|
|
|
|
for it. |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
If passed a file name as a normal string, it will attempt to load the |
|
119
|
|
|
|
|
|
|
document from the file. |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
If passed a reference to a C, this is taken to be source code and |
|
122
|
|
|
|
|
|
|
parsed directly to create the document. |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
If passed zero arguments, a "blank" document will be created that contains |
|
125
|
|
|
|
|
|
|
no content at all. |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
In all cases, the document is considered to be "anonymous" and not tied back |
|
128
|
|
|
|
|
|
|
to where it was created from. Specifically, if you create a PPI::Document from |
|
129
|
|
|
|
|
|
|
a filename, the document will B remember where it was created from. |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
The constructor also takes attribute flags. |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
At this time, the only available attribute is the C flag. |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Setting C to true will allow various systems to provide |
|
136
|
|
|
|
|
|
|
additional optimisations and caching. Note that because C is an |
|
137
|
|
|
|
|
|
|
optimisation flag, it is off by default and you will need to explicitly |
|
138
|
|
|
|
|
|
|
enable it. |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Returns a C object, or C if parsing fails. |
|
141
|
|
|
|
|
|
|
L objects can also be thrown if there are parsing problems. |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub new { |
|
146
|
33406
|
|
|
33406
|
1
|
7738195
|
local $_; # An extra one, just in case |
|
147
|
33406
|
50
|
|
|
|
62335
|
my $class = ref $_[0] ? ref shift : shift; |
|
148
|
|
|
|
|
|
|
|
|
149
|
33406
|
100
|
|
|
|
60009
|
unless ( @_ ) { |
|
150
|
16704
|
|
|
|
|
39123
|
my $self = $class->SUPER::new; |
|
151
|
16704
|
|
|
|
|
34492
|
$self->{readonly} = ! 1; |
|
152
|
16704
|
|
|
|
|
22447
|
$self->{tab_width} = 1; |
|
153
|
16704
|
|
|
|
|
33038
|
return $self; |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# Check constructor attributes |
|
157
|
16702
|
|
|
|
|
20470
|
my $source = shift; |
|
158
|
16702
|
|
|
|
|
23851
|
my %attr = @_; |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# Check the data source |
|
161
|
16702
|
50
|
|
|
|
57937
|
if ( ! defined $source ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
162
|
0
|
|
|
|
|
0
|
$class->_error("An undefined value was passed to PPI::Document::new"); |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
} elsif ( ! ref $source ) { |
|
165
|
|
|
|
|
|
|
# Catch people using the old API |
|
166
|
498
|
50
|
|
|
|
2249
|
if ( $source =~ /(?:\012|\015)/ ) { |
|
167
|
0
|
|
|
|
|
0
|
Carp::croak("API CHANGE: Source code should only be passed to PPI::Document->new as a SCALAR reference"); |
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# Save the filename |
|
171
|
498
|
|
66
|
|
|
2572
|
$attr{filename} ||= $source; |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# When loading from a filename, use the caching layer if it exists. |
|
174
|
498
|
100
|
|
|
|
1129
|
if ( $CACHE ) { |
|
175
|
3
|
|
|
|
|
8
|
my $file_contents = PPI::Util::_slurp( $source ); |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# Errors returned as plain string |
|
178
|
3
|
50
|
|
|
|
8
|
return $class->_error($file_contents) if !ref $file_contents; |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# Retrieve the document from the cache |
|
181
|
3
|
|
|
|
|
10
|
my $document = $CACHE->get_document($file_contents); |
|
182
|
3
|
100
|
|
|
|
13
|
return $class->_setattr( $document, %attr ) if $document; |
|
183
|
|
|
|
|
|
|
|
|
184
|
1
|
|
|
|
|
7
|
$document = PPI::Lexer->lex_source( $$file_contents ); |
|
185
|
1
|
50
|
|
|
|
5
|
if ( $document ) { |
|
186
|
|
|
|
|
|
|
# Save in the cache |
|
187
|
1
|
|
|
|
|
3
|
$CACHE->store_document( $document ); |
|
188
|
1
|
|
|
|
|
44
|
return $class->_setattr( $document, %attr ); |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
} else { |
|
191
|
495
|
|
|
|
|
2641
|
my $document = PPI::Lexer->lex_file( $source ); |
|
192
|
495
|
50
|
|
|
|
3303
|
return $class->_setattr( $document, %attr ) if $document; |
|
193
|
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
} elsif ( _SCALAR0($source) ) { |
|
196
|
16201
|
|
|
|
|
44728
|
my $document = PPI::Lexer->lex_source( $$source ); |
|
197
|
16201
|
100
|
|
|
|
65069
|
return $class->_setattr( $document, %attr ) if $document; |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
} elsif ( _ARRAY0($source) ) { |
|
200
|
3
|
|
|
|
|
8
|
$source = join '', map { "$_\n" } @$source; |
|
|
5
|
|
|
|
|
11
|
|
|
201
|
3
|
|
|
|
|
9
|
my $document = PPI::Lexer->lex_source( $source ); |
|
202
|
3
|
50
|
|
|
|
18
|
return $class->_setattr( $document, %attr ) if $document; |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
} else { |
|
205
|
0
|
|
|
|
|
0
|
$class->_error("Unknown object or reference was passed to PPI::Document::new"); |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# Pull and store the error from the lexer |
|
209
|
1
|
|
|
|
|
2
|
my $errstr; |
|
210
|
1
|
50
|
|
|
|
9
|
if ( _INSTANCE($@, 'PPI::Exception') ) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
211
|
1
|
|
|
|
|
3
|
$errstr = $@->message; |
|
212
|
|
|
|
|
|
|
} elsif ( $@ ) { |
|
213
|
0
|
|
|
|
|
0
|
$errstr = $@; |
|
214
|
0
|
|
|
|
|
0
|
$errstr =~ s/\sat line\s.+$//; |
|
215
|
|
|
|
|
|
|
} elsif ( PPI::Lexer->errstr ) { |
|
216
|
0
|
|
|
|
|
0
|
$errstr = PPI::Lexer->errstr; |
|
217
|
|
|
|
|
|
|
} else { |
|
218
|
0
|
|
|
|
|
0
|
$errstr = "Unknown error parsing Perl document"; |
|
219
|
|
|
|
|
|
|
} |
|
220
|
1
|
|
|
|
|
3
|
PPI::Lexer->_clear; |
|
221
|
1
|
|
|
|
|
3
|
$class->_error( $errstr ); |
|
222
|
|
|
|
|
|
|
} |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub load { |
|
225
|
0
|
|
|
0
|
0
|
0
|
Carp::croak("API CHANGE: File names should now be passed to PPI::Document->new to load a file"); |
|
226
|
|
|
|
|
|
|
} |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub _setattr { |
|
229
|
16701
|
|
|
16701
|
|
31113
|
my ($class, $document, %attr) = @_; |
|
230
|
16701
|
|
|
|
|
29682
|
$document->{readonly} = !! $attr{readonly}; |
|
231
|
16701
|
|
|
|
|
26467
|
$document->{filename} = $attr{filename}; |
|
232
|
16701
|
|
|
|
|
51728
|
return $document; |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=pod |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=head2 set_cache $cache |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
As of L 1.100, C supports parser caching. |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
The default cache class L provides a L-based |
|
242
|
|
|
|
|
|
|
caching or the parsed document based on the MD5 hash of the document as |
|
243
|
|
|
|
|
|
|
a string. |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
The static C method is used to set the cache object for |
|
246
|
|
|
|
|
|
|
C to use when loading documents. It takes as argument |
|
247
|
|
|
|
|
|
|
a L object (or something that C the same). |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
If passed C, this method will stop using the current cache, if any. |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
For more information on caching, see L. |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
Returns true on success, or C if not passed a valid param. |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=cut |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
sub set_cache { |
|
258
|
3
|
50
|
|
3
|
1
|
14
|
my $class = ref $_[0] ? ref shift : shift; |
|
259
|
|
|
|
|
|
|
|
|
260
|
3
|
100
|
|
|
|
6
|
if ( defined $_[0] ) { |
|
261
|
|
|
|
|
|
|
# Enable the cache |
|
262
|
2
|
50
|
|
|
|
15
|
my $object = _INSTANCE(shift, 'PPI::Cache') or return undef; |
|
263
|
2
|
|
|
|
|
3
|
$CACHE = $object; |
|
264
|
|
|
|
|
|
|
} else { |
|
265
|
|
|
|
|
|
|
# Disable the cache |
|
266
|
1
|
|
|
|
|
3
|
$CACHE = undef; |
|
267
|
|
|
|
|
|
|
} |
|
268
|
|
|
|
|
|
|
|
|
269
|
3
|
|
|
|
|
11
|
1; |
|
270
|
|
|
|
|
|
|
} |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=pod |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=head2 get_cache |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
If a document cache is currently set, the C method will |
|
277
|
|
|
|
|
|
|
return it. |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Returns a L object, or C if there is no cache |
|
280
|
|
|
|
|
|
|
currently set for C. |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=cut |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub get_cache { |
|
285
|
7
|
|
|
7
|
1
|
1133
|
$CACHE; |
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
##################################################################### |
|
293
|
|
|
|
|
|
|
# PPI::Document Instance Methods |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=pod |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=head2 filename |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
The C accessor returns the name of the file in which the document |
|
300
|
|
|
|
|
|
|
is stored. |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=cut |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub filename { |
|
305
|
255
|
|
|
255
|
1
|
1287
|
$_[0]->{filename}; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=pod |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=head2 readonly |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
The C attribute indicates if the document is intended to be |
|
313
|
|
|
|
|
|
|
read-only, and will never be modified. This is an advisory flag, that |
|
314
|
|
|
|
|
|
|
writers of L-related systems may or may not use to enable |
|
315
|
|
|
|
|
|
|
optimisations and caches for your document. |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Returns true if the document is read-only or false if not. |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=cut |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub readonly { |
|
322
|
4
|
|
|
4
|
1
|
1344
|
$_[0]->{readonly}; |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=pod |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head2 tab_width [ $width ] |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
In order to handle support for C correctly, C |
|
330
|
|
|
|
|
|
|
need to understand the concept of tabs and tab width. The C |
|
331
|
|
|
|
|
|
|
method is used to get and set the size of the tab width. |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
At the present time, PPI only supports "naive" (width 1) tabs, but we do |
|
334
|
|
|
|
|
|
|
plan on supporting arbitrary, default and auto-sensing tab widths later. |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
Returns the tab width as an integer, or Cs if you attempt to set the |
|
337
|
|
|
|
|
|
|
tab width. |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=cut |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
sub tab_width { |
|
342
|
55660
|
|
|
55660
|
1
|
57584
|
my $self = shift; |
|
343
|
55660
|
100
|
|
|
|
88497
|
return $self->{tab_width} unless @_; |
|
344
|
2
|
|
|
|
|
5
|
$self->{tab_width} = shift; |
|
345
|
|
|
|
|
|
|
} |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=pod |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=head2 save |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
$document->save( $file ) |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
The C method serializes the C object and saves the |
|
354
|
|
|
|
|
|
|
resulting Perl document to a file. Returns C on failure to open |
|
355
|
|
|
|
|
|
|
or write to the file. |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=cut |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
sub save { |
|
360
|
2
|
|
|
2
|
1
|
4
|
my $self = shift; |
|
361
|
2
|
|
|
|
|
5
|
local *FILE; |
|
362
|
2
|
50
|
|
|
|
131
|
open( FILE, '>', $_[0] ) or return undef; |
|
363
|
2
|
|
|
|
|
8
|
binmode FILE; |
|
364
|
2
|
50
|
|
|
|
17
|
print FILE $self->serialize or return undef; |
|
365
|
2
|
50
|
|
|
|
163
|
close FILE or return undef; |
|
366
|
2
|
|
|
|
|
18
|
return 1; |
|
367
|
|
|
|
|
|
|
} |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
=pod |
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=head2 serialize |
|
372
|
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
Unlike the C method, which shows only the immediate content |
|
374
|
|
|
|
|
|
|
within an element, Document objects also have to be able to be written |
|
375
|
|
|
|
|
|
|
out to a file again. |
|
376
|
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
When doing this we need to take into account some additional factors. |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
Primarily, we need to handle here-docs correctly, so that are written |
|
380
|
|
|
|
|
|
|
to the file in the expected place. |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
The C method generates the actual file content for a given |
|
383
|
|
|
|
|
|
|
Document object. The resulting string can be written straight to a file. |
|
384
|
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
Returns the serialized document as a string. |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=cut |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
sub serialize { |
|
390
|
7055
|
|
|
7055
|
1
|
286926
|
my $self = shift; |
|
391
|
7055
|
|
|
|
|
15288
|
my @tokens = $self->tokens; |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
# The here-doc content buffer |
|
394
|
7055
|
|
|
|
|
11395
|
my $heredoc = ''; |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# Start the main loop |
|
397
|
7055
|
|
|
|
|
8226
|
my $output = ''; |
|
398
|
7055
|
|
|
|
|
15005
|
foreach my $i ( 0 .. $#tokens ) { |
|
399
|
264430
|
|
|
|
|
267637
|
my $Token = $tokens[$i]; |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# Handle normal tokens |
|
402
|
264430
|
100
|
|
|
|
522203
|
unless ( $Token->isa('PPI::Token::HereDoc') ) { |
|
403
|
263827
|
|
|
|
|
356305
|
my $content = $Token->content; |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
# Handle the trivial cases |
|
406
|
263827
|
100
|
100
|
|
|
393991
|
unless ( $heredoc ne '' and $content =~ /\n/ ) { |
|
407
|
263411
|
|
|
|
|
268307
|
$output .= $content; |
|
408
|
263411
|
|
|
|
|
298709
|
next; |
|
409
|
|
|
|
|
|
|
} |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
# We have pending here-doc content that needs to be |
|
412
|
|
|
|
|
|
|
# inserted just after the first newline in the content. |
|
413
|
416
|
100
|
|
|
|
822
|
if ( $content eq "\n" ) { |
|
414
|
|
|
|
|
|
|
# Shortcut the most common case for speed |
|
415
|
294
|
|
|
|
|
516
|
$output .= $content . $heredoc; |
|
416
|
|
|
|
|
|
|
} else { |
|
417
|
|
|
|
|
|
|
# Slower and more general version |
|
418
|
122
|
|
|
|
|
559
|
$content =~ s/\n/\n$heredoc/; |
|
419
|
122
|
|
|
|
|
244
|
$output .= $content; |
|
420
|
|
|
|
|
|
|
} |
|
421
|
|
|
|
|
|
|
|
|
422
|
416
|
|
|
|
|
498
|
$heredoc = ''; |
|
423
|
416
|
|
|
|
|
668
|
next; |
|
424
|
|
|
|
|
|
|
} |
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
# This token is a HereDoc. |
|
427
|
|
|
|
|
|
|
# First, add the token content as normal, which in this |
|
428
|
|
|
|
|
|
|
# case will definitely not contain a newline. |
|
429
|
603
|
|
|
|
|
1247
|
$output .= $Token->content; |
|
430
|
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
# Pick up the indentation, which may be undef. |
|
432
|
603
|
|
100
|
|
|
1465
|
my $indentation = $Token->indentation || ''; |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
# Now add all of the here-doc content to the heredoc buffer. |
|
435
|
603
|
|
|
|
|
1245
|
foreach my $line ( $Token->heredoc ) { |
|
436
|
947
|
100
|
|
|
|
1902
|
$heredoc .= "\n" eq $line ? $line : $indentation . $line; |
|
437
|
|
|
|
|
|
|
} |
|
438
|
|
|
|
|
|
|
|
|
439
|
603
|
100
|
|
|
|
1249
|
if ( $Token->{_damaged} ) { |
|
440
|
|
|
|
|
|
|
# Special Case: |
|
441
|
|
|
|
|
|
|
# There are a couple of warning/bug situations |
|
442
|
|
|
|
|
|
|
# that can occur when a HereDoc content was read in |
|
443
|
|
|
|
|
|
|
# from the end of a file that we silently allow. |
|
444
|
|
|
|
|
|
|
# |
|
445
|
|
|
|
|
|
|
# When writing back out to the file we have to |
|
446
|
|
|
|
|
|
|
# auto-repair these problems if we aren't going back |
|
447
|
|
|
|
|
|
|
# on to the end of the file. |
|
448
|
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
# When calculating $last_line, ignore the final token if |
|
450
|
|
|
|
|
|
|
# and only if it has a single newline at the end. |
|
451
|
459
|
|
|
|
|
604
|
my $last_index = $#tokens; |
|
452
|
459
|
100
|
|
|
|
1913
|
if ( $tokens[$last_index]->{content} =~ /^[^\n]*\n$/ ) { |
|
453
|
284
|
|
|
|
|
396
|
$last_index--; |
|
454
|
|
|
|
|
|
|
} |
|
455
|
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
# This is a two part test. |
|
457
|
|
|
|
|
|
|
# First, are we on the last line of the |
|
458
|
|
|
|
|
|
|
# content part of the file |
|
459
|
|
|
|
|
|
|
my $last_line = List::Util::none { |
|
460
|
1252
|
50
|
|
1252
|
|
4243
|
$tokens[$_] and $tokens[$_]->{content} =~ /\n/ |
|
461
|
459
|
|
|
|
|
2259
|
} (($i + 1) .. $last_index); |
|
462
|
459
|
50
|
|
|
|
1626
|
if ( ! defined $last_line ) { |
|
463
|
|
|
|
|
|
|
# Handles the null list case |
|
464
|
0
|
|
|
|
|
0
|
$last_line = 1; |
|
465
|
|
|
|
|
|
|
} |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
# Secondly, are their any more here-docs after us, |
|
468
|
|
|
|
|
|
|
# (with content or a terminator) |
|
469
|
|
|
|
|
|
|
my $any_after = List::Util::any { |
|
470
|
|
|
|
|
|
|
$tokens[$_]->isa('PPI::Token::HereDoc') |
|
471
|
|
|
|
|
|
|
and ( |
|
472
|
2
|
|
|
|
|
8
|
scalar(@{$tokens[$_]->{_heredoc}}) |
|
473
|
|
|
|
|
|
|
or |
|
474
|
|
|
|
|
|
|
defined $tokens[$_]->{_terminator_line} |
|
475
|
|
|
|
|
|
|
) |
|
476
|
459
|
100
|
33
|
1536
|
|
1386
|
} (($i + 1) .. $#tokens); |
|
|
1536
|
|
|
|
|
4018
|
|
|
477
|
459
|
50
|
|
|
|
1541
|
if ( ! defined $any_after ) { |
|
478
|
|
|
|
|
|
|
# Handles the null list case |
|
479
|
0
|
|
|
|
|
0
|
$any_after = ''; |
|
480
|
|
|
|
|
|
|
} |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
# We don't need to repair the last here-doc on the |
|
483
|
|
|
|
|
|
|
# last line. But we do need to repair anything else. |
|
484
|
459
|
50
|
33
|
|
|
1314
|
unless ( $last_line and ! $any_after ) { |
|
485
|
|
|
|
|
|
|
# Add a terminating string if it didn't have one |
|
486
|
0
|
0
|
|
|
|
0
|
unless ( defined $Token->{_terminator_line} ) { |
|
487
|
0
|
|
|
|
|
0
|
$Token->{_terminator_line} = $Token->{_terminator}; |
|
488
|
|
|
|
|
|
|
} |
|
489
|
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
# Add a trailing newline to the terminating |
|
491
|
|
|
|
|
|
|
# string if it didn't have one. |
|
492
|
0
|
0
|
|
|
|
0
|
unless ( $Token->{_terminator_line} =~ /\n$/ ) { |
|
493
|
0
|
|
|
|
|
0
|
$Token->{_terminator_line} .= "\n"; |
|
494
|
|
|
|
|
|
|
} |
|
495
|
|
|
|
|
|
|
} |
|
496
|
|
|
|
|
|
|
} |
|
497
|
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
# Now add the termination line to the heredoc buffer |
|
499
|
603
|
100
|
|
|
|
1300
|
if ( defined $Token->{_terminator_line} ) { |
|
500
|
151
|
|
|
|
|
349
|
$heredoc .= $indentation . $Token->{_terminator_line}; |
|
501
|
|
|
|
|
|
|
} |
|
502
|
|
|
|
|
|
|
} |
|
503
|
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
# End of tokens |
|
505
|
|
|
|
|
|
|
|
|
506
|
7055
|
50
|
|
|
|
12967
|
if ( $heredoc ne '' ) { |
|
507
|
|
|
|
|
|
|
# If the file doesn't end in a newline, we need to add one |
|
508
|
|
|
|
|
|
|
# so that the here-doc content starts on the next line. |
|
509
|
0
|
0
|
|
|
|
0
|
unless ( $output =~ /\n$/ ) { |
|
510
|
0
|
|
|
|
|
0
|
$output .= "\n"; |
|
511
|
|
|
|
|
|
|
} |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
# Now we add the remaining here-doc content |
|
514
|
|
|
|
|
|
|
# to the end of the file. |
|
515
|
0
|
|
|
|
|
0
|
$output .= $heredoc; |
|
516
|
|
|
|
|
|
|
} |
|
517
|
|
|
|
|
|
|
|
|
518
|
7055
|
|
|
|
|
26411
|
$output; |
|
519
|
|
|
|
|
|
|
} |
|
520
|
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
=pod |
|
522
|
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=head2 hex_id |
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
The C method generates an unique identifier for the Perl document. |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
This identifier is basically just the serialized document, with |
|
528
|
|
|
|
|
|
|
Unix-specific newlines, passed through MD5 to produce a hexadecimal string. |
|
529
|
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
This identifier is used by a variety of systems (such as L |
|
531
|
|
|
|
|
|
|
and L) as a unique key against which to store or cache |
|
532
|
|
|
|
|
|
|
information about a document (or indeed, to cache the document itself). |
|
533
|
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
Returns a 32 character hexadecimal string. |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
=cut |
|
537
|
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
sub hex_id { |
|
539
|
163
|
|
|
163
|
1
|
67165
|
PPI::Util::md5hex($_[0]->serialize); |
|
540
|
|
|
|
|
|
|
} |
|
541
|
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
=pod |
|
543
|
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
=head2 index_locations |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
Within a document, all L objects can be considered to have a |
|
547
|
|
|
|
|
|
|
"location", a line/column position within the document when considered as a |
|
548
|
|
|
|
|
|
|
file. This position is primarily useful for debugging type activities. |
|
549
|
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
The method for finding the position of a single Element is a bit laborious, |
|
551
|
|
|
|
|
|
|
and very slow if you need to do it a lot. So the C method |
|
552
|
|
|
|
|
|
|
will index and save the locations of every Element within the Document in |
|
553
|
|
|
|
|
|
|
advance, making future calls to virtually free. |
|
554
|
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
Please note that this index should always be cleared using C |
|
556
|
|
|
|
|
|
|
once you are finished with the locations. If content is added to or removed |
|
557
|
|
|
|
|
|
|
from the file, these indexed locations will be B. |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=cut |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
sub index_locations { |
|
562
|
255
|
|
|
255
|
1
|
2262
|
my $self = shift; |
|
563
|
255
|
|
|
|
|
618
|
my @tokens = $self->tokens; |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
# Whenever we hit a heredoc we will need to increment by |
|
566
|
|
|
|
|
|
|
# the number of lines in its content section when we |
|
567
|
|
|
|
|
|
|
# encounter the next token with a newline in it. |
|
568
|
255
|
|
|
|
|
701
|
my $heredoc = 0; |
|
569
|
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
# Find the first Token without a location |
|
571
|
255
|
|
|
|
|
442
|
my ($first, $location) = (); |
|
572
|
255
|
|
|
|
|
825
|
foreach ( 0 .. $#tokens ) { |
|
573
|
254
|
|
|
|
|
458
|
my $Token = $tokens[$_]; |
|
574
|
254
|
50
|
|
|
|
566
|
next if $Token->{_location}; |
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
# Found the first Token without a location |
|
577
|
|
|
|
|
|
|
# Calculate the new location if needed. |
|
578
|
254
|
50
|
|
|
|
513
|
if ($_) { |
|
579
|
0
|
|
|
|
|
0
|
$location = |
|
580
|
|
|
|
|
|
|
$self->_add_location( $location, $tokens[$_ - 1], \$heredoc ); |
|
581
|
|
|
|
|
|
|
} else { |
|
582
|
254
|
50
|
|
|
|
1028
|
my $logical_file = |
|
583
|
|
|
|
|
|
|
$self->can('filename') ? $self->filename : undef; |
|
584
|
254
|
|
|
|
|
653
|
$location = [ 1, 1, 1, 1, $logical_file ]; |
|
585
|
|
|
|
|
|
|
} |
|
586
|
254
|
|
|
|
|
384
|
$first = $_; |
|
587
|
254
|
|
|
|
|
350
|
last; |
|
588
|
|
|
|
|
|
|
} |
|
589
|
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
# Calculate locations for the rest |
|
591
|
255
|
100
|
|
|
|
527
|
if ( defined $first ) { |
|
592
|
254
|
|
|
|
|
548
|
foreach ( $first .. $#tokens ) { |
|
593
|
66261
|
|
|
|
|
75908
|
my $Token = $tokens[$_]; |
|
594
|
66261
|
|
|
|
|
88817
|
$Token->{_location} = $location; |
|
595
|
66261
|
|
|
|
|
84465
|
$location = $self->_add_location( $location, $Token, \$heredoc ); |
|
596
|
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
# Add any here-doc lines to the counter |
|
598
|
66261
|
100
|
|
|
|
169467
|
if ( $Token->isa('PPI::Token::HereDoc') ) { |
|
599
|
34
|
|
|
|
|
84
|
$heredoc += $Token->heredoc + 1; |
|
600
|
|
|
|
|
|
|
} |
|
601
|
|
|
|
|
|
|
} |
|
602
|
|
|
|
|
|
|
} |
|
603
|
|
|
|
|
|
|
|
|
604
|
255
|
|
|
|
|
3136
|
1; |
|
605
|
|
|
|
|
|
|
} |
|
606
|
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
sub _add_location { |
|
608
|
66261
|
|
|
66261
|
|
80898
|
my ($self, $start, $Token, $heredoc) = @_; |
|
609
|
66261
|
|
|
|
|
95090
|
my $content = $Token->{content}; |
|
610
|
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
# Does the content contain any newlines |
|
612
|
66261
|
|
|
|
|
93397
|
my $newlines =()= $content =~ /\n/g; |
|
613
|
66261
|
|
|
|
|
87146
|
my ($logical_line, $logical_file) = |
|
614
|
|
|
|
|
|
|
$self->_logical_line_and_file($start, $Token, $newlines); |
|
615
|
|
|
|
|
|
|
|
|
616
|
66261
|
100
|
|
|
|
90454
|
unless ( $newlines ) { |
|
617
|
|
|
|
|
|
|
# Handle the simple case |
|
618
|
|
|
|
|
|
|
return [ |
|
619
|
55382
|
|
|
|
|
82757
|
$start->[LOCATION_LINE], |
|
620
|
|
|
|
|
|
|
$start->[LOCATION_CHARACTER] + length($content), |
|
621
|
|
|
|
|
|
|
$start->[LOCATION_COLUMN] |
|
622
|
|
|
|
|
|
|
+ $self->_visual_length( |
|
623
|
|
|
|
|
|
|
$content, |
|
624
|
|
|
|
|
|
|
$start->[LOCATION_COLUMN] |
|
625
|
|
|
|
|
|
|
), |
|
626
|
|
|
|
|
|
|
$logical_line, |
|
627
|
|
|
|
|
|
|
$logical_file, |
|
628
|
|
|
|
|
|
|
]; |
|
629
|
|
|
|
|
|
|
} |
|
630
|
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
# This is the more complex case where we hit or |
|
632
|
|
|
|
|
|
|
# span a newline boundary. |
|
633
|
10879
|
|
|
|
|
12274
|
my $physical_line = $start->[LOCATION_LINE] + $newlines; |
|
634
|
10879
|
|
|
|
|
22189
|
my $location = [ $physical_line, 1, 1, $logical_line, $logical_file ]; |
|
635
|
10879
|
100
|
66
|
|
|
26558
|
if ( $heredoc and $$heredoc ) { |
|
636
|
31
|
|
|
|
|
62
|
$location->[LOCATION_LINE] += $$heredoc; |
|
637
|
31
|
|
|
|
|
41
|
$location->[LOCATION_LOGICAL_LINE] += $$heredoc; |
|
638
|
31
|
|
|
|
|
40
|
$$heredoc = 0; |
|
639
|
|
|
|
|
|
|
} |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
# Does the token have additional characters |
|
642
|
|
|
|
|
|
|
# after their last newline. |
|
643
|
10879
|
100
|
|
|
|
22661
|
if ( $content =~ /\n([^\n]+?)\z/ ) { |
|
644
|
275
|
|
|
|
|
745
|
$location->[LOCATION_CHARACTER] += length($1); |
|
645
|
275
|
|
|
|
|
508
|
$location->[LOCATION_COLUMN] += |
|
646
|
|
|
|
|
|
|
$self->_visual_length( |
|
647
|
|
|
|
|
|
|
$1, $location->[LOCATION_COLUMN], |
|
648
|
|
|
|
|
|
|
); |
|
649
|
|
|
|
|
|
|
} |
|
650
|
|
|
|
|
|
|
|
|
651
|
10879
|
|
|
|
|
15257
|
$location; |
|
652
|
|
|
|
|
|
|
} |
|
653
|
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
sub _logical_line_and_file { |
|
655
|
66261
|
|
|
66261
|
|
76765
|
my ($self, $start, $Token, $newlines) = @_; |
|
656
|
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
# Regex taken from perlsyn, with the correction that there's no space |
|
658
|
|
|
|
|
|
|
# required between the line number and the file name. |
|
659
|
66261
|
100
|
|
|
|
89944
|
if ($start->[LOCATION_CHARACTER] == 1) { |
|
660
|
10630
|
100
|
|
|
|
32331
|
if ( $Token->isa('PPI::Token::Comment') ) { |
|
|
|
100
|
|
|
|
|
|
|
661
|
1764
|
100
|
|
|
|
3253
|
if ( |
|
662
|
|
|
|
|
|
|
$Token->content =~ m< |
|
663
|
|
|
|
|
|
|
\A |
|
664
|
|
|
|
|
|
|
\# \s* |
|
665
|
|
|
|
|
|
|
line \s+ |
|
666
|
|
|
|
|
|
|
(\d+) \s* |
|
667
|
|
|
|
|
|
|
(?: (\"?) ([^\"]* [^\s\"]) \2 )? |
|
668
|
|
|
|
|
|
|
\s* |
|
669
|
|
|
|
|
|
|
\z |
|
670
|
|
|
|
|
|
|
>xms |
|
671
|
|
|
|
|
|
|
) { |
|
672
|
13
|
|
66
|
|
|
64
|
return $1, ($3 || $start->[LOCATION_LOGICAL_FILE]); |
|
673
|
|
|
|
|
|
|
} |
|
674
|
|
|
|
|
|
|
} |
|
675
|
|
|
|
|
|
|
elsif ( $Token->isa('PPI::Token::Pod') ) { |
|
676
|
343
|
|
|
|
|
829
|
my $content = $Token->content; |
|
677
|
343
|
|
|
|
|
455
|
my $line; |
|
678
|
343
|
|
|
|
|
403
|
my $file = $start->[LOCATION_LOGICAL_FILE]; |
|
679
|
343
|
|
|
|
|
379
|
my $end_of_directive; |
|
680
|
343
|
|
|
|
|
1184
|
while ( |
|
681
|
|
|
|
|
|
|
$content =~ m< |
|
682
|
|
|
|
|
|
|
^ |
|
683
|
|
|
|
|
|
|
\# \s*? |
|
684
|
|
|
|
|
|
|
line \s+? |
|
685
|
|
|
|
|
|
|
(\d+) (?: (?! \n) \s)* |
|
686
|
|
|
|
|
|
|
(?: (\"?) ([^\"]*? [^\s\"]) \2 )?? |
|
687
|
|
|
|
|
|
|
\s*? |
|
688
|
|
|
|
|
|
|
$ |
|
689
|
|
|
|
|
|
|
>xmsg |
|
690
|
|
|
|
|
|
|
) { |
|
691
|
6
|
|
66
|
|
|
50
|
($line, $file) = ($1, ( $3 || $file ) ); |
|
692
|
6
|
|
|
|
|
13
|
$end_of_directive = pos $content; |
|
693
|
|
|
|
|
|
|
} |
|
694
|
|
|
|
|
|
|
|
|
695
|
343
|
100
|
|
|
|
615
|
if (defined $line) { |
|
696
|
6
|
|
|
|
|
9
|
pos $content = $end_of_directive; |
|
697
|
6
|
|
|
|
|
23
|
my $post_directive_newlines =()= $content =~ m< \G [^\n]* \n >xmsg; |
|
698
|
6
|
|
|
|
|
20
|
return $line + $post_directive_newlines - 1, $file; |
|
699
|
|
|
|
|
|
|
} |
|
700
|
|
|
|
|
|
|
} |
|
701
|
|
|
|
|
|
|
} |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
return |
|
704
|
66242
|
|
|
|
|
109179
|
$start->[LOCATION_LOGICAL_LINE] + $newlines, |
|
705
|
|
|
|
|
|
|
$start->[LOCATION_LOGICAL_FILE]; |
|
706
|
|
|
|
|
|
|
} |
|
707
|
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
sub _visual_length { |
|
709
|
55657
|
|
|
55657
|
|
67691
|
my ($self, $content, $pos) = @_; |
|
710
|
|
|
|
|
|
|
|
|
711
|
55657
|
|
|
|
|
63890
|
my $tab_width = $self->tab_width; |
|
712
|
55657
|
|
|
|
|
59192
|
my ($length, $vis_inc); |
|
713
|
|
|
|
|
|
|
|
|
714
|
55657
|
100
|
|
|
|
178793
|
return length $content if $content !~ /\t/; |
|
715
|
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
# Split the content in tab and non-tab parts and calculate the |
|
717
|
|
|
|
|
|
|
# "visual increase" of each part. |
|
718
|
4253
|
|
|
|
|
14320
|
for my $part ( split(/(\t)/, $content) ) { |
|
719
|
15647
|
100
|
|
|
|
18353
|
if ($part eq "\t") { |
|
720
|
7798
|
|
|
|
|
9495
|
$vis_inc = $tab_width - ($pos-1) % $tab_width; |
|
721
|
|
|
|
|
|
|
} |
|
722
|
|
|
|
|
|
|
else { |
|
723
|
7849
|
|
|
|
|
7737
|
$vis_inc = length $part; |
|
724
|
|
|
|
|
|
|
} |
|
725
|
15647
|
|
|
|
|
14358
|
$length += $vis_inc; |
|
726
|
15647
|
|
|
|
|
16044
|
$pos += $vis_inc; |
|
727
|
|
|
|
|
|
|
} |
|
728
|
|
|
|
|
|
|
|
|
729
|
4253
|
|
|
|
|
13883
|
$length; |
|
730
|
|
|
|
|
|
|
} |
|
731
|
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
=pod |
|
733
|
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
=head2 flush_locations |
|
735
|
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
When no longer needed, the C method clears all location data |
|
737
|
|
|
|
|
|
|
from the tokens. |
|
738
|
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
=cut |
|
740
|
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
sub flush_locations { |
|
742
|
1
|
|
|
1
|
1
|
552
|
shift->_flush_locations(@_); |
|
743
|
|
|
|
|
|
|
} |
|
744
|
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
=pod |
|
746
|
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
=head2 normalized |
|
748
|
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
The C method is used to generate a "Layer 1" |
|
750
|
|
|
|
|
|
|
L object for the current Document. |
|
751
|
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
A "normalized" Perl Document is an arbitrary structure that removes any |
|
753
|
|
|
|
|
|
|
irrelevant parts of the document and refactors out variations in style, |
|
754
|
|
|
|
|
|
|
to attempt to approach something that is closer to the "true meaning" |
|
755
|
|
|
|
|
|
|
of the Document. |
|
756
|
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
See L for more information on document normalization and |
|
758
|
|
|
|
|
|
|
the tasks for which it is useful. |
|
759
|
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
Returns a L object, or C on error. |
|
761
|
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
=cut |
|
763
|
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
sub normalized { |
|
765
|
|
|
|
|
|
|
# The normalization process will utterly destroy and mangle |
|
766
|
|
|
|
|
|
|
# anything passed to it, so we are going to only give it a |
|
767
|
|
|
|
|
|
|
# clone of ourselves. |
|
768
|
4
|
|
|
4
|
1
|
1390
|
PPI::Normal->process( $_[0]->clone ); |
|
769
|
|
|
|
|
|
|
} |
|
770
|
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
=pod |
|
772
|
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
=head1 complete |
|
774
|
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
The C method is used to determine if a document is cleanly |
|
776
|
|
|
|
|
|
|
structured, all braces are closed, the final statement is |
|
777
|
|
|
|
|
|
|
fully terminated and all heredocs are fully entered. |
|
778
|
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
Returns true if the document is complete or false if not. |
|
780
|
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
=cut |
|
782
|
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
sub complete { |
|
784
|
2
|
|
|
2
|
0
|
663
|
my $self = shift; |
|
785
|
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
# Every structure has to be complete |
|
787
|
|
|
|
|
|
|
$self->find_any( sub { |
|
788
|
15
|
50
|
|
15
|
|
57
|
$_[1]->isa('PPI::Structure') |
|
789
|
|
|
|
|
|
|
and |
|
790
|
|
|
|
|
|
|
! $_[1]->complete |
|
791
|
|
|
|
|
|
|
} ) |
|
792
|
2
|
50
|
|
|
|
14
|
and return ''; |
|
793
|
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
# Strip anything that isn't a statement off the end |
|
795
|
2
|
|
|
|
|
14
|
my @child = $self->children; |
|
796
|
2
|
|
66
|
|
|
13
|
while ( @child and not $child[-1]->isa('PPI::Statement') ) { |
|
797
|
2
|
|
|
|
|
7
|
pop @child; |
|
798
|
|
|
|
|
|
|
} |
|
799
|
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
# We must have at least one statement |
|
801
|
2
|
50
|
|
|
|
11
|
return '' unless @child; |
|
802
|
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
# Check the completeness of the last statement |
|
804
|
2
|
|
|
|
|
7
|
return $child[-1]->_complete; |
|
805
|
|
|
|
|
|
|
} |
|
806
|
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
##################################################################### |
|
812
|
|
|
|
|
|
|
# PPI::Node Methods |
|
813
|
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
# We are a scope boundary |
|
815
|
|
|
|
|
|
|
### XS -> PPI/XS.xs:_PPI_Document__scope 0.903+ |
|
816
|
|
|
|
|
|
|
sub scope() { 1 } |
|
817
|
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
##################################################################### |
|
823
|
|
|
|
|
|
|
# PPI::Element Methods |
|
824
|
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
sub insert_before { |
|
826
|
0
|
|
|
0
|
1
|
0
|
return undef; |
|
827
|
|
|
|
|
|
|
# die "Cannot insert_before a PPI::Document"; |
|
828
|
|
|
|
|
|
|
} |
|
829
|
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
sub insert_after { |
|
831
|
0
|
|
|
0
|
1
|
0
|
return undef; |
|
832
|
|
|
|
|
|
|
# die "Cannot insert_after a PPI::Document"; |
|
833
|
|
|
|
|
|
|
} |
|
834
|
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
sub replace { |
|
836
|
0
|
|
|
0
|
1
|
0
|
return undef; |
|
837
|
|
|
|
|
|
|
# die "Cannot replace a PPI::Document"; |
|
838
|
|
|
|
|
|
|
} |
|
839
|
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
##################################################################### |
|
845
|
|
|
|
|
|
|
# Error Handling |
|
846
|
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
# Set the error message |
|
848
|
|
|
|
|
|
|
sub _error { |
|
849
|
1
|
|
|
1
|
|
2
|
$errstr = $_[1]; |
|
850
|
1
|
|
|
|
|
3
|
undef; |
|
851
|
|
|
|
|
|
|
} |
|
852
|
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
# Clear the error message. |
|
854
|
|
|
|
|
|
|
# Returns the object as a convenience. |
|
855
|
|
|
|
|
|
|
sub _clear { |
|
856
|
2327
|
|
|
2327
|
|
3627
|
$errstr = ''; |
|
857
|
2327
|
|
|
|
|
3241
|
$_[0]; |
|
858
|
|
|
|
|
|
|
} |
|
859
|
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
=pod |
|
861
|
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
=head2 errstr |
|
863
|
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
For error that occur when loading and saving documents, you can use |
|
865
|
|
|
|
|
|
|
C, as either a static or object method, to access the error message. |
|
866
|
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
If a Document loads or saves without error, C will return false. |
|
868
|
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
=cut |
|
870
|
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
sub errstr { |
|
872
|
2339
|
|
|
2339
|
1
|
11340
|
$errstr; |
|
873
|
|
|
|
|
|
|
} |
|
874
|
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
|
|
877
|
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
##################################################################### |
|
880
|
|
|
|
|
|
|
# Native Storable Support |
|
881
|
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
sub STORABLE_freeze { |
|
883
|
4
|
|
|
4
|
0
|
698
|
my $self = shift; |
|
884
|
4
|
|
|
|
|
9
|
my $class = ref $self; |
|
885
|
4
|
|
|
|
|
18
|
my %hash = %$self; |
|
886
|
4
|
|
|
|
|
489
|
return ($class, \%hash); |
|
887
|
|
|
|
|
|
|
} |
|
888
|
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
sub STORABLE_thaw { |
|
890
|
6
|
|
|
6
|
0
|
565
|
my ($self, undef, $class, $hash) = @_; |
|
891
|
6
|
|
|
|
|
12
|
bless $self, $class; |
|
892
|
6
|
|
|
|
|
19
|
foreach ( keys %$hash ) { |
|
893
|
21
|
|
|
|
|
38
|
$self->{$_} = delete $hash->{$_}; |
|
894
|
|
|
|
|
|
|
} |
|
895
|
6
|
|
|
|
|
24
|
$self->__link_children; |
|
896
|
|
|
|
|
|
|
} |
|
897
|
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
1; |
|
899
|
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
=pod |
|
901
|
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
=head1 TO DO |
|
903
|
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
- May need to overload some methods to forcefully prevent Document |
|
905
|
|
|
|
|
|
|
objects becoming children of another Node. |
|
906
|
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
=head1 SUPPORT |
|
908
|
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
See the L in the main module. |
|
910
|
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
=head1 AUTHOR |
|
912
|
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
Adam Kennedy Eadamk@cpan.orgE |
|
914
|
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
916
|
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
L, L |
|
918
|
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
920
|
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
Copyright 2001 - 2011 Adam Kennedy. |
|
922
|
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
This program is free software; you can redistribute |
|
924
|
|
|
|
|
|
|
it and/or modify it under the same terms as Perl itself. |
|
925
|
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
The full text of the license can be found in the |
|
927
|
|
|
|
|
|
|
LICENSE file included with this module. |
|
928
|
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
=cut |