File Coverage

blib/lib/PPI/Node.pm
Criterion Covered Total %
statement 226 244 92.6
branch 101 132 76.5
condition 12 15 80.0
subroutine 33 34 97.0
pod 19 20 95.0
total 391 445 87.8


line stmt bran cond sub pod time code
1             package PPI::Node;
2              
3             =pod
4              
5             =head1 NAME
6              
7             PPI::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              
40             The C<PPI::Node> class provides an abstract base class for the Element
41             classes that are able to contain other elements L<PPI::Document>,
42             L<PPI::Statement>, and L<PPI::Structure>.
43              
44             As well as those listed below, all of the methods that apply to
45             L<PPI::Element> objects also apply to C<PPI::Node> objects.
46              
47             =head1 METHODS
48              
49             =cut
50              
51 67     67   356 use strict;
  67         105  
  67         2746  
52 67     67   1776 use Carp ();
  67         93  
  67         2863  
53 67     67   1770 use Scalar::Util qw{refaddr};
  67         5139  
  67         7658  
54 67     67   280 use Params::Util qw{_INSTANCE _CLASS _CODELIKE _NUMBER};
  67         3136  
  67         6383  
55 67     67   2435 use PPI::Element ();
  67         3590  
  67         5103  
56 67     67   34925 use PPI::Singletons '%_PARENT', '%_POSITION_CACHE';
  67         164  
  67         158493  
57              
58             our $VERSION = '1.284';
59              
60             our @ISA = "PPI::Element";
61              
62              
63              
64              
65              
66             #####################################################################
67             # The basic constructor
68              
69             sub new {
70 16801   33 16801 0 49966 my $class = ref $_[0] || $_[0];
71 16801         50906 bless { children => [] }, $class;
72             }
73              
74              
75              
76              
77              
78             #####################################################################
79             # PDOM Methods
80              
81             =pod
82              
83             =head2 scope
84              
85             The C<scope> method returns true if the node represents a lexical scope
86             boundary, or false if it does not.
87              
88             =cut
89              
90             ### XS -> PPI/XS.xs:_PPI_Node__scope 0.903+
91             sub scope() { '' }
92              
93             =pod
94              
95             =head2 add_element $Element
96              
97             The C<add_element> method adds a L<PPI::Element> object to the end of a
98             C<PPI::Node>. Because Elements maintain links to their parent, an
99             Element can only be added to a single Node.
100              
101             Returns true if the L<PPI::Element> was added. Returns C<undef> if the
102             Element was already within another Node, or the method is not passed
103             a L<PPI::Element> object.
104              
105             =cut
106              
107             sub add_element {
108 1     1 1 10 my $self = shift;
109              
110             # Check the element
111 1 50       9 my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
112 1 50       4 $_PARENT{refaddr $Element} and return undef;
113              
114             # Add the argument to the elements
115 1         1 push @{$self->{children}}, $Element;
  1         4  
116             Scalar::Util::weaken(
117 1         3 $_PARENT{refaddr $Element} = $self
118             );
119              
120 1         2 1;
121             }
122              
123             # In a typical run profile, add_element is the number 1 resource drain.
124             # This is a highly optimised unsafe version, for internal use only.
125             sub __add_element {
126             Scalar::Util::weaken(
127 0     0   0 $_PARENT{refaddr $_[1]} = $_[0]
128             );
129 0         0 push @{$_[0]->{children}}, $_[1];
  0         0  
130             }
131              
132             =pod
133              
134             =head2 elements
135              
136             The C<elements> method accesses all child elements B<structurally> within
137             the C<PPI::Node> object. Note that in the base of the L<PPI::Structure>
138             classes, this C<DOES> include the brace tokens at either end of the
139             structure.
140              
141             Returns a list of zero or more L<PPI::Element> objects.
142              
143             Alternatively, if called in the scalar context, the C<elements> method
144             returns a count of the number of elements.
145              
146             =cut
147              
148             sub elements {
149 2 50   2 1 484 if ( wantarray ) {
150 2         3 return @{$_[0]->{children}};
  2         5  
151             } else {
152 0         0 return scalar @{$_[0]->{children}};
  0         0  
153             }
154             }
155              
156             =pod
157              
158             =head2 first_element
159              
160             The C<first_element> method accesses the first element structurally within
161             the C<PPI::Node> object. As for the C<elements> method, this does include
162             the brace tokens for L<PPI::Structure> objects.
163              
164             Returns a L<PPI::Element> object, or C<undef> if for some reason the
165             C<PPI::Node> object does not contain any elements.
166              
167             =cut
168              
169             # Normally the first element is also the first child
170             sub first_element {
171 15     15 1 2631 $_[0]->{children}->[0];
172             }
173              
174             =pod
175              
176             =head2 last_element
177              
178             The C<last_element> method accesses the last element structurally within
179             the C<PPI::Node> object. As for the C<elements> method, this does include
180             the brace tokens for L<PPI::Structure> objects.
181              
182             Returns a L<PPI::Element> object, or C<undef> if for some reason the
183             C<PPI::Node> object does not contain any elements.
184              
185             =cut
186              
187             # Normally the last element is also the last child
188             sub last_element {
189 11     11 1 57 $_[0]->{children}->[-1];
190             }
191              
192             =pod
193              
194             =head2 children
195              
196             The C<children> method accesses all child elements lexically within the
197             C<PPI::Node> object. Note that in the case of the L<PPI::Structure>
198             classes, this does B<NOT> include the brace tokens at either end of the
199             structure.
200              
201             Returns a list of zero of more L<PPI::Element> objects.
202              
203             Alternatively, if called in the scalar context, the C<children> method
204             returns a count of the number of lexical children.
205              
206             =cut
207              
208             # In the default case, this is the same as for the elements method
209             sub children {
210 2180 50   2180 1 147702 wantarray ? @{$_[0]->{children}} : scalar @{$_[0]->{children}};
  2180         9093  
  0         0  
211             }
212              
213             =pod
214              
215             =head2 schildren
216              
217             The C<schildren> method is really just a convenience, the significant-only
218             variation of the normal C<children> method.
219              
220             In list context, returns a list of significant children. In scalar context,
221             returns the number of significant children.
222              
223             =cut
224              
225             sub schildren {
226 61080 100   61080 1 8894247 return grep { $_->significant } @{$_[0]->{children}} if wantarray;
  122844         207034  
  30424         52844  
227 30656         39286 my $count = 0;
228 30656         31949 foreach ( @{$_[0]->{children}} ) {
  30656         61406  
229 107427 100       208284 $count++ if $_->significant;
230             }
231 30656         79051 return $count;
232             }
233              
234             =pod
235              
236             =head2 child $index
237              
238             The C<child> method accesses a child L<PPI::Element> object by its
239             position within the Node.
240              
241             Returns a L<PPI::Element> object, or C<undef> if there is no child
242             element at that node.
243              
244             =cut
245              
246             sub child {
247 860     860 1 103540 my ( $self, $index ) = @_;
248 860 100       2798 PPI::Exception->throw( "method child() needs an index" )
249             if not defined _NUMBER $index;
250 858         3492 $self->{children}->[$index];
251             }
252              
253             =pod
254              
255             =head2 schild $index
256              
257             The lexical structure of the Perl language ignores 'insignificant' items,
258             such as whitespace and comments, while L<PPI> treats these items as valid
259             tokens so that it can reassemble the file at any time. Because of this,
260             in many situations there is a need to find an Element within a Node by
261             index, only counting lexically significant Elements.
262              
263             The C<schild> method returns a child Element by index, ignoring
264             insignificant Elements. The index of a child Element is specified in the
265             same way as for a normal array, with the first Element at index 0, and
266             negative indexes used to identify a "from the end" position.
267              
268             =cut
269              
270             sub schild {
271 2122818     2122818 1 9060785 my $self = shift;
272 2122818         2014533 my $idx = 0 + shift;
273 2122818         2257274 my $el = $self->{children};
274 2122818 100       2360621 if ( $idx < 0 ) {
275 79098         80327 my $cursor = 0;
276 79098         152657 while ( exists $el->[--$cursor] ) {
277 93966 100 100     361550 return $el->[$cursor] if $el->[$cursor]->significant and ++$idx >= 0;
278             }
279             } else {
280 2043720         1831606 my $cursor = -1;
281 2043720         2708577 while ( exists $el->[++$cursor] ) {
282 5065888 100 100     14631876 return $el->[$cursor] if $el->[$cursor]->significant and --$idx < 0;
283             }
284             }
285 37728         159965 undef;
286             }
287              
288             =pod
289              
290             =head2 contains $Element
291              
292             The C<contains> method is used to determine if another L<PPI::Element>
293             object is logically "within" a C<PPI::Node>. For the special case of the
294             brace tokens at either side of a L<PPI::Structure> object, they are
295             generally considered "within" a L<PPI::Structure> object, even if they are
296             not actually in the elements for the L<PPI::Structure>.
297              
298             Returns true if the L<PPI::Element> is within us, false if not, or C<undef>
299             on error.
300              
301             =cut
302              
303             sub contains {
304 34     34 1 17885 my $self = shift;
305 34 100       268 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 29         87 while ( $Element = $Element->parent ) {
310 79 100       198 return 1 if refaddr($self) == refaddr($Element);
311             }
312              
313 0         0 '';
314             }
315              
316             =pod
317              
318             =head2 find $class | \&wanted
319              
320             The C<find> method is used to search within a code tree for
321             L<PPI::Element> objects that meet a particular condition.
322              
323             To specify the condition, the method can be provided with either a simple
324             class 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 go 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              
344             The function will be passed two arguments, the top-level C<PPI::Node>
345             you are searching in and the current L<PPI::Element> that the condition
346             is testing.
347              
348             The anonymous function should return one of three values. Returning true
349             indicates a condition match, defined-false (C<0> or C<''>) indicates
350             no-match, and C<undef> indicates no-match and no-descend.
351              
352             In the last case, the tree walker will skip over anything below the
353             C<undef>-returning element and move on to the next element at the same
354             level.
355              
356             To halt the entire search and return C<undef> immediately, a condition
357             function should throw an exception (i.e. C<die>).
358              
359             Note that this same wanted logic is used for all methods documented to
360             have a C<\&wanted> parameter, as this one does.
361              
362             The C<find> method returns a reference to an array of L<PPI::Element>
363             objects that match the condition, false (but defined) if no Elements match
364             the condition, or C<undef> if you provide a bad condition, or an error
365             occurs during the search process.
366              
367             In the case of a bad condition, a warning will be emitted as well.
368              
369             =cut
370              
371             sub find {
372 5174     5174 1 5281250 my $self = shift;
373 5174 100       15723 my $wanted = $self->_wanted(shift) or return undef;
374              
375             # Use a queue based search, rather than a recursive one
376 5171         7307 my @found;
377 5171         7245 my @queue = @{$self->{children}};
  5171         15894  
378 5171         8413 my $ok = eval {
379 5171         11817 while ( @queue ) {
380 355300         355474 my $Element = shift @queue;
381 355300         1407461 my $rv = &$wanted( $self, $Element );
382 355300 100       894436 push @found, $Element if $rv;
383              
384             # Support "don't descend on undef return"
385 355300 50       416941 next unless defined $rv;
386              
387             # Skip if the Element doesn't have any children
388 355300 100       764592 next unless $Element->isa('PPI::Node');
389              
390             # Depth-first keeps the queue size down and provides a
391             # better logical order.
392 60252 100       111842 if ( $Element->isa('PPI::Structure') ) {
393 22130 100       37543 unshift @queue, $Element->finish if $Element->finish;
394 22130         23313 unshift @queue, @{$Element->{children}};
  22130         48003  
395 22130 50       33963 unshift @queue, $Element->start if $Element->start;
396             } else {
397 38122         37189 unshift @queue, @{$Element->{children}};
  38122         113745  
398             }
399             }
400 5171         8420 1;
401             };
402 5171 50       10120 if ( !$ok ) {
403             # Caught exception thrown from the wanted function
404 0         0 return undef;
405             }
406              
407 5171 100       32046 @found ? \@found : '';
408             }
409              
410             =pod
411              
412             =head2 find_first $class | \&wanted
413              
414             If the normal C<find> method is like a grep, then C<find_first> is
415             equivalent to the L<List::Util> C<first> function.
416              
417             Given an element class or a wanted function, it will search depth-first
418             through a tree until it finds something that matches the condition,
419             returning the first Element that it encounters.
420              
421             See the C<find> method for details on the format of the search condition.
422              
423             Returns the first L<PPI::Element> object that matches the condition, false
424             if nothing matches the condition, or C<undef> if given an invalid condition,
425             or an error occurs.
426              
427             =cut
428              
429             sub find_first {
430 2224     2224 1 40557 my $self = shift;
431 2224 50       7303 my $wanted = $self->_wanted(shift) or return undef;
432              
433             # Use the same queue-based search as for ->find
434 2224         3715 my @queue = @{$self->{children}};
  2224         15712  
435 2224         3599 my $rv;
436 2224         3266 my $ok = eval {
437             # The defined() here prevents a ton of calls to PPI::Util::TRUE
438 2224         5393 while ( @queue ) {
439 768578         730956 my $Element = shift @queue;
440 768578         7634504 my $element_rv = $wanted->( $self, $Element );
441 768578 100       1071102 if ( $element_rv ) {
442 39         58 $rv = $Element;
443 39         64 last;
444             }
445              
446             # Support "don't descend on undef return"
447 768539 100       870562 next if !defined $element_rv;
448              
449             # Skip if the Element doesn't have any children
450 744502 100       1533511 next if !$Element->isa('PPI::Node');
451              
452             # Depth-first keeps the queue size down and provides a
453             # better logical order.
454 114169 100       199162 if ( $Element->isa('PPI::Structure') ) {
455 43210 100       74197 unshift @queue, $Element->finish if defined($Element->finish);
456 43210         44874 unshift @queue, @{$Element->{children}};
  43210         95111  
457 43210 50       65518 unshift @queue, $Element->start if defined($Element->start);
458             } else {
459 70959         65475 unshift @queue, @{$Element->{children}};
  70959         233649  
460             }
461             }
462 2224         3944 1;
463             };
464 2224 50       4669 if ( !$ok ) {
465             # Caught exception thrown from the wanted function
466 0         0 return undef;
467             }
468              
469 2224 100       24913 $rv or '';
470             }
471              
472             =pod
473              
474             =head2 find_any $class | \&wanted
475              
476             The C<find_any> method is a short-circuiting true/false method that behaves
477             like the normal C<find> method, but returns true as soon as it finds any
478             Elements that match the search condition.
479              
480             See the C<find> method for details on the format of the search condition.
481              
482             Returns true if any Elements that match the condition can be found, false if
483             not, or C<undef> if given an invalid condition, or an error occurs.
484              
485             =cut
486              
487             sub find_any {
488 2184     2184 1 626060 my $self = shift;
489 2184         6571 my $rv = $self->find_first(@_);
490 2184 100       13742 $rv ? 1 : $rv; # false or undef
491             }
492              
493             =pod
494              
495             =head2 remove_child $Element
496              
497             If passed a L<PPI::Element> object that is a direct child of the Node,
498             the C<remove_element> method will remove the C<Element> intact, along
499             with any of its children. As such, this method acts essentially as a
500             'cut' function.
501              
502             If successful, returns the removed element. Otherwise, returns C<undef>.
503              
504             =cut
505              
506             sub remove_child {
507 66     66 1 77 my $self = shift;
508 66 50       241 my $child = _INSTANCE(shift, 'PPI::Element') or return undef;
509              
510             # Find the position of the child
511 66         77 my $key = refaddr $child;
512 66         148 my $p = $self->__position($child);
513 66 100       100 return undef unless defined $p;
514              
515             # Splice it out, and remove the child's parent entry
516 65         69 splice( @{$self->{children}}, $p, 1 );
  65         131  
517 65         101 delete $_PARENT{$key};
518              
519 65         172 $child;
520             }
521              
522             =head2 replace_child $Element, $Replacement
523              
524             If successful, returns the replace element. Otherwise, returns C<undef>.
525              
526             =cut
527              
528             sub replace_child {
529 4     4 1 12 my $self = shift;
530              
531 4 50       24 my $child = _INSTANCE(shift, 'PPI::Element') or return undef;
532 4 50       52 my $replacement = _INSTANCE(shift, 'PPI::Element') or return undef;
533              
534 4         17 my $success = $self->__replace_child( $child, $replacement );
535              
536 4 100       11 return $success ? $replacement : undef;
537             }
538              
539             =pod
540              
541             =head2 prune $class | \&wanted
542              
543             The C<prune> method is used to strip L<PPI::Element> objects out of a code
544             tree. The argument is the same as for the C<find> method, either a class
545             name, or an anonymous subroutine which returns true/false. Any Element
546             that matches the class|wanted will be deleted from the code tree, along
547             with any of its children.
548              
549             The C<prune> method returns the number of C<Element> objects that matched
550             and were removed, B<non-recursively>. This might also be zero, so avoid a
551             simple true/false test on the return false of the C<prune> method. It
552             returns C<undef> on error, which you probably B<should> test for.
553              
554             =cut
555              
556             sub prune {
557 30     30 1 3236 my $self = shift;
558 30 50       71 my $wanted = $self->_wanted(shift) or return undef;
559              
560             # Use a depth-first queue search
561 30         51 my $pruned = 0;
562 30         72 my @queue = $self->children;
563 30         36 my $ok = eval {
564 30         101 while ( my $element = shift @queue ) {
565 269         1884 my $rv = &$wanted( $self, $element );
566 269 100       374 if ( $rv ) {
567             # Delete the child
568 62 50       133 $element->delete or return undef;
569 62         64 $pruned++;
570 62         127 next;
571             }
572              
573             # Support the undef == "don't descend"
574 207 50       336 next unless defined $rv;
575              
576 207 100       837 if ( _INSTANCE($element, 'PPI::Node') ) {
577             # Depth-first keeps the queue size down
578 43         95 unshift @queue, $element->children;
579             }
580             }
581 30         41 1;
582             };
583 30 50       51 if ( !$ok ) {
584             # Caught exception thrown from the wanted function
585 0         0 return undef;
586             }
587              
588 30         184 $pruned;
589             }
590              
591             # This method is likely to be very heavily used, so take
592             # it slowly and carefully.
593             ### NOTE: Renaming this function or changing either to self will probably
594             ### break File::Find::Rule::PPI
595             sub _wanted {
596 7428     7428   10657 my $either = shift;
597 7428 100       18910 my $it = defined($_[0]) ? shift : do {
598 1 50       4 Carp::carp('Undefined value passed as search condition') if $^W;
599 1         5 return undef;
600             };
601              
602             # Has the caller provided a wanted function directly
603 7427 100       32150 return $it if _CODELIKE($it);
604 3665 100       8339 if ( ref $it ) {
605             # No other ref types are supported
606 1 50       4 Carp::carp('Illegal non-CODE reference passed as search condition') if $^W;
607 1         4 return undef;
608             }
609              
610             # The first argument should be an Element class, possibly in shorthand
611 3664 100       12503 $it = "PPI::$it" unless substr($it, 0, 5) eq 'PPI::';
612 3664 100 66     12459 unless ( _CLASS($it) and $it->isa('PPI::Element') ) {
613             # We got something, but it isn't an element
614 1 50       20 Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
615 1         5 return undef;
616             }
617              
618             # Create the class part of the wanted function
619 3663         71756 my $wanted_class = "\n\treturn '' unless \$_[1]->isa('$it');";
620              
621             # Have we been given a second argument to check the content
622 3663         6077 my $wanted_content = '';
623 3663 50       8068 if ( defined $_[0] ) {
624 0         0 my $content = shift;
625 0 0       0 if ( ref $content eq 'Regexp' ) {
    0          
626 0         0 $content = "$content";
627             } elsif ( ref $content ) {
628             # No other ref types are supported
629 0 0       0 Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
630 0         0 return undef;
631             } else {
632 0         0 $content = quotemeta $content;
633             }
634              
635             # Complete the content part of the wanted function
636 0         0 $wanted_content .= "\n\treturn '' unless defined \$_[1]->{content};";
637 0         0 $wanted_content .= "\n\treturn '' unless \$_[1]->{content} =~ /$content/;";
638             }
639              
640             # Create the complete wanted function
641 3663         7401 my $code = "sub {"
642             . $wanted_class
643             . $wanted_content
644             . "\n\t1;"
645             . "\n}";
646              
647             # Compile the wanted function
648 3663         345577 $code = eval $code;
649 3663 50       20627 (ref $code eq 'CODE') ? $code : undef;
650             }
651              
652              
653              
654              
655              
656             ####################################################################
657             # PPI::Element overloaded methods
658              
659             sub tokens {
660 78977     78977 1 78154 map { $_->tokens } @{$_[0]->{children}};
  374313         549971  
  78977         145935  
661             }
662              
663             ### XS -> PPI/XS.xs:_PPI_Element__content 0.900+
664             sub content {
665 90730     90730 1 127896 join '', map { $_->content } @{$_[0]->{children}};
  429964         602522  
  90730         149193  
666             }
667              
668             # Clone as normal, but then go down and relink all the _PARENT entries
669             sub clone {
670 6     6 1 1114 my $self = shift;
671 6         32 my $clone = $self->SUPER::clone;
672 6         31 $clone->__link_children;
673 6         23 $clone;
674             }
675              
676             sub location {
677 8228     8228 1 20199 my $self = shift;
678 8228 100       24499 my $first = $self->{children}->[0] or return undef;
679 8225         13089 $first->location;
680             }
681              
682              
683              
684              
685              
686             #####################################################################
687             # Internal Methods
688              
689             sub DESTROY {
690 98459     98459   10158135 local $_;
691 98459 100       158565 if ( $_[0]->{children} ) {
692 16826         30991 my @queue = $_[0];
693 16826         42703 while ( defined($_ = shift @queue) ) {
694 418891 100       614021 unshift @queue, @{delete $_->{children}} if $_->{children};
  98439         181514  
695              
696             # Remove all internal/private weird crosslinking so that
697             # the cascading DESTROY calls will get called properly.
698 418891         787478 %$_ = ();
699             }
700             }
701              
702 98459         171148 $_[0]->SUPER::DESTROY;
703             }
704              
705             sub __position {
706 1220203     1220203   1309006 my ( $self, $child ) = @_;
707 1220203         1103851 my $key = refaddr $child;
708              
709             return undef unless #
710 1220203 50       1575017 my $elements = $self->{children};
711              
712 1220203 100       1847746 if (defined (my $position = $_POSITION_CACHE{$key})) {
713 1168701         1151173 my $maybe_child = $elements->[$position];
714 1168701 100 100     2979868 return $position if defined $maybe_child and refaddr $maybe_child == $key;
715             }
716              
717 51538         73827 delete $_POSITION_CACHE{$key};
718              
719 51538         60625 $_POSITION_CACHE{refaddr $elements->[$_]} = $_ for 0 .. $#{$elements};
  51538         535863  
720              
721 51538         103703 return $_POSITION_CACHE{$key};
722             }
723              
724             # Insert one or more elements before a child
725             sub __insert_before_child {
726 2     2   5 my ( $self, $child, @insertions ) = @_;
727 2         4 my $key = refaddr $child;
728 2         5 my $p = $self->__position($child);
729 2         4 foreach ( @insertions ) {
730             Scalar::Util::weaken(
731 2         8 $_PARENT{refaddr $_} = $self
732             );
733             }
734 2         2 splice( @{$self->{children}}, $p, 0, @insertions );
  2         6  
735 2         6 1;
736             }
737              
738             # Insert one or more elements after a child
739             sub __insert_after_child {
740 2     2   4 my ( $self, $child, @insertions ) = @_;
741 2         3 my $key = refaddr $child;
742 2         9 my $p = $self->__position($child);
743 2         4 foreach ( @insertions ) {
744             Scalar::Util::weaken(
745 2         6 $_PARENT{refaddr $_} = $self
746             );
747             }
748 2         2 splice( @{$self->{children}}, $p + 1, 0, @insertions );
  2         7  
749 2         5 1;
750             }
751              
752             # Replace a child
753             sub __replace_child {
754 4     4   8 my ( $self, $old_child, @replacements ) = @_;
755 4         7 my $old_child_addr = refaddr $old_child;
756              
757             # Cache parent of new children
758 4         10 my $old_child_index = $self->__position($old_child);
759              
760 4 100       8 return undef if !defined $old_child_index;
761              
762 3         6 foreach ( @replacements ) {
763             Scalar::Util::weaken(
764 3         9 $_PARENT{refaddr $_} = $self
765             );
766             }
767              
768             # Replace old child with new children
769 3         4 splice( @{$self->{children}}, $old_child_index, 1, @replacements );
  3         8  
770              
771             # Uncache parent of old child
772 3         5 delete $_PARENT{$old_child_addr};
773 3         6 1;
774             }
775              
776             # Create PARENT links for an entire tree.
777             # Used when cloning or thawing.
778             sub __link_children {
779 12     12   18 my $self = shift;
780              
781             # Relink all our children ( depth first )
782 12         24 my @queue = ( $self );
783 12         52 while ( my $Node = shift @queue ) {
784             # Link our immediate children
785 33         34 foreach my $Element ( @{$Node->{children}} ) {
  33         54  
786             Scalar::Util::weaken(
787 117         188 $_PARENT{refaddr($Element)} = $Node
788             );
789 117 100       292 unshift @queue, $Element if $Element->isa('PPI::Node');
790             }
791              
792             # If it's a structure, relink the open/close braces
793 33 100       132 next unless $Node->isa('PPI::Structure');
794             Scalar::Util::weaken(
795 4 50       13 $_PARENT{refaddr($Node->start)} = $Node
796             ) if $Node->start;
797             Scalar::Util::weaken(
798 4 50       17 $_PARENT{refaddr($Node->finish)} = $Node
799             ) if $Node->finish;
800             }
801              
802 12         49 1;
803             }
804              
805             1;
806              
807             =pod
808              
809             =head1 TO DO
810              
811             - Move as much as possible to L<PPI::XS>
812              
813             =head1 SUPPORT
814              
815             See the L<support section|PPI/SUPPORT> in the main module.
816              
817             =head1 AUTHOR
818              
819             Adam Kennedy E<lt>adamk@cpan.orgE<gt>
820              
821             =head1 COPYRIGHT
822              
823             Copyright 2001 - 2011 Adam Kennedy.
824              
825             This program is free software; you can redistribute
826             it and/or modify it under the same terms as Perl itself.
827              
828             The full text of the license can be found in the
829             LICENSE file included with this module.
830              
831             =cut