有几种方法可以列出包中的所有潜艇:
sub list_methods {
my $package = shift;
no strict 'refs';
return grep { defined &{"$package\::$_"} } keys %{"$package\::"}
}
但是,如果包“使用”其他包,例如'File :: Basename',那么也会列出像'fileparse'这样的子包。 我试图'需要'包而不是'使用'它们,问题可以解决。另一方面,如果我'需要'包,我必须指定潜艇的完整路径。
你有什么想法吗?
答案 0 :(得分:3)
use B qw( svref_2object );
sub list_nonimported_subs {
my ($pkg_name) = @_;
my $pkg = do { no strict 'refs'; *{ $pkg_name . '::' } };
my @nonimported_subs;
for my $name (keys %$pkg) {
my $glob = $pkg->{$name};
my $code = *$glob{CODE}
or next;
my $cv = svref_2object($code);
my $orig_pkg_name = $cv->GV->STASH->NAME;
next if $orig_pkg_name ne $pkg_name;
push @nonimported_subs, $name;
}
return @nonimported_subs;
}
有一个标志会告诉我们是否导入了一个glob中的CV,但是我找不到如何使用B来获取它,所以我检查了sub的__PACKAGE__
与正在检查的包
不可能判断某事是否是某种方法,所以我概括了该子的名称。
答案 1 :(得分:2)
PPI将解析源代码,因此甚至不需要加载模块:
use PPI;
my $source = $INC{'Some/Module.pm'}; # or whatever
my $Document = PPI::Document->new($source) or die "oops";
for my $sub ( @{ $Document->find('PPI::Statement::Sub') || [] } ) {
unless ( $sub->forward ) {
print $sub->name, "\n";
}
}