in reply to How to get line ranges of subroutines from Perl source code

It’s a little clumsy (might be a better way?) but this PPI based version seems to do a decent job–

use PPI; my $doc = PPI::Document->new(shift || die "Give a doc!\n"); my $subs = $doc->find("PPI::Statement::Sub"); for my $sub ( @$subs ) { my $start = $sub->line_number; my $lines = $sub =~ y/\n//; my $end = $start + $lines; print "Found a subroutine starting at line ", $start, " and ending at line ", $end, $/; }

Replies are listed 'Best First'.
Re^2: How to get line ranges of subroutines from Perl source code
by rockyb (Scribe) on Apr 17, 2014 at 01:36 UTC

    Many thanks!

    I think this is pretty much what I need. I also need the fully qualified subroutine name e.g. main::foo or File::Basename::dirname, but that is easily added. To wit:

    #!/usr/bin/perl -w use PPI; use strict; use Cwd 'abs_path'; my $filename = shift || die "Give me a doc!"; my $doc = PPI::Document->new($filename); my $subs = $doc->find("PPI::Statement::Sub"); my $packages = $doc->find('PPI::Statement::Package'); my @pkg_info = (['main', 0]); if ($packages ne "") { for my $pkg ( @$packages ) { my $start = $pkg->line_number; my $pkg_name = $pkg->{children}[2]; push @pkg_info, [$pkg_name, $start]; } } sub enclosing_pkg($$) { my ($start, $end) = @_; my $pkg_name = 'main'; foreach my $pkg_info (@pkg_info) { if ($pkg_info->[1] > $start) { # fn start and end can't span a "package" statement. die "Bolixed package parsing" if $pkg_info->[1] < $end; last; } $pkg_name = $pkg_info->[0]; } $pkg_name; } print abs_path($filename), ":", $/; for my $fn ( @$subs ) { my $start = $fn->line_number; my $lines = $fn =~ y/\n//; my $end = $start + $lines; my $pkg_name = enclosing_pkg($start, $end); printf "\t%s::%s: %d-%d\n", $pkg_name, $fn->name, $start, $end; }

    The only remaining piece is getting a list of files that need to get loaded, but I think I can get that via %INC.

    Finally to the question of is this perfect, or is there's a better way? Possibly.

    But I'd like to start out with something that is pretty good as this is, and then improve or even rewrite as we understand better ways. In my experience, if you wait for the perfect solution, you'll never get anywhere.

Re^2: How to get line ranges of subroutines from Perl source code
by stevieb (Canon) on Jul 15, 2015 at 15:49 UTC

    Old thread, I know, but this is *EXACTLY* the baseline I've needed to find for a project I'm currently working on.

    If you add:

    my $name = $sub->name; print "Found $name starting at line "...

    One gets the actual name of the sub too.

    Thanks!

    -stevieb