Y at-il un outil pour extraire toutes les variables, le module et les noms de fonction à partir d'un fichier de module Perl?

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

  •  20-09-2019
  •  | 
  •  

Question

Mes excuses si cela est un double; Je sais pas les propres termes à rechercher.

Je confié la tâche qui est un fragment d'une application plus large à l'analyse d'un fichier de module Perl (.pm). Y at-il un outil, l'application ou d'un script qui va simplement passer par le code et retirer tous les noms de variables, les noms des modules et des appels de fonction? Mieux encore serait quelque chose qui déterminer si elle a été déclarée dans ce fichier ou est quelque chose d'extérieur.

Est-ce qu'un tel outil existe? Je ne reçois que le seul fichier, donc ce n'est pas quelque chose que je peux exécuter -. Simplement une analyse statique de base, je suppose que

Était-ce utile?

La solution

Découvrez la nouvelle, mais bien recommandé Class::Sniff .

A partir de la documentation:

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

vous obtiendrez la plupart du chemin. Certains variables, selon la portée, peut ne pas être disponible.

Autres conseils

Si je comprends bien, vous êtes à la recherche d'un outil pour passer par le code source Perl. Je vais proposer PPI .

Voici un exemple bricolé à partir des documents:

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

Notez que, cette volonté de sortie:

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

parce que plusieurs classes sont définies dans HTML/Template.pm. De toute évidence, une approche moins naïve travaillerait avec l'arbre PDOM de manière hiérarchique.

Un autre outil CPAN est disponible Class :: inspecteur

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

Cela vous donnera des résultats similaires à la classe :: Sniff; vous pouvez toujours avoir à faire un peu de traitement sur votre propre.

Il y a de meilleures réponses à cette question, mais ils ne reçoivent pas d'affichage, donc je vais réclamer le plus rapide pistolet dans l'Ouest et allez-y et publier un « quick-fix ».

Un tel outil existe, en fait, et est construit en Perl. Vous pouvez accéder à la table de symboles pour tout espace de noms en utilisant une variable de hachage spécial. Pour accéder à l'espace de noms main (celui par défaut):

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

Si votre colis est nommé Mon / Package.pm, et est donc dans l'espace de noms My::Package, vous changeriez %main:: à %My::Package:: pour obtenir le même effet. Voir perldoc perlmod entrée sur les tables de symboles - ils l'expliquent, et ils énumèrent quelques solutions de rechange qui pourraient être mieux, ou au moins vous permettre de commencer à trouver le bon module pour le travail (c'est la devise Perl - Il y a plus d'un module à le faire)

.

Si vous voulez le faire sans exécuter de code que vous analysez, il est assez facile de le faire avec PPI . Regarde mes Module :: Utilisation :: Extrait ; il est un court morceau de code montre comment extraire une sorte d'élément que vous voulez de PerlDOM PPI.

Si vous voulez le faire avec le code que vous avez déjà compilé, les autres suggestions dans les réponses sont mieux.

J'ai trouvé une assez bonne réponse à ce que je cherchais dans cette par Randal Schwartz. Il a démontré à l'aide du module B :: Xref pour extraire exactement les informations que je cherchais. Il suffit de remplacer l'évaluation uniligne il a utilisé avec le nom du module a fonctionné comme un champion, et apparemment B :: Xref est livré avec ActiveState Perl, donc je ne pas besoin de modules supplémentaires.

perl -MO=Xref module.pm 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top