Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked

PPI replacing/updating a stub

by clueless newbie (Deacon)
on Sep 24, 2017 at 15:41 UTC ( #1199996=perlquestion: print w/replies, xml ) Need Help??

clueless newbie has asked for the wisdom of the Perl Monks concerning the following question:

How to replace a (sub's) stub using PPI?

I'm playing with PPI and the problem of fleshing out a stub has me baffled. The following snippet illustrates my problem.

#!/usr/bin/env perl use if (-d 'C:/Users/clueless_newbie'),lib=>'C:/Users/clueless_newbie/ +GOOGLE~1/code/lib'; use if (-d 'C:/Users/clueless_newbie'),lib=>'C:/Users/clueless_newbie/ +code/Perl-5/devlib'; # $ENV{DBG} -> compile time; $ENV{DEBUG} -> run time. use if ($ENV{DBG} || $ENV{DEBUG}),"Devel::UnComment","#[=]#","Keep"; use Data::Dumper; use PPI; use PPI::Dumper; use strict; use warnings; use 5.10.0; { # INTERNALS }; # INTERNALS my $raw=<<'__RAW__'; package FeeFi; sub Fee { print "Fee\n"; } sub Fi { print "Fi\n"; } -1; __RAW__ my %sub_h; { # Save the subs; replacing them with placeholders # Create the PPI document my $document=PPI::Document->new(\$raw) or die "oops!"; $document->save('before'); for my $sub (@{$document->find('PPI::Statement::Sub') || []}) { unless ($sub->forward) { #say $sub->name; # save the sub and its content $sub_h{$sub->name}{content}=$sub->content; # Replace the sub's block as a stub by removing its childr +en my @elements=$sub->block->children; for (my $i=0; $i < @elements; $i++) { $elements[$i]->remove; }; }; }; # Save the stubbed out "main/package" under the key ''; $sub_h{''}{content}=$document->content; }; #=# DEBUG [ sub_h=>\%sub_h ]; # Completing the round trip { # Create the stubbed out main my $document=PPI::Document->new(\$sub_h{''}{content}) or die "oops creating ''!"; #=# DEBUG '',PPI::Dumper->new($document,whitespace=>0)->string; # Find and flesh out the stubs for my $stub (@{$document->find('PPI::Statement::Sub') || []}) { unless ($stub->forward) { my $name=$stub->name; #=# TRACE $name; # Flesh out this stub my $sub=PPI::Document->new(\$sub_h{$name}{content})->find_ +first('PPI::Statement::Sub'); #=# TRACE '',PPI::Dumper->new($sub,whitespace=>0)->string; # So ow do I flesh out the stub from $sub???? $stub->insert_after($sub) # <=== Doesn't do it! or warn "Can't insert_after!"; #=# DEBUG '',PPI::Dumper->new($document,whitespace=>0)->st +ring; }; }; #=# DEBUG '',PPI::Dumper->new($document,whitespace=>0)->string; $document->save('after'); # <=== "after" should be prog +rammatically equal to "before" }; exit;

Replies are listed 'Best First'.
Re: PPI replacing/updating a stub
by haukex (Chancellor) on Sep 24, 2017 at 18:05 UTC

    What's going on behind the scenes is actually pretty interesting. So when you say PPI::Document->new(\$sub_h{$name}{content})->find_first('PPI::Statement::Sub'), you're creating a new document, however, you're not keeping a reference to that document, so it is immediately DESTROYed - which clobbers every element of that document - including the sub returned from find_first!

    So to fix that, split that statement into two, saving the document in a variable so that it is not immediately destroyed. But the code still doesn't work, because that document is still getting destroyed at the end of the loop body, removing the elements before you get to save. So to fix that, you need to disassociate the sub element from its document via remove.

    There's one more minor issue, which is that you need to remove the stub, since you're replacing it with the stored one. So putting all that together gets you this, which works (file after should be identical to before):

      Thank you very much!

Re: PPI replacing/updating a stub
by holli (Monsignor) on Sep 24, 2017 at 21:15 UTC
    I just want to mention, when it's about textually transforming Perl source code, there is also PPR. That module provides one giant regex that matches all of Perl (or pieces of it). Sounds crazy, I know. But hey, Damian wrote it so go figure.


    You can lead your users to water, but alas, you cannot drown them.
Re: PPI replacing/updating a stub
by Anonymous Monk on Sep 24, 2017 at 16:41 UTC
    $raw is the sample input yes? whats the expected output?
      Were I able to get it working the output would be programmatically identical to $raw.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1199996]
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2019-11-22 04:53 GMT
Find Nodes?
    Voting Booth?
    Strict and warnings: which comes first?

    Results (108 votes). Check out past polls.