package Deconstifier; use warnings; use strict; use parent 'PPI::Transform'; =head1 DESCRIPTION L implementation that modifies a subset of L such that they are no longer inlined. The subset of C definitions that are currently supported is: sub FOO () { 42; } sub BAR () { "string"; } sub QUZ () { undef; } where the final semicolon is optional. =cut sub document { ( my $self = shift )->isa(__PACKAGE__) or return undef; ( my $doc = shift )->isa('PPI::Document') or return undef; my $subs = $doc->find(sub { if ( $_[1]->isa('PPI::Statement::Sub') && defined($_[1]->prototype) && $_[1]->prototype eq "" ) { my $bl = $_[1]->block; if ( $bl && $bl->schildren==1 && $bl->schild(0)->isa('PPI::Statement') ) { my $st = $bl->schild(0); if ( $st->schildren==1 || $st->schildren==2 && $st->schild(1)->isa('PPI::Token::Structure') && $st->schild(1)->content eq ';' ) { my $ch = $st->schild(0); if ( $ch->isa('PPI::Token::Number') || $ch->isa('PPI::Token::Quote') || $ch->isa('PPI::Token::Word') && $ch->literal eq 'undef' ) { return 1; } } } } return 0; }); return undef unless defined $subs; return 0 unless $subs; for my $s (@$subs) { #use PPI::Dumper; PPI::Dumper->new($s, whitespace=>0, comments=>0)->print; # This first one only seems to work on Perl 5.8+, the second down to 5.6 and maybe/likely earlier (untested). # NOTE: This isn't really the right way to use PPI::Token::Word, but since it's the only modification we're making it works fine. #$s->block->schild(0)->schild(0)->insert_before(PPI::Token::Word->new('return ')); $s->block->schild(0)->schild(0)->insert_after(PPI::Token::Word->new(' if $]')); } return 0+@$subs; } 1;