Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / PPI / Node.pm
CommitLineData
3fea05b9 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
51use strict;
52use Carp ();
53use Scalar::Util qw{refaddr};
54use List::MoreUtils ();
55use Params::Util qw{_INSTANCE _CLASS _CODELIKE};
56use PPI::Element ();
57
58use vars qw{$VERSION @ISA *_PARENT};
59BEGIN {
60 $VERSION = '1.206';
61 @ISA = 'PPI::Element';
62 *_PARENT = *PPI::Element::_PARENT;
63}
64
65
66
67
68
69#####################################################################
70# The basic constructor
71
72sub new {
73 my $class = ref $_[0] || $_[0];
74 bless { children => [] }, $class;
75}
76
77
78
79
80
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
173sub first_element {
174 $_[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
212sub children {
213 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
228sub schildren {
229 return grep { $_->significant } @{$_[0]->{children}} if wantarray;
230 my $count = 0;
231 foreach ( @{$_[0]->{children}} ) {
232 $count++ if $_->significant;
233 }
234 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
249sub child {
250 $_[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
270sub schild {
271 my $self = shift;
272 my $idx = 0 + shift;
273 my $el = $self->{children};
274 if ( $idx < 0 ) {
275 my $cursor = 0;
276 while ( exists $el->[--$cursor] ) {
277 return $el->[$cursor] if $el->[$cursor]->significant and ++$idx >= 0;
278 }
279 } else {
280 my $cursor = -1;
281 while ( exists $el->[++$cursor] ) {
282 return $el->[$cursor] if $el->[$cursor]->significant and --$idx < 0;
283 }
284 }
285 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
371sub find {
372 my $self = shift;
373 my $wanted = $self->_wanted(shift) or return undef;
374
375 # Use a queue based search, rather than a recursive one
376 my @found = ();
377 my @queue = $self->children;
378 eval {
379 while ( my $Element = shift @queue ) {
380 my $rv = &$wanted( $self, $Element );
381 push @found, $Element if $rv;
382
383 # Support "don't descend on undef return"
384 next unless defined $rv;
385
386 # Skip if the Element doesn't have any children
387 next unless $Element->isa('PPI::Node');
388
389 # Depth-first keeps the queue size down and provides a
390 # better logical order.
391 if ( $Element->isa('PPI::Structure') ) {
392 unshift @queue, $Element->finish if $Element->finish;
393 unshift @queue, $Element->children;
394 unshift @queue, $Element->start if $Element->start;
395 } else {
396 unshift @queue, $Element->children;
397 }
398 }
399 };
400 if ( $@ ) {
401 # Caught exception thrown from the wanted function
402 return undef;
403 }
404
405 @found ? \@found : '';
406}
407
408=pod
409
410=head2 find_first $class | \&wanted
411
412If the normal C<find> method is like a grep, then C<find_first> is
413equivalent to the L<Scalar::Util> C<first> function.
414
415Given an element class or a wanted function, it will search depth-first
416through a tree until it finds something that matches the condition,
417returning the first Element that it encounters.
418
419See the C<find> method for details on the format of the search condition.
420
421Returns the first L<PPI::Element> object that matches the condition, false
422if nothing matches the condition, or C<undef> if given an invalid condition,
423or an error occurs.
424
425=cut
426
427sub find_first {
428 my $self = shift;
429 my $wanted = $self->_wanted(shift) or return undef;
430
431 # Use the same queue-based search as for ->find
432 my @queue = $self->children;
433 my $rv = eval {
434 # The defined() here prevents a ton of calls to PPI::Util::TRUE
435 while ( defined( my $Element = shift @queue ) ) {
436 my $rv = &$wanted( $self, $Element );
437 return $Element if $rv;
438
439 # Support "don't descend on undef return"
440 next unless defined $rv;
441
442 # Skip if the Element doesn't have any children
443 next unless $Element->isa('PPI::Node');
444
445 # Depth-first keeps the queue size down and provides a
446 # better logical order.
447 if ( $Element->isa('PPI::Structure') ) {
448 unshift @queue, $Element->finish if defined($Element->finish);
449 unshift @queue, $Element->children;
450 unshift @queue, $Element->start if defined($Element->start);
451 } else {
452 unshift @queue, $Element->children;
453 }
454 }
455 };
456 if ( $@ ) {
457 # Caught exception thrown from the wanted function
458 return undef;
459 }
460
461 $rv or '';
462}
463
464=pod
465
466=head2 find_any $class | \&wanted
467
468The C<find_any> method is a short-circuiting true/false method that behaves
469like the normal C<find> method, but returns true as soon as it finds any
470Elements that match the search condition.
471
472See the C<find> method for details on the format of the search condition.
473
474Returns true if any Elements that match the condition can be found, false if
475not, or C<undef> if given an invalid condition, or an error occurs.
476
477=cut
478
479sub find_any {
480 my $self = shift;
481 my $rv = $self->find_first(@_);
482 $rv ? 1 : $rv; # false or undef
483}
484
485=pod
486
487=head2 remove_child $Element
488
489If passed a L<PPI::Element> object that is a direct child of the Node,
490the C<remove_element> method will remove the C<Element> intact, along
491with any of its children. As such, this method acts essentially as a
492'cut' function.
493
494If successful, returns the removed element. Otherwise, returns C<undef>.
495
496=cut
497
498sub remove_child {
499 my $self = shift;
500 my $child = _INSTANCE(shift, 'PPI::Element') or return undef;
501
502 # Find the position of the child
503 my $key = refaddr $child;
504 my $p = List::MoreUtils::firstidx {
505 refaddr $_ == $key
506 } @{$self->{children}};
507 return undef unless defined $p;
508
509 # Splice it out, and remove the child's parent entry
510 splice( @{$self->{children}}, $p, 1 );
511 delete $_PARENT{refaddr $child};
512
513 $child;
514}
515
516=pod
517
518=head2 prune $class | \&wanted
519
520The C<prune> method is used to strip L<PPI::Element> objects out of a code
521tree. The argument is the same as for the C<find> method, either a class
522name, or an anonymous subroutine which returns true/false. Any Element
523that matches the class|wanted will be deleted from the code tree, along
524with any of its children.
525
526The C<prune> method returns the number of C<Element> objects that matched
527and were removed, B<non-recursively>. This might also be zero, so avoid a
528simple true/false test on the return false of the C<prune> method. It
529returns C<undef> on error, which you probably B<should> test for.
530
531=begin testing prune 2
532
533# Avoids a bug in old Perls relating to the detection of scripts
534# Known to occur in ActivePerl 5.6.1 and at least one 5.6.2 install.
535my $hashbang = reverse 'lrep/nib/rsu/!#';
536my $document = PPI::Document->new( \<<"END_PERL" );
537$hashbang
538
539use strict;
540
541sub one { 1 }
542sub two { 2 }
543sub three { 3 }
544
545print one;
546print "\n";
547print three;
548print "\n";
549
550exit;
551END_PERL
552
553isa_ok( $document, 'PPI::Document' );
554ok( defined($document->prune ('PPI::Statement::Sub')),
555 'Pruned multiple subs ok' );
556
557=end testing
558
559=cut
560
561sub prune {
562 my $self = shift;
563 my $wanted = $self->_wanted(shift) or return undef;
564
565 # Use a depth-first queue search
566 my $pruned = 0;
567 my @queue = $self->children;
568 eval {
569 while ( my $element = shift @queue ) {
570 my $rv = &$wanted( $self, $element );
571 if ( $rv ) {
572 # Delete the child
573 $element->delete or return undef;
574 $pruned++;
575 next;
576 }
577
578 # Support the undef == "don't descend"
579 next unless defined $rv;
580
581 if ( _INSTANCE($element, 'PPI::Node') ) {
582 # Depth-first keeps the queue size down
583 unshift @queue, $element->children;
584 }
585 }
586 };
587 if ( $@ ) {
588 # Caught exception thrown from the wanted function
589 return undef;
590 }
591
592 $pruned;
593}
594
595# This method is likely to be very heavily used, to take
596# it slowly and carefuly.
597### NOTE: Renaming this function or changing either to self will probably
598### break File::Find::Rule::PPI
599sub _wanted {
600 my $either = shift;
601 my $it = defined($_[0]) ? shift : do {
602 Carp::carp('Undefined value passed as search condition') if $^W;
603 return undef;
604 };
605
606 # Has the caller provided a wanted function directly
607 return $it if _CODELIKE($it);
608 if ( ref $it ) {
609 # No other ref types are supported
610 Carp::carp('Illegal non-CODE reference passed as search condition') if $^W;
611 return undef;
612 }
613
614 # The first argument should be an Element class, possibly in shorthand
615 $it = "PPI::$it" unless substr($it, 0, 5) eq 'PPI::';
616 unless ( _CLASS($it) and $it->isa('PPI::Element') ) {
617 # We got something, but it isn't an element
618 Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
619 return undef;
620 }
621
622 # Create the class part of the wanted function
623 my $wanted_class = "\n\treturn '' unless \$_[1]->isa('$it');";
624
625 # Have we been given a second argument to check the content
626 my $wanted_content = '';
627 if ( defined $_[0] ) {
628 my $content = shift;
629 if ( ref $content eq 'Regexp' ) {
630 $content = "$content";
631 } elsif ( ref $content ) {
632 # No other ref types are supported
633 Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
634 return undef;
635 } else {
636 $content = quotemeta $content;
637 }
638
639 # Complete the content part of the wanted function
640 $wanted_content .= "\n\treturn '' unless defined \$_[1]->{content};";
641 $wanted_content .= "\n\treturn '' unless \$_[1]->{content} =~ /$content/;";
642 }
643
644 # Create the complete wanted function
645 my $code = "sub {"
646 . $wanted_class
647 . $wanted_content
648 . "\n\t1;"
649 . "\n}";
650
651 # Compile the wanted function
652 $code = eval $code;
653 (ref $code eq 'CODE') ? $code : undef;
654}
655
656
657
658
659
660####################################################################
661# PPI::Element overloaded methods
662
663sub tokens {
664 map { $_->tokens } @{$_[0]->{children}};
665}
666
667### XS -> PPI/XS.xs:_PPI_Element__content 0.900+
668sub content {
669 join '', map { $_->content } @{$_[0]->{children}};
670}
671
672# Clone as normal, but then go down and relink all the _PARENT entries
673sub clone {
674 my $self = shift;
675 my $clone = $self->SUPER::clone;
676 $clone->__link_children;
677 $clone;
678}
679
680sub location {
681 my $self = shift;
682 my $first = $self->{children}->[0] or return undef;
683 $first->location;
684}
685
686
687
688
689
690#####################################################################
691# Internal Methods
692
693sub DESTROY {
694 local $_;
695 if ( $_[0]->{children} ) {
696 my @queue = $_[0];
697 while ( defined($_ = shift @queue) ) {
698 unshift @queue, @{delete $_->{children}} if $_->{children};
699
700 # Remove all internal/private weird crosslinking so that
701 # the cascading DESTROY calls will get called properly.
702 %$_ = ();
703 }
704 }
705
706 # Remove us from our parent node as normal
707 delete $_PARENT{refaddr $_[0]};
708}
709
710# Find the position of a child
711sub __position {
712 my $key = refaddr $_[1];
713 List::MoreUtils::firstidx { refaddr $_ == $key } @{$_[0]->{children}};
714}
715
716# Insert one or more elements before a child
717sub __insert_before_child {
718 my $self = shift;
719 my $key = refaddr shift;
720 my $p = List::MoreUtils::firstidx {
721 refaddr $_ == $key
722 } @{$self->{children}};
723 foreach ( @_ ) {
724 Scalar::Util::weaken(
725 $_PARENT{refaddr $_} = $self
726 );
727 }
728 splice( @{$self->{children}}, $p, 0, @_ );
729 1;
730}
731
732# Insert one or more elements after a child
733sub __insert_after_child {
734 my $self = shift;
735 my $key = refaddr shift;
736 my $p = List::MoreUtils::firstidx {
737 refaddr $_ == $key
738 } @{$self->{children}};
739 foreach ( @_ ) {
740 Scalar::Util::weaken(
741 $_PARENT{refaddr $_} = $self
742 );
743 }
744 splice( @{$self->{children}}, $p + 1, 0, @_ );
745 1;
746}
747
748# Replace a child
749sub __replace_child {
750 my $self = shift;
751 my $key = refaddr shift;
752 my $p = List::MoreUtils::firstidx {
753 refaddr $_ == $key
754 } @{$self->{children}};
755 foreach ( @_ ) {
756 Scalar::Util::weaken(
757 $_PARENT{refaddr $_} = $self
758 );
759 }
760 splice( @{$self->{children}}, $p, 1, @_ );
761 1;
762}
763
764# Create PARENT links for an entire tree.
765# Used when cloning or thawing.
766sub __link_children {
767 my $self = shift;
768
769 # Relink all our children ( depth first )
770 my @queue = ( $self );
771 while ( my $Node = shift @queue ) {
772 # Link our immediate children
773 foreach my $Element ( @{$Node->{children}} ) {
774 Scalar::Util::weaken(
775 $_PARENT{refaddr($Element)} = $Node
776 );
777 unshift @queue, $Element if $Element->isa('PPI::Node');
778 }
779
780 # If it's a structure, relink the open/close braces
781 next unless $Node->isa('PPI::Structure');
782 Scalar::Util::weaken(
783 $_PARENT{refaddr($Node->start)} = $Node
784 ) if $Node->start;
785 Scalar::Util::weaken(
786 $_PARENT{refaddr($Node->finish)} = $Node
787 ) if $Node->finish;
788 }
789
790 1;
791}
792
7931;
794
795=pod
796
797=head1 TO DO
798
799- Move as much as possible to L<PPI::XS>
800
801=head1 SUPPORT
802
803See the L<support section|PPI/SUPPORT> in the main module.
804
805=head1 AUTHOR
806
807Adam Kennedy E<lt>adamk@cpan.orgE<gt>
808
809=head1 COPYRIGHT
810
811Copyright 2001 - 2009 Adam Kennedy.
812
813This program is free software; you can redistribute
814it and/or modify it under the same terms as Perl itself.
815
816The full text of the license can be found in the
817LICENSE file included with this module.
818
819=cut