Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / PPI / Dumper.pm
1 package PPI::Dumper;
2
3 =pod
4
5 =head1 NAME
6
7 PPI::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
22 The PDOM trees in PPI are quite complex, and getting a dump of their
23 structure for development and debugging purposes is important.
24
25 This module provides that functionality.
26
27 The process is relatively simple. Create a dumper object with a
28 particular set of options, and then call one of the dump methods to
29 generate the dump content itself.
30
31 =head1 METHODS
32
33 =cut
34
35 use strict;
36 use Params::Util qw{_INSTANCE};
37
38 use vars qw{$VERSION};
39 BEGIN {
40         $VERSION = '1.206';
41 }
42
43
44
45
46
47 #####################################################################
48 # Constructor
49
50 =pod
51
52 =head2 new $Element, param => value, ...
53
54 The C<new> constructor creates a dumper, and takes as argument a single
55 L<PPI::Element> object of any type to serve as the root of the tree to
56 be dumped, and a number of key-E<gt>value parameters to control the output
57 format of the Dumper. Details of the parameters are listed below.
58
59 Returns a new C<PPI::Dumper> object, or C<undef> if the constructor
60 is not passed a correct L<PPI::Element> root object.
61
62 =over
63
64 =item memaddr
65
66 Should the dumper print the memory addresses of each PDOM element.
67 True/false value, off by default.
68
69 =item indent
70
71 Should the structures being dumped be indented. This value is numeric,
72 with the number representing the number of spaces to use when indenting
73 the dumper output. Set to '2' by default.
74
75 =item class
76
77 Should the dumper print the full class for each element.
78 True/false value, on by default.
79
80 =item content
81
82 Should the dumper show the content of each element. True/false value,
83 on by default.
84
85 =item whitespace
86
87 Should the dumper show whitespace tokens. By not showing the copious
88 numbers of whitespace tokens the structure of the code can often be
89 made much clearer. True/false value, on by default.
90
91 =item comments
92
93 Should the dumper show comment tokens. In situations where you have
94 a lot of comments, the code can often be made clearer by ignoring
95 comment tokens. True/value value, on by default.
96
97 =item locations
98
99 Should 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
101 what these values really are. True/false value, off by default.
102
103 =back
104
105 =cut
106
107 sub 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
163 The C<print> method generates the dump and prints it to STDOUT.
164
165 Returns as for the internal print function.
166
167 =cut
168
169 sub print {
170         CORE::print(shift->string);
171 }
172
173 =pod
174
175 =head2 string
176
177 The C<string> method generates the dump and provides it as a
178 single string.
179
180 Returns a string or undef if there is an error while generating the dump. 
181
182 =cut
183
184 sub 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
193 The C<list> method generates the dump and provides it as a raw
194 list, without trailing newlines.
195
196 Returns a list or the null list if there is an error while generation
197 the dump.
198
199 =cut
200
201 sub list {
202         my $array_ref = shift->_dump or return ();
203         @$array_ref;
204 }
205
206
207
208
209
210 #####################################################################
211 # Generation Support Methods
212
213 sub _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
239 sub _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
297 1;
298
299 =pod
300
301 =head1 SUPPORT
302
303 See the L<support section|PPI/SUPPORT> in the main module.
304
305 =head1 AUTHOR
306
307 Adam Kennedy E<lt>adamk@cpan.orgE<gt>
308
309 =head1 COPYRIGHT
310
311 Copyright 2001 - 2009 Adam Kennedy.
312
313 This program is free software; you can redistribute
314 it and/or modify it under the same terms as Perl itself.
315
316 The full text of the license can be found in the
317 LICENSE file included with this module.
318
319 =cut