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 class provides an abstract base class for the Element
41             classes that are able to contain other elements L,
42             L, and L.
43              
44             As well as those listed below, all of the methods that apply to
45             L objects also apply to C objects.
46              
47             =head1 METHODS
48              
49             =cut
50              
51 67     67   498 use strict;
  67         136  
  67         6706  
52 67     67   446 use Carp ();
  67         135  
  67         4926  
53 67     67   2568 use Scalar::Util qw{refaddr};
  67         172  
  67         10049  
54 67     67   11870 use Params::Util qw{_INSTANCE _CLASS _CODELIKE _NUMBER};
  67         2298  
  67         6734  
55 67     67   4743 use PPI::Element ();
  67         5673  
  67         8508  
56 67     67   50246 use PPI::Singletons '%_PARENT', '%_POSITION_CACHE';
  67         255  
  67         234899  
57              
58             our $VERSION = '1.28401'; # TRIAL
59              
60             our @ISA = "PPI::Element";
61              
62              
63              
64              
65              
66             #####################################################################
67             # The basic constructor
68              
69             sub new {
70 16800   33 16800 0 92205 my $class = ref $_[0] || $_[0];
71 16800         82358 bless { children => [] }, $class;
72             }
73              
74              
75              
76              
77              
78             #####################################################################
79             # PDOM Methods
80              
81             =pod
82              
83             =head2 scope
84              
85             The C 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 method adds a L object to the end of a
98             C. 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 was added. Returns C if the
102             Element was already within another Node, or the method is not passed
103             a L object.
104              
105             =cut
106              
107             sub add_element {
108 1     1 1 12 my $self = shift;
109              
110             # Check the element
111 1 50       12 my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
112 1 50       5 $_PARENT{refaddr $Element} and return undef;
113              
114             # Add the argument to the elements
115 1         2 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 method accesses all child elements B within
137             the C object. Note that in the base of the L
138             classes, this C include the brace tokens at either end of the
139             structure.
140              
141             Returns a list of zero or more L objects.
142              
143             Alternatively, if called in the scalar context, the C method
144             returns a count of the number of elements.
145              
146             =cut
147              
148             sub elements {
149 2 50   2 1 735 if ( wantarray ) {
150 2         3 return @{$_[0]->{children}};
  2         10  
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 method accesses the first element structurally within
161             the C object. As for the C method, this does include
162             the brace tokens for L objects.
163              
164             Returns a L object, or C if for some reason the
165             C 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 33071 $_[0]->{children}->[0];
172             }
173              
174             =pod
175              
176             =head2 last_element
177              
178             The C method accesses the last element structurally within
179             the C object. As for the C method, this does include
180             the brace tokens for L objects.
181              
182             Returns a L object, or C if for some reason the
183             C 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 98 $_[0]->{children}->[-1];
190             }
191              
192             =pod
193              
194             =head2 children
195              
196             The C method accesses all child elements lexically within the
197             C object. Note that in the case of the L
198             classes, this does B include the brace tokens at either end of the
199             structure.
200              
201             Returns a list of zero of more L objects.
202              
203             Alternatively, if called in the scalar context, the C 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 2179 50   2179 1 209268 wantarray ? @{$_[0]->{children}} : scalar @{$_[0]->{children}};
  2179         13279  
  0         0  
211             }
212              
213             =pod
214              
215             =head2 schildren
216              
217             The C method is really just a convenience, the significant-only
218             variation of the normal C 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 61058 100   61058 1 13795392 return grep { $_->significant } @{$_[0]->{children}} if wantarray;
  122667         312767  
  30396         91934  
227 30662         56607 my $count = 0;
228 30662         46825 foreach ( @{$_[0]->{children}} ) {
  30662         93474  
229 107469 100       316881 $count++ if $_->significant;
230             }
231 30662         129284 return $count;
232             }
233              
234             =pod
235              
236             =head2 child $index
237              
238             The C method accesses a child L object by its
239             position within the Node.
240              
241             Returns a L object, or C if there is no child
242             element at that node.
243              
244             =cut
245              
246             sub child {
247 860     860 1 177451 my ( $self, $index ) = @_;
248 860 100       4629 PPI::Exception->throw( "method child() needs an index" )
249             if not defined _NUMBER $index;
250 858         6448 $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 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 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 160581     160581 1 11402539 my $self = shift;
272 160581         274594 my $idx = 0 + shift;
273 160581         314439 my $el = $self->{children};
274 160581 100       367946 if ( $idx < 0 ) {
275 24928         42889 my $cursor = 0;
276 24928         73451 while ( exists $el->[--$cursor] ) {
277 26318 100 100     187787 return $el->[$cursor] if $el->[$cursor]->significant and ++$idx >= 0;
278             }
279             } else {
280 135653         203043 my $cursor = -1;
281 135653         363889 while ( exists $el->[++$cursor] ) {
282 187303 100 100     1409187 return $el->[$cursor] if $el->[$cursor]->significant and --$idx < 0;
283             }
284             }
285 3368         16453 undef;
286             }
287              
288             =pod
289              
290             =head2 contains $Element
291              
292             The C method is used to determine if another L
293             object is logically "within" a C. For the special case of the
294             brace tokens at either side of a L object, they are
295             generally considered "within" a L object, even if they are
296             not actually in the elements for the L.
297              
298             Returns true if the L is within us, false if not, or C
299             on error.
300              
301             =cut
302              
303             sub contains {
304 34     34 1 23337 my $self = shift;
305 34 100       2019 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         116 while ( $Element = $Element->parent ) {
310 79 100       243 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 method is used to search within a code tree for
321             L 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/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
345             you are searching in and the current L 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 indicates no-match and no-descend.
351              
352             In the last case, the tree walker will skip over anything below the
353             C-returning element and move on to the next element at the same
354             level.
355              
356             To halt the entire search and return C immediately, a condition
357             function should throw an exception (i.e. C).
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 method returns a reference to an array of L
363             objects that match the condition, false (but defined) if no Elements match
364             the condition, or C 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 8185493 my $self = shift;
373 5174 100       29385 my $wanted = $self->_wanted(shift) or return undef;
374              
375             # Use a queue based search, rather than a recursive one
376 5171         11319 my @found;
377 5171         9218 my @queue = @{$self->{children}};
  5171         23672  
378 5171         11216 my $ok = eval {
379 5171         16083 while ( @queue ) {
380 357172         515817 my $Element = shift @queue;
381 357172         2521750 my $rv = &$wanted( $self, $Element );
382 357172 100       1320443 push @found, $Element if $rv;
383              
384             # Support "don't descend on undef return"
385 357172 50       650653 next unless defined $rv;
386              
387             # Skip if the Element doesn't have any children
388 357172 100       1234628 next unless $Element->isa('PPI::Node');
389              
390             # Depth-first keeps the queue size down and provides a
391             # better logical order.
392 60504 100       178586 if ( $Element->isa('PPI::Structure') ) {
393 22238 100       72133 unshift @queue, $Element->finish if $Element->finish;
394 22238         35900 unshift @queue, @{$Element->{children}};
  22238         66236  
395 22238 50       53900 unshift @queue, $Element->start if $Element->start;
396             } else {
397 38266         53983 unshift @queue, @{$Element->{children}};
  38266         164058  
398             }
399             }
400 5171         14637 1;
401             };
402 5171 50       15489 if ( !$ok ) {
403             # Caught exception thrown from the wanted function
404 0         0 return undef;
405             }
406              
407 5171 100       49727 @found ? \@found : '';
408             }
409              
410             =pod
411              
412             =head2 find_first $class | \&wanted
413              
414             If the normal C method is like a grep, then C is
415             equivalent to the L C 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 method for details on the format of the search condition.
422              
423             Returns the first L object that matches the condition, false
424             if nothing matches the condition, or C if given an invalid condition,
425             or an error occurs.
426              
427             =cut
428              
429             sub find_first {
430 2224     2224 1 68356 my $self = shift;
431 2224 50       8347 my $wanted = $self->_wanted(shift) or return undef;
432              
433             # Use the same queue-based search as for ->find
434 2224         4353 my @queue = @{$self->{children}};
  2224         23793  
435 2224         4392 my $rv;
436 2224         4318 my $ok = eval {
437             # The defined() here prevents a ton of calls to PPI::Util::TRUE
438 2224         7409 while ( @queue ) {
439 771948         1184936 my $Element = shift @queue;
440 771948         14916022 my $element_rv = $wanted->( $self, $Element );
441 771948 100       1682618 if ( $element_rv ) {
442 39         76 $rv = $Element;
443 39         92 last;
444             }
445              
446             # Support "don't descend on undef return"
447 771909 100       1428273 next if !defined $element_rv;
448              
449             # Skip if the Element doesn't have any children
450 747306 100       2571102 next if !$Element->isa('PPI::Node');
451              
452             # Depth-first keeps the queue size down and provides a
453             # better logical order.
454 114549 100       354437 if ( $Element->isa('PPI::Structure') ) {
455 43372 100       178683 unshift @queue, $Element->finish if defined($Element->finish);
456 43372         77282 unshift @queue, @{$Element->{children}};
  43372         149611  
457 43372 50       104349 unshift @queue, $Element->start if defined($Element->start);
458             } else {
459 71177         111564 unshift @queue, @{$Element->{children}};
  71177         363230  
460             }
461             }
462 2224         5547 1;
463             };
464 2224 50       6332 if ( !$ok ) {
465             # Caught exception thrown from the wanted function
466 0         0 return undef;
467             }
468              
469 2224 100       31717 $rv or '';
470             }
471              
472             =pod
473              
474             =head2 find_any $class | \&wanted
475              
476             The C method is a short-circuiting true/false method that behaves
477             like the normal C method, but returns true as soon as it finds any
478             Elements that match the search condition.
479              
480             See the C 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 if given an invalid condition, or an error occurs.
484              
485             =cut
486              
487             sub find_any {
488 2184     2184 1 944399 my $self = shift;
489 2184         9652 my $rv = $self->find_first(@_);
490 2184 100       19611 $rv ? 1 : $rv; # false or undef
491             }
492              
493             =pod
494              
495             =head2 remove_child $Element
496              
497             If passed a L object that is a direct child of the Node,
498             the C method will remove the C 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.
503              
504             =cut
505              
506             sub remove_child {
507 66     66 1 123 my $self = shift;
508 66 50       1082 my $child = _INSTANCE(shift, 'PPI::Element') or return undef;
509              
510             # Find the position of the child
511 66         102 my $key = refaddr $child;
512 66         209 my $p = $self->__position($child);
513 66 100       141 return undef unless defined $p;
514              
515             # Splice it out, and remove the child's parent entry
516 65         130 splice( @{$self->{children}}, $p, 1 );
  65         146  
517 65         133 delete $_PARENT{$key};
518              
519 65         269 $child;
520             }
521              
522             =head2 replace_child $Element, $Replacement
523              
524             If successful, returns the replace element. Otherwise, returns C.
525              
526             =cut
527              
528             sub replace_child {
529 4     4 1 17 my $self = shift;
530              
531 4 50       29 my $child = _INSTANCE(shift, 'PPI::Element') or return undef;
532 4 50       53 my $replacement = _INSTANCE(shift, 'PPI::Element') or return undef;
533              
534 4         15 my $success = $self->__replace_child( $child, $replacement );
535              
536 4 100       18 return $success ? $replacement : undef;
537             }
538              
539             =pod
540              
541             =head2 prune $class | \&wanted
542              
543             The C method is used to strip L objects out of a code
544             tree. The argument is the same as for the C 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 method returns the number of C objects that matched
550             and were removed, B. This might also be zero, so avoid a
551             simple true/false test on the return false of the C method. It
552             returns C on error, which you probably B test for.
553              
554             =cut
555              
556             sub prune {
557 30     30 1 4767 my $self = shift;
558 30 50       95 my $wanted = $self->_wanted(shift) or return undef;
559              
560             # Use a depth-first queue search
561 30         52 my $pruned = 0;
562 30         103 my @queue = $self->children;
563 30         52 my $ok = eval {
564 30         124 while ( my $element = shift @queue ) {
565 269         2583 my $rv = &$wanted( $self, $element );
566 269 100       489 if ( $rv ) {
567             # Delete the child
568 62 50       219 $element->delete or return undef;
569 62         78 $pruned++;
570 62         170 next;
571             }
572              
573             # Support the undef == "don't descend"
574 207 50       349 next unless defined $rv;
575              
576 207 100       1195 if ( _INSTANCE($element, 'PPI::Node') ) {
577             # Depth-first keeps the queue size down
578 43         114 unshift @queue, $element->children;
579             }
580             }
581 30         79 1;
582             };
583 30 50       74 if ( !$ok ) {
584             # Caught exception thrown from the wanted function
585 0         0 return undef;
586             }
587              
588 30         255 $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   16078 my $either = shift;
597 7428 100       28723 my $it = defined($_[0]) ? shift : do {
598 1 50       5 Carp::carp('Undefined value passed as search condition') if $^W;
599 1         7 return undef;
600             };
601              
602             # Has the caller provided a wanted function directly
603 7427 100       48145 return $it if _CODELIKE($it);
604 3665 100       13964 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         5 return undef;
608             }
609              
610             # The first argument should be an Element class, possibly in shorthand
611 3664 100       17705 $it = "PPI::$it" unless substr($it, 0, 5) eq 'PPI::';
612 3664 100 66     19651 unless ( _CLASS($it) and $it->isa('PPI::Element') ) {
613             # We got something, but it isn't an element
614 1 50       38 Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
615 1         10 return undef;
616             }
617              
618             # Create the class part of the wanted function
619 3663         115484 my $wanted_class = "\n\treturn '' unless \$_[1]->isa('$it');";
620              
621             # Have we been given a second argument to check the content
622 3663         10486 my $wanted_content = '';
623 3663 50       11400 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         11132 my $code = "sub {"
642             . $wanted_class
643             . $wanted_content
644             . "\n\t1;"
645             . "\n}";
646              
647             # Compile the wanted function
648 3663         468080 $code = eval $code;
649 3663 50       34061 (ref $code eq 'CODE') ? $code : undef;
650             }
651              
652              
653              
654              
655              
656             ####################################################################
657             # PPI::Element overloaded methods
658              
659             sub tokens {
660 79257     79257 1 117111 map { $_->tokens } @{$_[0]->{children}};
  376253         846420  
  79257         216851  
661             }
662              
663             ### XS -> PPI/XS.xs:_PPI_Element__content 0.900+
664             sub content {
665 90806     90806 1 203626 join '', map { $_->content } @{$_[0]->{children}};
  430489         925486  
  90806         230667  
666             }
667              
668             # Clone as normal, but then go down and relink all the _PARENT entries
669             sub clone {
670 6     6 1 1085 my $self = shift;
671 6         35 my $clone = $self->SUPER::clone;
672 6         32 $clone->__link_children;
673 6         25 $clone;
674             }
675              
676             sub location {
677 8264     8264 1 32375 my $self = shift;
678 8264 100       39702 my $first = $self->{children}->[0] or return undef;
679 8261         21834 $first->location;
680             }
681              
682              
683              
684              
685              
686             #####################################################################
687             # Internal Methods
688              
689             sub DESTROY {
690 98675     98675   15686786 local $_;
691 98675 100       253392 if ( $_[0]->{children} ) {
692 16825         60370 my @queue = $_[0];
693 16825         70172 while ( defined($_ = shift @queue) ) {
694 420420 100       931141 unshift @queue, @{delete $_->{children}} if $_->{children};
  98655         270303  
695              
696             # Remove all internal/private weird crosslinking so that
697             # the cascading DESTROY calls will get called properly.
698 420420         1249375 %$_ = ();
699             }
700             }
701              
702 98675         287484 $_[0]->SUPER::DESTROY;
703             }
704              
705             sub __position {
706 4179     4179   7232 my ( $self, $child ) = @_;
707 4179         5787 my $key = refaddr $child;
708              
709             return undef unless #
710 4179 50       8841 my $elements = $self->{children};
711              
712 4179 100       10276 if (defined (my $position = $_POSITION_CACHE{$key})) {
713 2346         3564 my $maybe_child = $elements->[$position];
714 2346 100 100     15591 return $position if defined $maybe_child and refaddr $maybe_child == $key;
715             }
716              
717 1869         2788 delete $_POSITION_CACHE{$key};
718              
719 1869         2764 $_POSITION_CACHE{refaddr $elements->[$_]} = $_ for 0 .. $#{$elements};
  1869         25250  
720              
721 1869         5060 return $_POSITION_CACHE{$key};
722             }
723              
724             # Insert one or more elements before a child
725             sub __insert_before_child {
726 2     2   7 my ( $self, $child, @insertions ) = @_;
727 2         5 my $key = refaddr $child;
728 2         9 my $p = $self->__position($child);
729 2         6 foreach ( @insertions ) {
730             Scalar::Util::weaken(
731 2         8 $_PARENT{refaddr $_} = $self
732             );
733             }
734 2         4 splice( @{$self->{children}}, $p, 0, @insertions );
  2         8  
735 2         7 1;
736             }
737              
738             # Insert one or more elements after a child
739             sub __insert_after_child {
740 2     2   7 my ( $self, $child, @insertions ) = @_;
741 2         4 my $key = refaddr $child;
742 2         10 my $p = $self->__position($child);
743 2         6 foreach ( @insertions ) {
744             Scalar::Util::weaken(
745 2         6 $_PARENT{refaddr $_} = $self
746             );
747             }
748 2         5 splice( @{$self->{children}}, $p + 1, 0, @insertions );
  2         10  
749 2         5 1;
750             }
751              
752             # Replace a child
753             sub __replace_child {
754 4     4   9 my ( $self, $old_child, @replacements ) = @_;
755 4         7 my $old_child_addr = refaddr $old_child;
756              
757             # Cache parent of new children
758 4         14 my $old_child_index = $self->__position($old_child);
759              
760 4 100       9 return undef if !defined $old_child_index;
761              
762 3         4 foreach ( @replacements ) {
763             Scalar::Util::weaken(
764 3         11 $_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         9  
770              
771             # Uncache parent of old child
772 3         4 delete $_PARENT{$old_child_addr};
773 3         5 1;
774             }
775              
776             # Create PARENT links for an entire tree.
777             # Used when cloning or thawing.
778             sub __link_children {
779 12     12   27 my $self = shift;
780              
781             # Relink all our children ( depth first )
782 12         33 my @queue = ( $self );
783 12         61 while ( my $Node = shift @queue ) {
784             # Link our immediate children
785 33         51 foreach my $Element ( @{$Node->{children}} ) {
  33         70  
786             Scalar::Util::weaken(
787 117         2078 $_PARENT{refaddr($Element)} = $Node
788             );
789 117 100       412 unshift @queue, $Element if $Element->isa('PPI::Node');
790             }
791              
792             # If it's a structure, relink the open/close braces
793 33 100       186 next unless $Node->isa('PPI::Structure');
794             Scalar::Util::weaken(
795 4 50       18 $_PARENT{refaddr($Node->start)} = $Node
796             ) if $Node->start;
797             Scalar::Util::weaken(
798 4 50       18 $_PARENT{refaddr($Node->finish)} = $Node
799             ) if $Node->finish;
800             }
801              
802 12         83 1;
803             }
804              
805             1;
806              
807             =pod
808              
809             =head1 TO DO
810              
811             - Move as much as possible to L
812              
813             =head1 SUPPORT
814              
815             See the L in the main module.
816              
817             =head1 AUTHOR
818              
819             Adam Kennedy Eadamk@cpan.orgE
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