Существует ли инструмент для извлечения всех имен переменных, модулей и функций из файла модуля Perl?

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

  •  20-09-2019
  •  | 
  •  

Вопрос

Приношу свои извинения, если это дубликат;Возможно, я не знаю подходящих терминов для поиска.

Мне поручено проанализировать файл модуля 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.Я собираюсь предложить ИЦП.

Вот пример, почерпнутый из документов:

#!/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 являются Класс::Инспектор

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 - для этого существует более одного модуля).

Если вы хотите сделать это без выполнения какого-либо кода, который вы анализируете, это довольно легко сделать с помощью ИЦП.Посмотри на мой Модуль::Использовать::Извлечь;этот короткий фрагмент кода показывает вам, как извлечь любой элемент, который вы хотите, из PerlDOM PPI.

Если вы хотите сделать это с помощью кода, который вы уже скомпилировали, другие предложения в ответах будут лучше.

Я нашел довольно хороший ответ на то, что я искал в этом колонна автор: Рэндал Шварц.Он продемонстрировал использование модуля B::Xref для извлечения именно той информации, которую я искал.Простая замена оцененной однострочной строки, которую он использовал, на имя файла модуля сработала как нельзя лучше, и, по-видимому, B::Xref поставляется с ActiveState Perl, поэтому мне не понадобились никакие дополнительные модули.

perl -MO=Xref module.pm 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top