← Index
NYTProf Performance Profile   « line view »
For /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/bin/perlcritic
  Run on Sat Mar 19 22:12:22 2016
Reported on Sat Mar 19 22:14:10 2016

Filename/Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/PPI/Node.pm
StatementsExecuted 3539983 statements in 4.21s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
3668643.37s6.01sPPI::Node::::findPPI::Node::find
116022821ms1.40sPPI::Node::::find_firstPPI::Node::find_first
3294243642ms931msPPI::Node::::tokensPPI::Node::tokens (recurses: max depth 15, inclusive time 3.16s)
1647122601ms999msPPI::Node::::DESTROYPPI::Node::DESTROY (recurses: max depth 1, inclusive time 81.6ms)
29896218265ms311msPPI::Node::::schildPPI::Node::schild
962721150ms178msPPI::Node::::schildrenPPI::Node::schildren
482821140ms160msPPI::Node::::_wantedPPI::Node::_wanted
96105261.5ms127msPPI::Node::::locationPPI::Node::location
20763356.3ms82.0msPPI::Node::::contentPPI::Node::content (recurses: max depth 5, inclusive time 30.8ms)
2404334.84ms4.84msPPI::Node::::childrenPPI::Node::children
14411842µs842µsPPI::Node::::newPPI::Node::new
14411361µs361µsPPI::Node::::first_elementPPI::Node::first_element
11112µs12µsPPI::Node::::BEGIN@59PPI::Node::BEGIN@59
11111µs24µsPPI::Node::::BEGIN@51PPI::Node::BEGIN@51
1117µs48µsPPI::Node::::BEGIN@58PPI::Node::BEGIN@58
1117µs28µsPPI::Node::::BEGIN@53PPI::Node::BEGIN@53
1117µs42µsPPI::Node::::BEGIN@55PPI::Node::BEGIN@55
2115µs5µsPPI::Node::::childPPI::Node::child
1113µs3µsPPI::Node::::BEGIN@56PPI::Node::BEGIN@56
1113µs3µsPPI::Node::::BEGIN@52PPI::Node::BEGIN@52
1113µs3µsPPI::Node::::BEGIN@54PPI::Node::BEGIN@54
0000s0sPPI::Node::::__ANON__[:508]PPI::Node::__ANON__[:508]
0000s0sPPI::Node::::__ANON__[:715]PPI::Node::__ANON__[:715]
0000s0sPPI::Node::::__ANON__[:724]PPI::Node::__ANON__[:724]
0000s0sPPI::Node::::__ANON__[:740]PPI::Node::__ANON__[:740]
0000s0sPPI::Node::::__ANON__[:756]PPI::Node::__ANON__[:756]
0000s0sPPI::Node::::__add_elementPPI::Node::__add_element
0000s0sPPI::Node::::__insert_after_childPPI::Node::__insert_after_child
0000s0sPPI::Node::::__insert_before_childPPI::Node::__insert_before_child
0000s0sPPI::Node::::__link_childrenPPI::Node::__link_children
0000s0sPPI::Node::::__positionPPI::Node::__position
0000s0sPPI::Node::::__replace_childPPI::Node::__replace_child
0000s0sPPI::Node::::add_elementPPI::Node::add_element
0000s0sPPI::Node::::clonePPI::Node::clone
0000s0sPPI::Node::::containsPPI::Node::contains
0000s0sPPI::Node::::elementsPPI::Node::elements
0000s0sPPI::Node::::find_anyPPI::Node::find_any
0000s0sPPI::Node::::last_elementPPI::Node::last_element
0000s0sPPI::Node::::prunePPI::Node::prune
0000s0sPPI::Node::::remove_childPPI::Node::remove_child
0000s0sPPI::Node::::scopePPI::Node::scope
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package PPI::Node;
2
3=pod
4
5=head1 NAME
6
7PPI::Node - Abstract PPI Node class, an Element that can contain other Elements
8
9=head1 INHERITANCE
10
11 PPI::Node
12 isa PPI::Element
13
14=head1 SYNOPSIS
15
16 # Create a typical node (a Document in this case)
17 my $Node = PPI::Document->new;
18
19 # Add an element to the node( in this case, a token )
20 my $Token = PPI::Token::Word->new('my');
21 $Node->add_element( $Token );
22
23 # Get the elements for the Node
24 my @elements = $Node->children;
25
26 # Find all the barewords within a Node
27 my $barewords = $Node->find( 'PPI::Token::Word' );
28
29 # Find by more complex criteria
30 my $my_tokens = $Node->find( sub { $_[1]->content eq 'my' } );
31
32 # Remove all the whitespace
33 $Node->prune( 'PPI::Token::Whitespace' );
34
35 # Remove by more complex criteria
36 $Node->prune( sub { $_[1]->content eq 'my' } );
37
38=head1 DESCRIPTION
39
40The C<PPI::Node> class provides an abstract base class for the Element
41classes that are able to contain other elements L<PPI::Document>,
42L<PPI::Statement>, and L<PPI::Structure>.
43
44As well as those listed below, all of the methods that apply to
45L<PPI::Element> objects also apply to C<PPI::Node> objects.
46
47=head1 METHODS
48
49=cut
50
51219µs236µs
# spent 24µs (11+12) within PPI::Node::BEGIN@51 which was called: # once (11µs+12µs) by PPI::Element::BEGIN@30 at line 51
use strict;
# spent 24µs making 1 call to PPI::Node::BEGIN@51 # spent 12µs making 1 call to strict::import
52217µs13µs
# spent 3µs within PPI::Node::BEGIN@52 which was called: # once (3µs+0s) by PPI::Element::BEGIN@30 at line 52
use Carp ();
# spent 3µs making 1 call to PPI::Node::BEGIN@52
53223µs249µs
# spent 28µs (7+21) within PPI::Node::BEGIN@53 which was called: # once (7µs+21µs) by PPI::Element::BEGIN@30 at line 53
use Scalar::Util qw{refaddr};
# spent 28µs making 1 call to PPI::Node::BEGIN@53 # spent 21µs making 1 call to Exporter::import
54218µs13µs
# spent 3µs within PPI::Node::BEGIN@54 which was called: # once (3µs+0s) by PPI::Element::BEGIN@30 at line 54
use List::MoreUtils ();
# spent 3µs making 1 call to PPI::Node::BEGIN@54
55219µs278µs
# spent 42µs (7+35) within PPI::Node::BEGIN@55 which was called: # once (7µs+35µs) by PPI::Element::BEGIN@30 at line 55
use Params::Util qw{_INSTANCE _CLASS _CODELIKE};
# spent 42µs making 1 call to PPI::Node::BEGIN@55 # spent 36µs making 1 call to Exporter::import
56219µs13µs
# spent 3µs within PPI::Node::BEGIN@56 which was called: # once (3µs+0s) by PPI::Element::BEGIN@30 at line 56
use PPI::Element ();
# spent 3µs making 1 call to PPI::Node::BEGIN@56
57
58240µs290µs
# spent 48µs (7+41) within PPI::Node::BEGIN@58 which was called: # once (7µs+41µs) by PPI::Element::BEGIN@30 at line 58
use vars qw{$VERSION @ISA *_PARENT};
# spent 48µs making 1 call to PPI::Node::BEGIN@58 # spent 41µs making 1 call to vars::import
59
# spent 12µs within PPI::Node::BEGIN@59 which was called: # once (12µs+0s) by PPI::Element::BEGIN@30 at line 63
BEGIN {
601300ns $VERSION = '1.215';
6118µs @ISA = 'PPI::Element';
6214µs *_PARENT = *PPI::Element::_PARENT;
6311.70ms112µs}
# spent 12µs making 1 call to PPI::Node::BEGIN@59
64
- -
69#####################################################################
70# The basic constructor
71
72
# spent 842µs within PPI::Node::new which was called 144 times, avg 6µs/call: # 144 times (842µs+0s) by PPI::Document::new at line 153 of PPI/Document.pm, avg 6µs/call
sub new {
73144119µs my $class = ref $_[0] || $_[0];
74144959µs bless { children => [] }, $class;
75}
76
- -
81#####################################################################
82# PDOM Methods
83
84=pod
85
86=head2 scope
87
88The C<scope> method returns true if the node represents a lexical scope
89boundary, or false if it does not.
90
91=cut
92
93### XS -> PPI/XS.xs:_PPI_Node__scope 0.903+
94sub scope { '' }
95
96=pod
97
98=head2 add_element $Element
99
100The C<add_element> method adds a L<PPI::Element> object to the end of a
101C<PPI::Node>. Because Elements maintain links to their parent, an
102Element can only be added to a single Node.
103
104Returns true if the L<PPI::Element> was added. Returns C<undef> if the
105Element was already within another Node, or the method is not passed
106a L<PPI::Element> object.
107
108=cut
109
110sub add_element {
111 my $self = shift;
112
113 # Check the element
114 my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
115 $_PARENT{refaddr $Element} and return undef;
116
117 # Add the argument to the elements
118 push @{$self->{children}}, $Element;
119 Scalar::Util::weaken(
120 $_PARENT{refaddr $Element} = $self
121 );
122
123 1;
124}
125
126# In a typical run profile, add_element is the number 1 resource drain.
127# This is a highly optimised unsafe version, for internal use only.
128sub __add_element {
129 Scalar::Util::weaken(
130 $_PARENT{refaddr $_[1]} = $_[0]
131 );
132 push @{$_[0]->{children}}, $_[1];
133}
134
135=pod
136
137=head2 elements
138
139The C<elements> method accesses all child elements B<structurally> within
140the C<PPI::Node> object. Note that in the base of the L<PPI::Structure>
141classes, this C<DOES> include the brace tokens at either end of the
142structure.
143
144Returns a list of zero or more L<PPI::Element> objects.
145
146Alternatively, if called in the scalar context, the C<elements> method
147returns a count of the number of elements.
148
149=cut
150
151sub elements {
152 if ( wantarray ) {
153 return @{$_[0]->{children}};
154 } else {
155 return scalar @{$_[0]->{children}};
156 }
157}
158
159=pod
160
161=head2 first_element
162
163The C<first_element> method accesses the first element structurally within
164the C<PPI::Node> object. As for the C<elements> method, this does include
165the brace tokens for L<PPI::Structure> objects.
166
167Returns a L<PPI::Element> object, or C<undef> if for some reason the
168C<PPI::Node> object does not contain any elements.
169
170=cut
171
172# Normally the first element is also the first child
173
# spent 361µs within PPI::Node::first_element which was called 144 times, avg 3µs/call: # 144 times (361µs+0s) by Perl::Critic::Document::AUTOLOAD at line 41 of Perl/Critic/Document.pm, avg 3µs/call
sub first_element {
174144455µs $_[0]->{children}->[0];
175}
176
177=pod
178
179=head2 last_element
180
181The C<last_element> method accesses the last element structurally within
182the C<PPI::Node> object. As for the C<elements> method, this does include
183the brace tokens for L<PPI::Structure> objects.
184
185Returns a L<PPI::Element> object, or C<undef> if for some reason the
186C<PPI::Node> object does not contain any elements.
187
188=cut
189
190# Normally the last element is also the last child
191sub last_element {
192 $_[0]->{children}->[-1];
193}
194
195=pod
196
197=head2 children
198
199The C<children> method accesses all child elements lexically within the
200C<PPI::Node> object. Note that in the case of the L<PPI::Structure>
201classes, this does B<NOT> include the brace tokens at either end of the
202structure.
203
204Returns a list of zero of more L<PPI::Element> objects.
205
206Alternatively, if called in the scalar context, the C<children> method
207returns a count of the number of lexical children.
208
209=cut
210
211# In the default case, this is the same as for the elements method
212
# spent 4.84ms within PPI::Node::children which was called 2404 times, avg 2µs/call: # 1299 times (2.67ms+0s) by PPI::Statement::Variable::type at line 67 of PPI/Statement/Variable.pm, avg 2µs/call # 1016 times (1.92ms+0s) by PPI::Statement::Sub::prototype at line 100 of PPI/Statement/Sub.pm, avg 2µs/call # 89 times (245µs+0s) by PPI::Lexer::_lex_structure at line 1367 of PPI/Lexer.pm, avg 3µs/call
sub children {
21324047.03ms wantarray ? @{$_[0]->{children}} : scalar @{$_[0]->{children}};
214}
215
216=pod
217
218=head2 schildren
219
220The C<schildren> method is really just a convenience, the significant-only
221variation of the normal C<children> method.
222
223In list context, returns a list of significant children. In scalar context,
224returns the number of significant children.
225
226=cut
227
228
# spent 178ms (150+28.1) within PPI::Node::schildren which was called 9627 times, avg 18µs/call: # 4817 times (60.9ms+14.2ms) by PPI::Lexer::_continues at line 705 of PPI/Lexer.pm, avg 16µs/call # 4810 times (88.8ms+14.0ms) by PPI::Lexer::_continues at line 722 of PPI/Lexer.pm, avg 21µs/call
sub schildren {
2292605536.5ms1642814.0ms return grep { $_->significant } @{$_[0]->{children}} if wantarray;
# spent 8.47ms making 10537 calls to PPI::Element::significant, avg 804ns/call # spent 5.49ms making 5891 calls to PPI::Token::Whitespace::significant, avg 933ns/call
2304817837µs my $count = 0;
23148174.87ms foreach ( @{$_[0]->{children}} ) {
2321643720.9ms1643714.2ms $count++ if $_->significant;
# spent 8.64ms making 10544 calls to PPI::Element::significant, avg 819ns/call # spent 5.53ms making 5893 calls to PPI::Token::Whitespace::significant, avg 939ns/call
233 }
234481712.4ms return $count;
235}
236
237=pod
238
239=head2 child $index
240
241The C<child> method accesses a child L<PPI::Element> object by its
242position within the Node.
243
244Returns a L<PPI::Element> object, or C<undef> if there is no child
245element at that node.
246
247=cut
248
249
# spent 5µs within PPI::Node::child which was called 2 times, avg 2µs/call: # 2 times (5µs+0s) by Perl::Critic::Annotation::_init at line 116 of Perl/Critic/Annotation.pm, avg 2µs/call
sub child {
25027µs $_[0]->{children}->[$_[1]];
251}
252
253=pod
254
255=head2 schild $index
256
257The lexical structure of the Perl language ignores 'insignificant' items,
258such as whitespace and comments, while L<PPI> treats these items as valid
259tokens so that it can reassemble the file at any time. Because of this,
260in many situations there is a need to find an Element within a Node by
261index, only counting lexically significant Elements.
262
263The C<schild> method returns a child Element by index, ignoring
264insignificant Elements. The index of a child Element is specified in the
265same way as for a normal array, with the first Element at index 0, and
266negative indexes used to identify a "from the end" position.
267
268=cut
269
270
# spent 311ms (265+45.8) within PPI::Node::schild which was called 29896 times, avg 10µs/call: # 6883 times (91.3ms+14.9ms) by PPI::Lexer::_add_element at line 1445 of PPI/Lexer.pm, avg 15µs/call # 6883 times (42.5ms+6.88ms) by PPI::Lexer::_add_element at line 1444 of PPI/Lexer.pm, avg 7µs/call # 3157 times (18.3ms+2.82ms) by PPI::Lexer::_round at line 990 of PPI/Lexer.pm, avg 7µs/call # 2355 times (16.6ms+2.21ms) by PPI::Statement::Compound::type at line 194 of PPI/Statement/Compound.pm, avg 8µs/call # 2273 times (12.5ms+1.91ms) by PPI::Lexer::_curly at line 1189 of PPI/Lexer.pm, avg 6µs/call # 1520 times (8.78ms+1.42ms) by PPI::Lexer::_continues at line 705 of PPI/Lexer.pm, avg 7µs/call # 1410 times (21.1ms+3.99ms) by PPI::Statement::Include::module at line 125 of PPI/Statement/Include.pm, avg 18µs/call # 1268 times (6.48ms+1.13ms) by PPI::Statement::Include::type at line 92 of PPI/Statement/Include.pm, avg 6µs/call # 1266 times (19.0ms+3.62ms) by PPI::Statement::Include::version at line 266 of PPI/Statement/Include.pm, avg 18µs/call # 982 times (9.10ms+2.66ms) by Perl::Critic::Policy::Modules::RequireBarewordIncludes::violates at line 36 of Perl/Critic/Policy/Modules/RequireBarewordIncludes.pm, avg 12µs/call # 587 times (5.69ms+1.57ms) by PPI::Statement::Compound::type at line 204 of PPI/Statement/Compound.pm, avg 12µs/call # 359 times (2.20ms+319µs) by PPI::Lexer::_square at line 1026 of PPI/Lexer.pm, avg 7µs/call # 329 times (3.52ms+903µs) by PPI::Lexer::_continues at line 750 of PPI/Lexer.pm, avg 13µs/call # 144 times (3.85ms+273µs) by Perl::Critic::Document::AUTOLOAD at line 41 of Perl/Critic/Document.pm, avg 29µs/call # 144 times (1.42ms+404µs) by PPI::Statement::Package::namespace at line 94 of PPI/Statement/Package.pm, avg 13µs/call # 93 times (1.01ms+298µs) by PPI::Statement::Compound::type at line 197 of PPI/Statement/Compound.pm, avg 14µs/call # 86 times (837µs+254µs) by Perl::Critic::Policy::Variables::RequireLexicalLoopIterators::violates at line 57 of Perl/Critic/Policy/Variables/RequireLexicalLoopIterators.pm, avg 13µs/call # 86 times (407µs+75µs) by Perl::Critic::Policy::Variables::RequireLexicalLoopIterators::violates at line 53 of Perl/Critic/Policy/Variables/RequireLexicalLoopIterators.pm, avg 6µs/call # 54 times (585µs+156µs) by PPI::Lexer::_curly at line 1253 of PPI/Lexer.pm, avg 14µs/call # 16 times (177µs+35µs) by Perl::Critic::Annotation::_is_single_line_annotation_on_simple_statement at line 205 of Perl/Critic/Annotation.pm, avg 13µs/call # once (7µs+2µs) by PPI::Lexer::_curly at line 1211 of PPI/Lexer.pm
sub schild {
271298965.19ms my $self = shift;
272298967.19ms1618µs my $idx = 0 + shift;
# spent 18µs making 16 calls to Readonly::Scalar::FETCH, avg 1µs/call
273298969.90ms my $el = $self->{children};
274298965.55ms if ( $idx < 0 ) {
2756189778µs my $cursor = 0;
27661892.31ms while ( exists $el->[--$cursor] ) {
277687132.0ms68716.13ms return $el->[$cursor] if $el->[$cursor]->significant and ++$idx >= 0;
# spent 5.74ms making 6486 calls to PPI::Element::significant, avg 885ns/call # spent 386µs making 385 calls to PPI::Token::Whitespace::significant, avg 1µs/call
278 }
279 } else {
280237072.08ms my $cursor = -1;
281237076.02ms while ( exists $el->[++$cursor] ) {
28243420117ms4342039.7ms return $el->[$cursor] if $el->[$cursor]->significant and --$idx < 0;
# spent 29.6ms making 33407 calls to PPI::Element::significant, avg 885ns/call # spent 10.0ms making 9921 calls to PPI::Token::Whitespace::significant, avg 1µs/call # spent 91µs making 92 calls to PPI::Token::Comment::significant, avg 988ns/call
283 }
284 }
285182711.7ms undef;
286}
287
288=pod
289
290=head2 contains $Element
291
292The C<contains> method is used to determine if another L<PPI::Element>
293object is logically "within" a C<PPI::Node>. For the special case of the
294brace tokens at either side of a L<PPI::Structure> object, they are
295generally considered "within" a L<PPI::Structure> object, even if they are
296not actually in the elements for the L<PPI::Structure>.
297
298Returns true if the L<PPI::Element> is within us, false if not, or C<undef>
299on error.
300
301=cut
302
303sub contains {
304 my $self = shift;
305 my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
306
307 # Iterate up the Element's parent chain until we either run out
308 # of parents, or get to ourself.
309 while ( $Element = $Element->parent ) {
310 return 1 if refaddr($self) == refaddr($Element);
311 }
312
313 '';
314}
315
316=pod
317
318=head2 find $class | \&wanted
319
320The C<find> method is used to search within a code tree for
321L<PPI::Element> objects that meet a particular condition.
322
323To specify the condition, the method can be provided with either a simple
324class name (full or shortened), or a C<CODE>/function reference.
325
326 # Find all single quotes in a Document (which is a Node)
327 $Document->find('PPI::Quote::Single');
328
329 # The same thing with a shortened class name
330 $Document->find('Quote::Single');
331
332 # Anything more elaborate, we so with the sub
333 $Document->find( sub {
334 # At the top level of the file...
335 $_[1]->parent == $_[0]
336 and (
337 # ...find all comments and POD
338 $_[1]->isa('PPI::Token::Pod')
339 or
340 $_[1]->isa('PPI::Token::Comment')
341 )
342 } );
343
344The function will be passed two arguments, the top-level C<PPI::Node>
345you are searching in and the current L<PPI::Element> that the condition
346is testing.
347
348The anonymous function should return one of three values. Returning true
349indicates a condition match, defined-false (C<0> or C<''>) indicates
350no-match, and C<undef> indicates no-match and no-descend.
351
352In the last case, the tree walker will skip over anything below the
353C<undef>-returning element and move on to the next element at the same
354level.
355
356To halt the entire search and return C<undef> immediately, a condition
357function should throw an exception (i.e. C<die>).
358
359Note that this same wanted logic is used for all methods documented to
360have a C<\&wanted> parameter, as this one does.
361
362The C<find> method returns a reference to an array of L<PPI::Element>
363objects that match the condition, false (but defined) if no Elements match
364the condition, or C<undef> if you provide a bad condition, or an error
365occurs during the search process.
366
367In the case of a bad condition, a warning will be emitted as well.
368
369=cut
370
371
# spent 6.01s (3.37+2.64) within PPI::Node::find which was called 3668 times, avg 1.64ms/call: # 1293 times (62.8ms+103ms) by Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations::violates at line 38 of Perl/Critic/Policy/Variables/ProhibitConditionalDeclarations.pm, avg 128µs/call # 1016 times (780ms+575ms) by Perl::Critic::Utils::McCabe::_count_logic_keywords at line 110 of Perl/Critic/Utils/McCabe.pm, avg 1.33ms/call # 1016 times (748ms+580ms) by Perl::Critic::Utils::McCabe::_count_logic_operators at line 129 of Perl/Critic/Utils/McCabe.pm, avg 1.31ms/call # 144 times (965ms+691ms) by Perl::Critic::Document::find at line 179 of Perl/Critic/Document.pm, avg 11.5ms/call # 144 times (807ms+679ms) by Perl::Critic::Document::find at line 160 of Perl/Critic/Document.pm, avg 10.3ms/call # 55 times (7.60ms+9.02ms) by Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions::_has_topic_side_effect at line 119 of Perl/Critic/Policy/ControlStructures/ProhibitMutatingListFunctions.pm, avg 302µs/call
sub find {
3723668730µs my $self = shift;
37336684.65ms3668155ms my $wanted = $self->_wanted(shift) or return undef;
# spent 155ms making 3668 calls to PPI::Node::_wanted, avg 42µs/call
374
375 # Use a queue based search, rather than a recursive one
37636681.30ms my @found = ();
37736685.36ms my @queue = @{$self->{children}};
37836681.07ms eval {
379366877.3ms while ( @queue ) {
38040629082.6ms my $Element = shift @queue;
381406290432ms4062901.88s my $rv = &$wanted( $self, $Element );
# spent 515ms making 110552 calls to Perl::Critic::Document::__ANON__[Perl/Critic/Document.pm:531], avg 5µs/call # spent 513ms making 110552 calls to Perl::Critic::Document::_is_a_version_statement, avg 5µs/call # spent 386ms making 86181 calls to PPI::Node::__ANON__[(eval 1000)[PPI/Node.pm:654]:4], avg 4µs/call # spent 366ms making 86181 calls to PPI::Node::__ANON__[(eval 1001)[PPI/Node.pm:654]:4], avg 4µs/call # spent 97.6ms making 12164 calls to Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations::_is_conditional, avg 8µs/call # spent 2.88ms making 660 calls to PPI::Node::__ANON__[(eval 1243)[PPI/Node.pm:654]:4], avg 4µs/call
38240629013.6ms push @found, $Element if $rv;
383
384 # Support "don't descend on undef return"
38540629043.4ms next unless defined $rv;
386
387 # Skip if the Element doesn't have any children
3883941261.25s394126384ms next unless $Element->isa('PPI::Node');
# spent 340ms making 383503 calls to UNIVERSAL::isa, avg 887ns/call # spent 43.8ms making 10611 calls to PPI::Structure::List::isa, avg 4µs/call # spent 58µs making 12 calls to PPI::Structure::For::isa, avg 5µs/call
389
390 # Depth-first keeps the queue size down and provides a
391 # better logical order.
39258424179ms5842487.8ms if ( $Element->isa('PPI::Structure') ) {
# spent 47.2ms making 10611 calls to PPI::Structure::List::isa, avg 4µs/call # spent 40.6ms making 47801 calls to UNIVERSAL::isa, avg 850ns/call # spent 46µs making 12 calls to PPI::Structure::For::isa, avg 4µs/call
39322718118ms6815467.4ms unshift @queue, $Element->finish if $Element->finish;
# spent 53.3ms making 45436 calls to PPI::Structure::finish, avg 1µs/call # spent 14.1ms making 22718 calls to PPI::Util::TRUE, avg 619ns/call
3942271819.1ms unshift @queue, @{$Element->{children}};
39522718108ms6815463.1ms unshift @queue, $Element->start if $Element->start;
# spent 50.8ms making 45436 calls to PPI::Structure::start, avg 1µs/call # spent 12.3ms making 22718 calls to PPI::Util::TRUE, avg 539ns/call
396 } else {
3973570646.0ms unshift @queue, @{$Element->{children}};
398 }
399 }
400 };
4013668291µs if ( $@ ) {
402 # Caught exception thrown from the wanted function
403 return undef;
404 }
405
406366821.0ms @found ? \@found : '';
407}
408
409=pod
410
411=head2 find_first $class | \&wanted
412
413If the normal C<find> method is like a grep, then C<find_first> is
414equivalent to the L<Scalar::Util> C<first> function.
415
416Given an element class or a wanted function, it will search depth-first
417through a tree until it finds something that matches the condition,
418returning the first Element that it encounters.
419
420See the C<find> method for details on the format of the search condition.
421
422Returns the first L<PPI::Element> object that matches the condition, false
423if nothing matches the condition, or C<undef> if given an invalid condition,
424or an error occurs.
425
426=cut
427
428
# spent 1.40s (821ms+582ms) within PPI::Node::find_first which was called 1160 times, avg 1.21ms/call: # 1016 times (796ms+527ms) by Perl::Critic::Policy::Subroutines::ProhibitNestedSubs::violates at line 47 of Perl/Critic/Policy/Subroutines/ProhibitNestedSubs.pm, avg 1.30ms/call # 144 times (24.6ms+54.8ms) by Perl::Critic::Document::find_first at line 194 of Perl/Critic/Document.pm, avg 551µs/call
sub find_first {
4291160305µs my $self = shift;
43011601.59ms11605.13ms my $wanted = $self->_wanted(shift) or return undef;
# spent 5.13ms making 1160 calls to PPI::Node::_wanted, avg 4µs/call
431
432 # Use the same queue-based search as for ->find
43311602.40ms my @queue = @{$self->{children}};
4341160461µs my $rv = eval {
435 # The defined() here prevents a ton of calls to PPI::Util::TRUE
436116016.4ms while ( @queue ) {
4378819218.5ms my $Element = shift @queue;
43888192103ms88192450ms my $rv = &$wanted( $self, $Element );
439881921.92ms return $Element if $rv;
440
441 # Support "don't descend on undef return"
442880489.15ms next unless defined $rv;
443
444 # Skip if the Element doesn't have any children
44588048264ms8804882.7ms next unless $Element->isa('PPI::Node');
# spent 72.9ms making 85441 calls to UNIVERSAL::isa, avg 854ns/call # spent 9.73ms making 2604 calls to PPI::Structure::List::isa, avg 4µs/call # spent 11µs making 3 calls to PPI::Structure::For::isa, avg 4µs/call
446
447 # Depth-first keeps the queue size down and provides a
448 # better logical order.
4491310436.9ms1310418.4ms if ( $Element->isa('PPI::Structure') ) {
# spent 9.32ms making 2604 calls to PPI::Structure::List::isa, avg 4µs/call # spent 9.07ms making 10497 calls to UNIVERSAL::isa, avg 864ns/call # spent 10µs making 3 calls to PPI::Structure::For::isa, avg 3µs/call
450554913.2ms1109813.2ms unshift @queue, $Element->finish if defined($Element->finish);
# spent 13.2ms making 11098 calls to PPI::Structure::finish, avg 1µs/call
45155495.31ms unshift @queue, @{$Element->{children}};
452554912.2ms1109812.6ms unshift @queue, $Element->start if defined($Element->start);
# spent 12.6ms making 11098 calls to PPI::Structure::start, avg 1µs/call
453 } else {
454755510.8ms unshift @queue, @{$Element->{children}};
455 }
456 }
457 };
4581160117µs if ( $@ ) {
459 # Caught exception thrown from the wanted function
460 return undef;
461 }
462
46311605.81ms144102µs $rv or '';
# spent 102µs making 144 calls to PPI::Util::TRUE, avg 708ns/call
464}
465
466=pod
467
468=head2 find_any $class | \&wanted
469
470The C<find_any> method is a short-circuiting true/false method that behaves
471like the normal C<find> method, but returns true as soon as it finds any
472Elements that match the search condition.
473
474See the C<find> method for details on the format of the search condition.
475
476Returns true if any Elements that match the condition can be found, false if
477not, or C<undef> if given an invalid condition, or an error occurs.
478
479=cut
480
481sub find_any {
482 my $self = shift;
483 my $rv = $self->find_first(@_);
484 $rv ? 1 : $rv; # false or undef
485}
486
487=pod
488
489=head2 remove_child $Element
490
491If passed a L<PPI::Element> object that is a direct child of the Node,
492the C<remove_element> method will remove the C<Element> intact, along
493with any of its children. As such, this method acts essentially as a
494'cut' function.
495
496If successful, returns the removed element. Otherwise, returns C<undef>.
497
498=cut
499
500sub remove_child {
501 my $self = shift;
502 my $child = _INSTANCE(shift, 'PPI::Element') or return undef;
503
504 # Find the position of the child
505 my $key = refaddr $child;
506 my $p = List::MoreUtils::firstidx {
507 refaddr $_ == $key
508 } @{$self->{children}};
509 return undef unless defined $p;
510
511 # Splice it out, and remove the child's parent entry
512 splice( @{$self->{children}}, $p, 1 );
513 delete $_PARENT{refaddr $child};
514
515 $child;
516}
517
518=pod
519
520=head2 prune $class | \&wanted
521
522The C<prune> method is used to strip L<PPI::Element> objects out of a code
523tree. The argument is the same as for the C<find> method, either a class
524name, or an anonymous subroutine which returns true/false. Any Element
525that matches the class|wanted will be deleted from the code tree, along
526with any of its children.
527
528The C<prune> method returns the number of C<Element> objects that matched
529and were removed, B<non-recursively>. This might also be zero, so avoid a
530simple true/false test on the return false of the C<prune> method. It
531returns C<undef> on error, which you probably B<should> test for.
532
533=begin testing prune 2
534
535# Avoids a bug in old Perls relating to the detection of scripts
536# Known to occur in ActivePerl 5.6.1 and at least one 5.6.2 install.
537my $hashbang = reverse 'lrep/nib/rsu/!#';
538my $document = PPI::Document->new( \<<"END_PERL" );
539$hashbang
540
541use strict;
542
543sub one { 1 }
544sub two { 2 }
545sub three { 3 }
546
547print one;
548print "\n";
549print three;
550print "\n";
551
552exit;
553END_PERL
554
555isa_ok( $document, 'PPI::Document' );
556ok( defined($document->prune ('PPI::Statement::Sub')),
557 'Pruned multiple subs ok' );
558
559=end testing
560
561=cut
562
563sub prune {
564 my $self = shift;
565 my $wanted = $self->_wanted(shift) or return undef;
566
567 # Use a depth-first queue search
568 my $pruned = 0;
569 my @queue = $self->children;
570 eval {
571 while ( my $element = shift @queue ) {
572 my $rv = &$wanted( $self, $element );
573 if ( $rv ) {
574 # Delete the child
575 $element->delete or return undef;
576 $pruned++;
577 next;
578 }
579
580 # Support the undef == "don't descend"
581 next unless defined $rv;
582
583 if ( _INSTANCE($element, 'PPI::Node') ) {
584 # Depth-first keeps the queue size down
585 unshift @queue, $element->children;
586 }
587 }
588 };
589 if ( $@ ) {
590 # Caught exception thrown from the wanted function
591 return undef;
592 }
593
594 $pruned;
595}
596
597# This method is likely to be very heavily used, to take
598# it slowly and carefuly.
599### NOTE: Renaming this function or changing either to self will probably
600### break File::Find::Rule::PPI
601
# spent 160ms (140+20.5) within PPI::Node::_wanted which was called 4828 times, avg 33µs/call: # 3668 times (135ms+19.6ms) by PPI::Node::find at line 373, avg 42µs/call # 1160 times (4.28ms+858µs) by PPI::Node::find_first at line 430, avg 4µs/call
sub _wanted {
6024828675µs my $either = shift;
60348281.64ms my $it = defined($_[0]) ? shift : do {
604 Carp::carp('Undefined value passed as search condition') if $^W;
605 return undef;
606 };
607
608 # Has the caller provided a wanted function directly
609482826.8ms48283.47ms return $it if _CODELIKE($it);
# spent 3.47ms making 4828 calls to Params::Util::_CODELIKE, avg 720ns/call
6102087275µs if ( ref $it ) {
611 # No other ref types are supported
612 Carp::carp('Illegal non-CODE reference passed as search condition') if $^W;
613 return undef;
614 }
615
616 # The first argument should be an Element class, possibly in shorthand
61720871.39ms $it = "PPI::$it" unless substr($it, 0, 5) eq 'PPI::';
618208710.2ms417417.0ms unless ( _CLASS($it) and $it->isa('PPI::Element') ) {
# spent 14.1ms making 2087 calls to Params::Util::_CLASS, avg 7µs/call # spent 2.95ms making 2087 calls to UNIVERSAL::isa, avg 1µs/call
619 # We got something, but it isn't an element
620 Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
621 return undef;
622 }
623
624 # Create the class part of the wanted function
62520871.39ms my $wanted_class = "\n\treturn '' unless \$_[1]->isa('$it');";
626
627 # Have we been given a second argument to check the content
6282087287µs my $wanted_content = '';
6292087372µs if ( defined $_[0] ) {
630 my $content = shift;
631 if ( ref $content eq 'Regexp' ) {
632 $content = "$content";
633 } elsif ( ref $content ) {
634 # No other ref types are supported
635 Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
636 return undef;
637 } else {
638 $content = quotemeta $content;
639 }
640
641 # Complete the content part of the wanted function
642 $wanted_content .= "\n\treturn '' unless defined \$_[1]->{content};";
643 $wanted_content .= "\n\treturn '' unless \$_[1]->{content} =~ /$content/;";
644 }
645
646 # Create the complete wanted function
64720871.48ms my $code = "sub {"
648 . $wanted_class
649 . $wanted_content
650 . "\n\t1;"
651 . "\n}";
652
653 # Compile the wanted function
654208788.9ms $code = eval $code;
# spent 582ms executing statements in 1016 string evals (merged)
# includes 308ms spent executing 86181 calls to 1 sub defined therein. # spent 569ms executing statements in 1016 string evals (merged)
# includes 290ms spent executing 86181 calls to 1 sub defined therein. # spent 5.69ms executing statements in 55 string evals (merged)
# includes 2.28ms spent executing 660 calls to 1 sub defined therein.
655208710.2ms (ref $code eq 'CODE') ? $code : undef;
656}
657
- -
662####################################################################
663# PPI::Element overloaded methods
664
665
# spent 931ms (642+290) within PPI::Node::tokens which was called 32942 times, avg 28µs/call: # 21076 times (424ms+-424ms) by PPI::Node::tokens at line 666, avg 0s/call # 11578 times (170ms+-170ms) by PPI::Structure::tokens at line 278 of PPI/Structure.pm, avg 0s/call # 144 times (24.9ms+475ms) by PPI::Document::index_locations at line 592 of PPI/Document.pm, avg 3.47ms/call # 144 times (22.9ms+408ms) by PPI::Document::serialize at line 423 of PPI/Document.pm, avg 2.99ms/call
sub tokens {
666230890343ms197948868ms map { $_->tokens } @{$_[0]->{children}};
# spent 1.40s making 11578 calls to PPI::Structure::tokens, avg 121µs/call, recursion: max depth 6, sum of overlapping time 664ms # spent 133ms making 165294 calls to PPI::Element::tokens, avg 802ns/call # spent 1.92s making 21076 calls to PPI::Node::tokens, avg 91µs/call, recursion: max depth 15, sum of overlapping time 1.92s
667}
668
669### XS -> PPI/XS.xs:_PPI_Element__content 0.900+
670
# spent 82.0ms (56.3+25.7) within PPI::Node::content which was called 2076 times, avg 40µs/call: # 1929 times (54.0ms+24.8ms) by PPI::Structure::content at line 293 of PPI/Structure.pm, avg 41µs/call # 144 times (2.23ms+814µs) by Perl::Critic::Document::CORE:match at line 552 of Perl/Critic/Document.pm, avg 21µs/call # 3 times (102µs+131µs) by Perl::Critic::Violation::_line_containing_violation at line 304 of Perl/Critic/Violation.pm, avg 78µs/call
sub content {
6711075420.7ms867810.5ms join '', map { $_->content } @{$_[0]->{children}};
# spent 10.4ms making 7954 calls to PPI::Token::content, avg 1µs/call # spent 46.1ms making 724 calls to PPI::Structure::content, avg 64µs/call, recursion: max depth 5, sum of overlapping time 46.0ms
672}
673
674# Clone as normal, but then go down and relink all the _PARENT entries
675sub clone {
676 my $self = shift;
677 my $clone = $self->SUPER::clone;
678 $clone->__link_children;
679 $clone;
680}
681
682
# spent 127ms (61.5+65.6) within PPI::Node::location which was called 9610 times, avg 13µs/call: # 9268 times (58.9ms+62.5ms) by Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict::violates at line 73 of Perl/Critic/Policy/TestingAndDebugging/RequireUseStrict.pm, avg 13µs/call # 144 times (1.17ms+1.47ms) by PPI::Element::logical_filename at line 974 of PPI/Element.pm, avg 18µs/call # 144 times (1.07ms+1.37ms) by Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict::violates at line 59 of Perl/Critic/Policy/TestingAndDebugging/RequireUseStrict.pm, avg 17µs/call # 51 times (324µs+307µs) by PPI::Element::logical_line_number at line 932 of PPI/Element.pm, avg 12µs/call # 3 times (17µs+16µs) by PPI::Element::line_number at line 814 of PPI/Element.pm, avg 11µs/call
sub location {
68396102.02ms my $self = shift;
684961031.4ms96105.22ms my $first = $self->{children}->[0] or return undef;
# spent 5.22ms making 9610 calls to PPI::Util::TRUE, avg 543ns/call
685961023.9ms961060.4ms $first->location;
# spent 60.2ms making 9602 calls to PPI::Element::location, avg 6µs/call # spent 180µs making 8 calls to PPI::Structure::location, avg 23µs/call
686}
687
- -
692#####################################################################
693# Internal Methods
694
695
# spent 999ms (601+398) within PPI::Node::DESTROY which was called 16471 times, avg 61µs/call: # 16327 times (72.3ms+-72.3ms) by PPI::Node::DESTROY at line 700, avg 0s/call # 144 times (529ms+470ms) by Perl::Critic::critique at line 249 of Perl/Critic/Command.pm, avg 6.94ms/call
sub DESTROY {
696164711.18ms local $_;
697164715.92ms if ( $_[0]->{children} ) {
698144149µs my @queue = $_[0];
699144204µs while ( defined($_ = shift @queue) ) {
70099118107ms98830338ms unshift @queue, @{delete $_->{children}} if $_->{children};
# spent 338ms making 82503 calls to PPI::Element::DESTROY, avg 4µs/call # spent 81.6ms making 16327 calls to PPI::Node::DESTROY, avg 5µs/call, recursion: max depth 1, sum of overlapping time 81.6ms
701
702 # Remove all internal/private weird crosslinking so that
703 # the cascading DESTROY calls will get called properly.
70499118254ms1157849.3ms %$_ = ();
# spent 49.3ms making 11578 calls to PPI::Element::DESTROY, avg 4µs/call
705 }
706 }
707
708 # Remove us from our parent node as normal
7091647187.8ms1661510.0ms delete $_PARENT{refaddr $_[0]};
# spent 9.49ms making 16471 calls to Scalar::Util::refaddr, avg 576ns/call # spent 528µs making 144 calls to PPI::Element::DESTROY, avg 4µs/call
710}
711
712# Find the position of a child
713sub __position {
714 my $key = refaddr $_[1];
715 List::MoreUtils::firstidx { refaddr $_ == $key } @{$_[0]->{children}};
716}
717
718# Insert one or more elements before a child
719sub __insert_before_child {
720 my $self = shift;
721 my $key = refaddr shift;
722 my $p = List::MoreUtils::firstidx {
723 refaddr $_ == $key
724 } @{$self->{children}};
725 foreach ( @_ ) {
726 Scalar::Util::weaken(
727 $_PARENT{refaddr $_} = $self
728 );
729 }
730 splice( @{$self->{children}}, $p, 0, @_ );
731 1;
732}
733
734# Insert one or more elements after a child
735sub __insert_after_child {
736 my $self = shift;
737 my $key = refaddr shift;
738 my $p = List::MoreUtils::firstidx {
739 refaddr $_ == $key
740 } @{$self->{children}};
741 foreach ( @_ ) {
742 Scalar::Util::weaken(
743 $_PARENT{refaddr $_} = $self
744 );
745 }
746 splice( @{$self->{children}}, $p + 1, 0, @_ );
747 1;
748}
749
750# Replace a child
751sub __replace_child {
752 my $self = shift;
753 my $key = refaddr shift;
754 my $p = List::MoreUtils::firstidx {
755 refaddr $_ == $key
756 } @{$self->{children}};
757 foreach ( @_ ) {
758 Scalar::Util::weaken(
759 $_PARENT{refaddr $_} = $self
760 );
761 }
762 splice( @{$self->{children}}, $p, 1, @_ );
763 1;
764}
765
766# Create PARENT links for an entire tree.
767# Used when cloning or thawing.
768sub __link_children {
769 my $self = shift;
770
771 # Relink all our children ( depth first )
772 my @queue = ( $self );
773 while ( my $Node = shift @queue ) {
774 # Link our immediate children
775 foreach my $Element ( @{$Node->{children}} ) {
776 Scalar::Util::weaken(
777 $_PARENT{refaddr($Element)} = $Node
778 );
779 unshift @queue, $Element if $Element->isa('PPI::Node');
780 }
781
782 # If it's a structure, relink the open/close braces
783 next unless $Node->isa('PPI::Structure');
784 Scalar::Util::weaken(
785 $_PARENT{refaddr($Node->start)} = $Node
786 ) if $Node->start;
787 Scalar::Util::weaken(
788 $_PARENT{refaddr($Node->finish)} = $Node
789 ) if $Node->finish;
790 }
791
792 1;
793}
794
79512µs1;
796
797=pod
798
799=head1 TO DO
800
801- Move as much as possible to L<PPI::XS>
802
803=head1 SUPPORT
804
805See the L<support section|PPI/SUPPORT> in the main module.
806
807=head1 AUTHOR
808
809Adam Kennedy E<lt>adamk@cpan.orgE<gt>
810
811=head1 COPYRIGHT
812
813Copyright 2001 - 2011 Adam Kennedy.
814
815This program is free software; you can redistribute
816it and/or modify it under the same terms as Perl itself.
817
818The full text of the license can be found in the
819LICENSE file included with this module.
820
821=cut