Существует ли инструмент для извлечения всех имен переменных, модулей и функций из файла модуля Perl?
-
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