Existe uma ferramenta para extrair todos os nomes de variáveis, módulos e funções de um arquivo de módulo Perl?

StackOverflow https://stackoverflow.com/questions/1343630

  •  20-09-2019
  •  | 
  •  

Pergunta

Minhas desculpas se isso é uma duplicata; Talvez eu não conheça os termos adequados para procurar.

Tenho a tarefa de analisar um arquivo de módulo Perl (.pm) que é um fragmento de um aplicativo maior. Existe uma ferramenta, aplicativo ou script que simplesmente passarão pelo código e retiram todos os nomes de variáveis, nomes de módulos e chamadas de função? Melhor ainda seria algo que identificaria se foi declarado dentro desse arquivo ou é algo externo.

Essa ferramenta existe? Eu só recebo o único arquivo, então isso não é algo que eu possa executar - apenas algumas análises estáticas básicas, eu acho.

Foi útil?

Solução

Confira o novo, mas bem recomendado Class::Sniff.

Dos documentos:

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

Isso o levará a maior parte do caminho até lá. Algum variables, dependendo do escopo, pode não estar disponível.

Outras dicas

Se eu entendi corretamente, você está procurando uma ferramenta para passar pelo código -fonte Perl. Eu vou sugerir PPI.

Aqui está um exemplo de destaque dos documentos:

#!/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;

Observe que isso será lançado:

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

porque várias classes são definidas em HTML/Template.pm. Claramente, uma abordagem menos ingênua funcionaria com a árvore do PDOM de maneira hierárquica.

Outra ferramenta CPAN disponível é Classe :: Inspetor

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' );

Isso lhe dará resultados semelhantes à classe :: Sniff; Você ainda pode ter que fazer algum processamento por conta própria.

Há melhores respostas para essa pergunta, mas elas não estão sendo publicadas, então reivindicarei a arma mais rápida no oeste e irei em frente e postar uma 'rápida fixação'.

Essa ferramenta existe, de fato, e é incorporada ao Perl. Você pode acessar a tabela de símbolos para qualquer espaço para nome usando uma variável de hash especial. Para acessar o main namespace (o padrão):

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

Se o seu pacote for chamado My/Package.pm, e, portanto, estiver no espaço para nome My::Package, você mudaria %main:: para %My::Package:: para alcançar o mesmo efeito. Veja o Perlmod Perlmod Entrada nas tabelas de símbolos - elas explicam e listam algumas alternativas que podem ser melhores, ou pelo menos você começar a encontrar o módulo certo para o trabalho (esse é o lema Perl - há mais de um módulo para fazê -lo).

Se você quiser fazer isso sem executar nenhum código que esteja analisando, é bastante fácil fazer isso com PPI. Confira o meu Módulo :: Use :: Extract; É um pouco de código mostra como extrair qualquer tipo de elemento que você deseja do PerlDom da PPI.

Se você deseja fazer isso com o código que já compilou, as outras sugestões nas respostas são melhores.

Encontrei uma resposta muito boa para o que estava procurando neste coluna Por Randal Schwartz. Ele demonstrou usar o módulo B :: XREF para extrair exatamente as informações que eu estava procurando. Apenas substituindo a linha de uma linha avaliada que ele usou com o nome do arquivo do módulo funcionou como um campeão e, aparentemente, B :: XREF vem com o Activestate Perl, então eu não precisava de módulos adicionais.

perl -MO=Xref module.pm 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top