2009-08-27 14 views
5

Mis disculpas si esto es un duplicado; Es posible que no sepa los términos adecuados para buscar.¿Existe alguna herramienta para extraer todos los nombres de variables, módulos y funciones de un archivo de módulo Perl?

Tengo la tarea de analizar un archivo de módulo Perl (.pm) que es un fragmento de una aplicación más grande. ¿Hay alguna herramienta, aplicación o script que simplemente revise el código y extraiga todos los nombres de las variables, los nombres de los módulos y las llamadas a funciones? Aún mejor sería algo que identificaría si fue declarado dentro de este archivo o si es algo externo.

¿Existe una herramienta de este tipo? Solo obtengo el archivo, así que no puedo ejecutarlo, solo supongo que es un análisis estático básico.

+4

Tome un vistazo aquí: http://stackoverflow.com/questions/607282/whats-the-best-way-to-discover-all-subroutines-a-perl-module-has Hay varios métodos establecidos. –

Respuesta

9

Eche un vistazo a la nueva, pero bien recomendada 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. Es posible que algunos variables, según el alcance, no estén disponibles.

+0

+1 Parece que fui derrotado al premio de pistola más rápido y con una mejor respuesta. ¡Maldice mi falta de conocimiento de CPAN! Sólo –

+1

razón por la que sabía era porque pedí que hace unos meses :) –

+0

¿Este trabajo en un archivo? El módulo en cuestión (el que tengo que analizar) tiene dependencias que no puedo satisfacer, porque no poseo ese código. – romandas

2

Hay mejores respuestas a esta pregunta, pero no están siendo publicadas, así que voy a reclamar el arma más rápida en el oeste y seguir adelante y publicar una 'solución rápida'.

Tal herramienta existe, de hecho, y está integrada en Perl. Puede acceder a la tabla de símbolos para cualquier espacio de nombres utilizando una variable hash especial. Para acceder a la main espacio de nombres (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::-%My::Package:: para lograr el mismo efecto. Consulte la entrada perldoc perlmod en las tablas de símbolos: lo explican, y enumeran algunas alternativas que pueden ser mejores, o al menos comienzan a buscar el módulo correcto para el trabajo (ese es el lema de Perl: hay más de un módulo que hacer) Eso).

+0

¿No necesitaría cargar el módulo para usar esto? – romandas

+0

Si desea hacer esto sin cargar el módulo, es probable que tenga que usar un buen 'grep' antiguo. O 'ack', una reescritura extensamente extendida de' grep' en Perl, usando expresiones regulares de Perl y teniendo numerosas características mejoradas. –

+0

'% principal ::' sólo tendrá las variables de paquete, las variables léxicas (es decir, las creadas con 'my') no son almacenados en ella. –

7

Otras herramientas de CPAN disponibles es 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'); 

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

8

Si entiendo correctamente, está buscando una herramienta para pasar por el código fuente de Perl. Voy a sugerir PPI.

Aquí se muestra 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. Claramente, un enfoque menos ingenuo funcionaría con el árbol PDOM de una manera jerárquica.

3

Si desea hacerlo sin ejecutar ningún código que esté analizando, es bastante fácil hacerlo con PPI. Mira mi Module::Use::Extract; es una pequeña porción de código que le muestra cómo extraer cualquier tipo de elemento que desee del PerlDOM de PPI.

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

0

me pareció una muy buena respuesta a lo que estaba buscando en este column por Randal Schwartz. Demostró que usaba el módulo B :: Xref para extraer exactamente la información que estaba buscando. 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 
Cuestiones relacionadas