What's the best way to discover all subroutines a Perl module has?
Asked Answered
A

3

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.

Aeroembolism answered 3/3, 2009 at 17:14 Comment(0)
E
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\::"}
}
Existent answered 3/3, 2009 at 17:29 Comment(6)
This will also list subroutines that the module imported from other modules.Mussorgsky
On second thought, it may also be important, depending on the application.Aeroembolism
True, but there is no easy way to get around that, I think. namespace::clean is the answer to such problems ;-)Existent
You'd want exists instead of defined to pick up autoloaded subs.Sly
Second \&.. in 2nd list_module should be same as first. Also, in_package is not filtering imported constants for me on 5.10...will researchSly
5.10 uses the new constsubs, so it's logical they aren't filtered out. Not sure how to filter those out though...Existent
S
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...

Shulamite answered 3/3, 2009 at 19:27 Comment(2)
For me, this answer was better than Leon's, since I needed all object methods (everything in the inheritance chain).Tuition
Using Class::Inspector from inside perl debugger is extremely useful, thanks.Cupbearer
P
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)...

Paronychia answered 3/3, 2009 at 18:8 Comment(7)
Looks interesting, but fairly new. I'd be hesitant to use it in a production environment.Aeroembolism
What reasons could you possibly have to get a list of methods in a production environment?Mussorgsky
I'm interested in prototyping out a Test::Class like tool. Developing prototypes off other untested code can lead to big headaches. :)Aeroembolism
Good point. I just hope you are not going to test on the production servers.Mussorgsky
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: use.perl.org/journal.pl?op=list&uid=2709Nevis
@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.Jackson
Not CPAN phobia, just a natural instinct to shy at "version 0.08". :)Aeroembolism

© 2022 - 2024 — McMap. All rights reserved.