Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / PPI / Dumper.pm
CommitLineData
3fea05b9 1package PPI::Dumper;
2
3=pod
4
5=head1 NAME
6
7PPI::Dumper - Dumping of PDOM trees
8
9=head1 SYNOPSIS
10
11 # Load a document
12 my $Module = PPI::Document->new( 'MyModule.pm' );
13
14 # Create the dumper
15 my $Dumper = PPI::Dumper->new( $Module );
16
17 # Dump the document
18 $Dumper->print;
19
20=head1 DESCRIPTION
21
22The PDOM trees in PPI are quite complex, and getting a dump of their
23structure for development and debugging purposes is important.
24
25This module provides that functionality.
26
27The process is relatively simple. Create a dumper object with a
28particular set of options, and then call one of the dump methods to
29generate the dump content itself.
30
31=head1 METHODS
32
33=cut
34
35use strict;
36use Params::Util qw{_INSTANCE};
37
38use vars qw{$VERSION};
39BEGIN {
40 $VERSION = '1.206';
41}
42
43
44
45
46
47#####################################################################
48# Constructor
49
50=pod
51
52=head2 new $Element, param => value, ...
53
54The C<new> constructor creates a dumper, and takes as argument a single
55L<PPI::Element> object of any type to serve as the root of the tree to
56be dumped, and a number of key-E<gt>value parameters to control the output
57format of the Dumper. Details of the parameters are listed below.
58
59Returns a new C<PPI::Dumper> object, or C<undef> if the constructor
60is not passed a correct L<PPI::Element> root object.
61
62=over
63
64=item memaddr
65
66Should the dumper print the memory addresses of each PDOM element.
67True/false value, off by default.
68
69=item indent
70
71Should the structures being dumped be indented. This value is numeric,
72with the number representing the number of spaces to use when indenting
73the dumper output. Set to '2' by default.
74
75=item class
76
77Should the dumper print the full class for each element.
78True/false value, on by default.
79
80=item content
81
82Should the dumper show the content of each element. True/false value,
83on by default.
84
85=item whitespace
86
87Should the dumper show whitespace tokens. By not showing the copious
88numbers of whitespace tokens the structure of the code can often be
89made much clearer. True/false value, on by default.
90
91=item comments
92
93Should the dumper show comment tokens. In situations where you have
94a lot of comments, the code can often be made clearer by ignoring
95comment tokens. True/value value, on by default.
96
97=item locations
98
99Should the dumper show the location of each token. The values shown are
100[ line, rowchar, column ]. See L<PPI::Element/"location"> for a description of
101what these values really are. True/false value, off by default.
102
103=back
104
105=cut
106
107sub new {
108 my $class = shift;
109 my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
110
111 # Create the object
112 my $self = bless {
113 root => $Element,
114 display => {
115 memaddr => '', # Show the refaddr of the item
116 indent => 2, # Indent the structures
117 class => 1, # Show the object class
118 content => 1, # Show the object contents
119 whitespace => 1, # Show whitespace tokens
120 comments => 1, # Show comment tokens
121 locations => 0, # Show token locations
122 },
123 }, $class;
124
125 # Handle the options
126 my %options = map { lc $_ } @_;
127 foreach ( keys %{$self->{display}} ) {
128 if ( exists $options{$_} ) {
129 if ( $_ eq 'indent' ) {
130 $self->{display}->{indent} = $options{$_};
131 } else {
132 $self->{display}->{$_} = !! $options{$_};
133 }
134 }
135 }
136
137 $self->{indent_string} = join '', (' ' x $self->{display}->{indent});
138
139 # Try to auto-call index_locations. If it failes, turn of locations display
140 if ( $self->{display}->{locations} ) {
141 my $Document = $Element->isa('PPI::Document') ? $Element : $Element->top;
142 if ( $Document->isa('PPI::Document') ) {
143 $Document->index_locations;
144 } else {
145 $self->{display}->{locations} = 0;
146 }
147 }
148
149 $self;
150}
151
152
153
154
155
156#####################################################################
157# Main Interface Methods
158
159=pod
160
161=head2 print
162
163The C<print> method generates the dump and prints it to STDOUT.
164
165Returns as for the internal print function.
166
167=cut
168
169sub print {
170 CORE::print(shift->string);
171}
172
173=pod
174
175=head2 string
176
177The C<string> method generates the dump and provides it as a
178single string.
179
180Returns a string or undef if there is an error while generating the dump.
181
182=cut
183
184sub string {
185 my $array_ref = shift->_dump or return undef;
186 join '', map { "$_\n" } @$array_ref;
187}
188
189=pod
190
191=head2 list
192
193The C<list> method generates the dump and provides it as a raw
194list, without trailing newlines.
195
196Returns a list or the null list if there is an error while generation
197the dump.
198
199=cut
200
201sub list {
202 my $array_ref = shift->_dump or return ();
203 @$array_ref;
204}
205
206
207
208
209
210#####################################################################
211# Generation Support Methods
212
213sub _dump {
214 my $self = ref $_[0] ? shift : shift->new(shift);
215 my $Element = _INSTANCE($_[0], 'PPI::Element') ? shift : $self->{root};
216 my $indent = shift || '';
217 my $output = shift || [];
218
219 # Print the element if needed
220 my $show = 1;
221 if ( $Element->isa('PPI::Token::Whitespace') ) {
222 $show = 0 unless $self->{display}->{whitespace};
223 } elsif ( $Element->isa('PPI::Token::Comment') ) {
224 $show = 0 unless $self->{display}->{comments};
225 }
226 push @$output, $self->_element_string( $Element, $indent ) if $show;
227
228 # Recurse into our children
229 if ( $Element->isa('PPI::Node') ) {
230 my $child_indent = $indent . $self->{indent_string};
231 foreach my $child ( @{$Element->{children}} ) {
232 $self->_dump( $child, $child_indent, $output );
233 }
234 }
235
236 $output;
237}
238
239sub _element_string {
240 my $self = ref $_[0] ? shift : shift->new(shift);
241 my $Element = _INSTANCE($_[0], 'PPI::Element') ? shift : $self->{root};
242 my $indent = shift || '';
243 my $string = '';
244
245 # Add the memory location
246 if ( $self->{display}->{memaddr} ) {
247 $string .= $Element->refaddr . ' ';
248 }
249
250 # Add the location if such exists
251 if ( $self->{display}->{locations} ) {
252 my $loc_string;
253 if ( $Element->isa('PPI::Token') ) {
254 my $location = $Element->location;
255 if ($location) {
256 $loc_string = sprintf("[ % 4d, % 3d, % 3d ] ", @$location);
257 }
258 }
259 # Output location or pad with 20 spaces
260 $string .= $loc_string || " " x 20;
261 }
262
263 # Add the indent
264 if ( $self->{display}->{indent} ) {
265 $string .= $indent;
266 }
267
268 # Add the class name
269 if ( $self->{display}->{class} ) {
270 $string .= ref $Element;
271 }
272
273 if ( $Element->isa('PPI::Token') ) {
274 # Add the content
275 if ( $self->{display}->{content} ) {
276 my $content = $Element->content;
277 $content =~ s/\n/\\n/g;
278 $content =~ s/\t/\\t/g;
279 $string .= " \t'$content'";
280 }
281 } elsif ( $Element->isa('PPI::Structure') ) {
282 # Add the content
283 if ( $self->{display}->{content} ) {
284 my $start = $Element->start
285 ? $Element->start->content
286 : '???';
287 my $finish = $Element->finish
288 ? $Element->finish->content
289 : '???';
290 $string .= " \t$start ... $finish";
291 }
292 }
293
294 $string;
295}
296
2971;
298
299=pod
300
301=head1 SUPPORT
302
303See the L<support section|PPI/SUPPORT> in the main module.
304
305=head1 AUTHOR
306
307Adam Kennedy E<lt>adamk@cpan.orgE<gt>
308
309=head1 COPYRIGHT
310
311Copyright 2001 - 2009 Adam Kennedy.
312
313This program is free software; you can redistribute
314it and/or modify it under the same terms as Perl itself.
315
316The full text of the license can be found in the
317LICENSE file included with this module.
318
319=cut