繁体   English   中英

是否有工具从Perl模块文件中提取所有变量,模块和函数名称?

[英]Is there a tool for extracting all variable, module, and function names from a Perl module file?

如果这是重复,我道歉; 我可能不知道要搜索的正确术语。

我的任务是分析一个Perl模块文件(.pm),它是一个更大的应用程序的片段。 是否有工具,应用程序或脚本只需通过代码并提取所有变量名称,模块名称和函数调用? 更好的是能够识别它是在该文件中声明还是外部的东西。

这样的工具存在吗? 我只得到一个文件,所以这不是我可以执行的东西 - 我想是一些基本的静态分析。

看看新的,但很好推荐的Class::Sniff

来自文档:

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

my $num_methods = $sniff->methods;
my $num_classes = $sniff->classes;
my @methods     = $sniff->methods;
my @classes     = $sniff->classes;

{
  my $graph    = $sniff->graph;   # Graph::Easy
  my $graphviz = $graph->as_graphviz();

  open my $DOT, '|dot -Tpng -o graph.png' or die("Cannot open pipe to dot: $!");
  print $DOT $graphviz;
}

print $sniff->to_string;
my @unreachable = $sniff->unreachable;
foreach my $method (@unreachable) {
    print "$method\n";
}

这将让你大部分时间到达那里。 某些variables (取决于范围)可能无法使用。

如果我理解正确,您正在寻找一个工具来完成Perl源代码。 我打算建议PPI

这是一个从文档中拼凑出来的例子:

#!/usr/bin/perl

use strict;
use warnings;

use PPI::Document;
use HTML::Template;

my $Module = PPI::Document->new( $INC{'HTML/Template.pm'} );

my $sub_nodes = $Module->find(
    sub { $_[1]->isa('PPI::Statement::Sub') and $_[1]->name }
);

my @sub_names = map { $_->name } @$sub_nodes;

use Data::Dumper;
print Dumper \@sub_names;

请注意,这将输出:

     ...
     'new',
     'new',
     'new',
     'output',
     'new',
     'new',
     'new',
     'new',
     'new',
     ...

因为HTML/Template.pm中定义了多个类。 显然,一种不那么天真的方法可以以分层方式使用PDOM树。

另一种可用的CPAN工具是Class :: Inspector

use Class::Inspector;

# Is a class installed and/or loaded
Class::Inspector->installed( 'Foo::Class' );
Class::Inspector->loaded( 'Foo::Class' );

# Filename related information
Class::Inspector->filename( 'Foo::Class' );
Class::Inspector->resolved_filename( 'Foo::Class' );

# Get subroutine related information
Class::Inspector->functions( 'Foo::Class' );
Class::Inspector->function_refs( 'Foo::Class' );
Class::Inspector->function_exists( 'Foo::Class', 'bar' );
Class::Inspector->methods( 'Foo::Class', 'full', 'public' );

# Find all loaded subclasses or something
Class::Inspector->subclasses( 'Foo::Class' );

这将给你类似于Class :: Sniff的结果; 您可能仍需要自己进行一些处理。

这个问题有更好的答案,但它们没有被发布,所以我会声称西部最快的枪并继续发布'快速修复'。

事实上,这样的工具存在于Perl中。 您可以使用特殊的哈希变量访问任何名称空间的符号表。 要访问main命名空间(默认命名空间):

for(keys %main::) { # alternatively %::
  print "$_\n";
}

如果您的包名为My / Package.pm,因此位于名称空间My::Package ,您可以将%main::更改为%My::Package::以实现相同的效果。 请参阅符号表上的perldoc perlmod条目 - 他们会解释它,并列出一些可能更好的替代方案,或者至少让您开始为工作找到合适的模块(这是Perl的座右铭 - 有多个模块到做它)。

如果您想在不执行任何正在分析的代码的情况下执行此操作,使用PPI执行此操作相当容易。 看看我的Module :: Use :: Extract ; 它是一小段代码,向您展示如何从PPI的PerlDOM中提取您想要的任何元素。

如果您想使用已编译的代码执行此操作,则答案中的其他建议会更好。

Randal Schwartz在本专栏中找到了一个非常好的答案。 他演示了如何使用B :: Xref模块提取我正在寻找的信息。 只是替换他使用的模块文件名的评估单线程就像一个冠军,显然B :: Xref带有ActiveState Perl,所以我不需要任何额外的模块。

perl -MO=Xref module.pm 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM