Re: CPAN modules for inspecting a Perl distribution?
by LanX (Saint) on Oct 12, 2018 at 20:31 UTC
|
| [reply] |
|
| [reply] |
|
I'm the author of Devel::Examine::Subs, so if you have any issues or questions, feel free to ask away here, or email me using my CPAN page's address.
| [reply] |
|
|
|
Re: CPAN modules for inspecting a Perl distribution?
by pryrt (Abbot) on Oct 12, 2018 at 20:25 UTC
|
I think this will do approximately what you want (from a linuxy command line): find . -type f -iname '*.pm' -exec egrep -iH '^\s*sub' {} \;. Not 100% effective, but it would be a pretty good first-level approximation (assuming it's not an XS distro) | [reply] [d/l] |
|
Thanks. But I'm looking for something that would provide some kind of standard report of the distribution's contents. Something that could help point me at a glance to what the major modules were, which modules had the most functions/lines, etc. instead of just peeking inside random files for 10 min.
| [reply] |
Re: CPAN modules for inspecting a Perl distribution?
by Laurent_R (Canon) on Oct 13, 2018 at 22:00 UTC
|
Hmm, not sure this is going to be useful for you.
Very recently, I had to generate a dynamic tree of program calls. This is a proprietary language in which a program may call a subroutine (well, it's called a procedure in that language) or may call an external program written in the same language. What I needed was a full tree of all programs called by a certain subroutine of the main invoicing program, including programs called by the called programs.
All those programs are not Perl programs, but I used Perl to parse the main invoicing program and to recursively parse programs called by the main program.
Basically, my program first reads statically the program passed as a parameter and stores in a hash of arrays all the procedures of the program, with the name of the procedure as a key, and an anonymous array of the interesting code lines as a value. Once this is done, I'm doing a dynamic analysis of internal subs and and external programs called, so we have two levels of recursion here: one at the internal procedure call level (calling the procedure analysis sub) and one at the program level (calling the external program analysis sub).
I'm basically calling my program with a program name and a specific procedure name as argument, then reading the content of the procedure, and calling recursively either the procedure analysis sub or the external analysis sub.
I ended up with a 300+ line program generating a complete tree of function and external program calls. And that program generates a complete tree of procedure and external program calls for the input program and procedure.
I can't publish my program, but I could provide a pseudo-code example if you wish.
HTH.
| [reply] |
Re: CPAN modules for inspecting a Perl distribution?
by Anonymous Monk on Oct 12, 2018 at 20:55 UTC
|
Module::Metadata can find some metadata about modules in a similar manner to PAUSE, and package_versions_from_directory can be used to find what it provides in a similar way. Finding functions and methods on the other hand depends on what you want to look for: 1. functions that have been defined at runtime, which would be discovered by loading the module and searching its stash for CODE entries which you could use Package::Stash for, or 2. functions that are visibly defined in the file, found by statically parsing the code using something like PPI. | [reply] |
Re: CPAN modules for inspecting a Perl distribution?
by nysus (Parson) on Oct 13, 2018 at 19:08 UTC
|
Here's a script I hacked together that gives me a basic report on a distribution. It provides a simple listing of each module, sorted by modules with most lines of code along with the number of subroutines in the module, followed by a summary report.
#! /usr/bin/env perl
use strict;
use warnings;
use Devel::Examine::Subs;
use SourceCode::LineCounter::Perl;
use Data::Dumper qw(Dumper);
my $filename = '/path/to/module/directory';
my $des = Devel::Examine::Subs->new( file => $filename );
my $files = $des->all( );
my %subs = ();
my $subroutine_total = 0;
my $counter = SourceCode::LineCounter::Perl->new;
$counter->accumulate(1);
for my $file (sort keys %$files) {
my $name = $file =~ s/$filename//r;
my $old_count = $counter->code;
$counter->count( $file );
my $lines_of_code = $counter->code - $old_count;
my $number_of_subs = scalar @{$files->{$file}};
$subroutine_total += $number_of_subs;
$subs{$name}{sub_names} = join("\n", @{$files->{$file}});
$subs{$name}{lines_of_code} = $lines_of_code;
$subs{$name}{subroutines} = $number_of_subs;
}
print "File listing:\n================\n";
for my $file (sort { $subs{$b}{lines_of_code} <=> $subs{$a}{lines_of_c
+ode} } sort keys %subs) {
print $file . "\n";
print "Number of subroutines: " . $subs{$file}{subroutines};
print "\n";
print "Lines of code: " . $subs{$file}{lines_of_code}. "\n";
# print $subs{$file}{sub_names};
print "\n\n";
}
print "\nTotal # files: " . scalar (keys %subs);
print "\nTotal # subroutines: " . $subroutine_total;
print "\nTotal # lines: " . $counter->total;
print "\nTotal # lines of code: " . $counter->code;
| [reply] [d/l] |
|
I like your approach, but it gave me a lot of doubles and it took ages. Here's my stab at it
Thanks for the motivation :)
Enjoy, Have FUN! H.Merijn
| [reply] [d/l] |
|
My script:
real 0m12.515s
user 0m11.919s
sys 0m0.505s
Your script:
real 0m15.987s
user 0m15.229s
sys 0m0.660s
This was done on the Rex v 1.6.0 module, which is pretty hefty. When you say "doubles," do you mean that some files were reported twice?
| [reply] [d/l] |
|
|
|
|
|
delete $SIG{__WARN__};
delete $SIG{__DIE__};
| [reply] [d/l] |
|