Perl 列出包中的子包,不包括从其他包中导入的子包



有几种方法可以列出包中的所有子:

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";
    }
}

相关内容

最新更新