24

What's the best way to programatically discover all of the subroutines a perl module has? This could be a module, a class (no @EXPORT), or anything in-between.

Edit: All of the methods below look like they will work. I'd probably use the Class::Sniff or Class::Inspector in production. However, Leon's answer is marked as 'accepted' since it answers the question as posed, even though no strict 'refs' has to be used. :-) Class::Sniff may be a good choice as it progresses; it looks like a lot of thought has gone into it.

Robert P
  • 15,707
  • 10
  • 68
  • 112

3 Answers3

23
sub list_module {
    my $module = shift;
    no strict 'refs';
    return grep { defined &{"$module\::$_"} } keys %{"$module\::"}
}

ETA: if you want to filter out imported subroutines, you can do this

use B qw/svref_2object/;

sub in_package {
    my ($coderef, $package) = @_;
    my $cv = svref_2object($coderef);
    return if not $cv->isa('B::CV') or $cv->GV->isa('B::SPECIAL');
    return $cv->GV->STASH->NAME eq $package;
}

sub list_module {
    my $module = shift;
    no strict 'refs';
    return grep { defined &{"$module\::$_"} and in_package(\&{*$_}, $module) } keys %{"$module\::"}
}
Leon Timmermans
  • 30,029
  • 2
  • 61
  • 110
12

Class::Inspector:

Class::Inspector allows you to get information about a loaded class. Most or all of this information can be found in other ways, but they aren't always very friendly, and usually involve a relatively high level of Perl wizardry, or strange and unusual looking code. Class::Inspector attempts to provide an easier, more friendly interface to this information...

gnat
  • 6,213
  • 108
  • 53
  • 73
jrockway
  • 42,082
  • 9
  • 61
  • 86
9

Have a look at this: Class::Sniff

The interface is rather ad-hoc at the moment and is likely to change. After creating a new instance, calling the report method is your best option. You can then visually examine it to look for potential problems:

my $sniff = Class::Sniff->new({class => 'Some::Class'});
print $sniff->report;

This module attempts to help programmers find 'code smells' in the object-oriented code. If it reports something, it does not mean that your code is wrong. It just means that you might want to look at your code a little bit more closely to see if you have any problems.

At the present time, we assume Perl's default left-most, depth-first search order. We may alter this in the future (and there's a work-around with the paths method. More on this later)...

gnat
  • 6,213
  • 108
  • 53
  • 73
nxadm
  • 2,079
  • 12
  • 17
  • Looks interesting, but fairly new. I'd be hesitant to use it in a production environment. – Robert P Mar 03 '09 at 18:36
  • 2
    What reasons could you possibly have to get a list of methods in a production environment? – innaM Mar 03 '09 at 18:45
  • 1
    I'm interested in prototyping out a Test::Class like tool. Developing prototypes off other untested code can lead to big headaches. :) – Robert P Mar 03 '09 at 18:54
  • Good point. I just hope you are not going to test on the production servers. – innaM Mar 03 '09 at 18:56
  • It's new, but Ovid has thought about this problem in great depth. It's not written lightly. See various journal posts related to Class::Sniff here: http://use.perl.org/journal.pl?op=list&uid=2709 – xdg Mar 03 '09 at 20:53
  • @RobertP You're ready to copy a snippet of code off a web page but balking at a module with documentation and tests? Face your CPAN-phobia. – Schwern Mar 05 '09 at 03:04
  • Not CPAN phobia, just a natural instinct to shy at "version 0.08". :) – Robert P Apr 09 '09 at 19:17