有几种方法可以列出包中的所有子:
sub list_methods {
my $package = shift;
no strict 'refs';
return grep { defined &{"$package::$_"} } keys %{"$package::"}
}
但是,如果包"使用"其他包,如"File::Basename",则像"fileparse"这样的子包也会被列出。我试图"要求"软件包而不是"使用"它们,问题可以解决。另一方面,如果我"需要"包,我必须指定 subs 的完整路径。
你有什么想法吗?
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 来获取它,所以我根据正在检查的包裹检查潜艇的__PACKAGE__
。
无法判断某物是否是一种方法,所以我概括了子的名称。
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";
}
}