¿Existe una herramienta para extraer todas las variables, módulo, y nombres de funciones de un archivo de módulo de Perl?

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

  •  20-09-2019
  •  | 
  •  

Pregunta

Mis disculpas si esto es un duplicado; Puede que no sepa los términos apropiados para buscar.

Estoy encargado de analizar un archivo de módulo Perl (.pm) que es un fragmento de una aplicación más grande. ¿Existe una herramienta, aplicación o script que simplemente va a pasar por el código y sacar todas las nombres de variables, nombres de los módulos, y llamadas a funciones? Aún mejor sería algo que podría identificar si se declara dentro de este archivo o es algo externo.

¿Existe una herramienta de este tipo? Solo me dan el archivo, así que esto no es algo que pueda ejecutar -. Sólo algunos análisis estático básica supongo

¿Fue útil?

Solución

Consulte la nueva, pero bien recomendado Class::Sniff .

A partir de los 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";
}

Esto le dará la mayor parte del camino. Algunos variables, dependiendo de su alcance, puede no estar disponible.

Otros consejos

Si he entendido bien, que busca una herramienta que pasar por el código fuente de Perl. Voy a sugerir PPI .

Este es un ejemplo de adoquines a partir de los 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;

Tenga en cuenta que, esta es la salida:

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

debido a múltiples clases se definen en HTML/Template.pm. Es evidente que un enfoque menos ingenua que trabajaría con el árbol PDom de una manera jerárquica.

Otra de las herramientas disponibles CPAN es Clase :: 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' );

Esto le dará resultados similares a la Clase :: Sniff; es posible que tenga que hacer algún tipo de procesamiento por su cuenta.

Hay mejores respuestas a esta pregunta, pero no se les está publicado, así que voy a reclamar el más rápido en el Oeste y seguir adelante y publicar una 'solución rápida'.

Esta herramienta existe, de hecho, y está integrado en Perl. Se puede acceder a la tabla de símbolos para cualquier espacio de nombres mediante el uso de una variable hash especial. Para acceder al espacio de nombres main (el valor predeterminado):

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

Si el paquete se denomina Mi / Package.pm, y por lo tanto en el espacio de nombres My::Package, que iba a cambiar %main:: a %My::Package:: para lograr el mismo efecto. Vea la perldoc perlmod entrada en tablas de símbolos - lo explican, y que la lista algunas alternativas que pueden ser mejor, o al menos que pueda empezar a encontrar el módulo adecuado para el trabajo (que es el lema de Perl - Hay más de un módulo para hacerlo)

.

Si desea hacerlo sin ejecutar cualquier código que se está analizando, es bastante fácil de hacer esto con PPI . Mira mi Módulo :: Uso :: Extracto ; Es un poco corta de código que muestra cómo extraer cualquier tipo de elemento que desee de PerlDOM del PPI.

Si quiere hacerlo con código que se ha acumulado, las otras sugerencias en las respuestas son mejores.

He encontrado una muy buena respuesta a lo que estaba buscando en este por Randal Schwartz. Demostró utilizando el módulo B :: referencia externa para extraer la información que estaba buscando exactamente. Sólo la sustitución de la de una sola línea que utiliza evaluado con el nombre de archivo del módulo funcionó como un campeón, y al parecer B :: referencia externa viene con ActiveState Perl, por lo que no necesita ningún módulos adicionales.

perl -MO=Xref module.pm 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top