Как я могу выкурить undefined подпрограммы?
Я хочу отсканировать базу кода, чтобы идентифицировать все экземпляры подпрограмм undefined, которые пока недоступны.
В качестве примера:
use strict;
use warnings;
my $flag = 0;
if ( $flag ) {
undefined_sub();
}
Наблюдения
-
Когда $flag
получает значение true, выдается следующее предупреждение:
Undefined subroutine &main::undefined_sub called at - line 6
Я не хочу полагаться на предупреждения, выпущенные во время выполнения, для определения undefined подпрограмм
-
Прагмы strict
и warnings
здесь не помогают. use strict 'subs'
не имеет эффекта.
-
Даже следующий фрагмент кода не работает
$ perl -Mstrict -we 'exit 0; undefined_sub()'
Ответы
Ответ 1
Возможно Политика подпрограмм:: ЗапретCallsToUndeclaredSubs из Perl:: Critic может помочь
Эта политика проверяет, что каждый вызов неквалифицированной подпрограммы имеет соответствующее подпрограммное объявление в текущем файле или явно отображается в списке импорта для одного из включенных модулей.
Эта "политика" является частью Perl:: Critic:: StricterSubs, которая должна быть установлена. Там есть еще несколько политик. Это считается нарушением строгости 4, поэтому вы можете сделать
perlcritic -4 script.pl
и проанализировать вывод для neither declared nor explicitly imported
или использовать
perlcritic -4 --single-policy ProhibitCallsToUndeclaredSubs script.pl
Некоторое законное использование по-прежнему помечено, поскольку оно требует, чтобы все подписчики были явно импортированы.
Это статический анализатор, который, я думаю, должен соответствовать вашей цели.
Ответ 2
То, о чем вы просите, по крайней мере в некотором смысле невозможно. Рассмотрим следующий фрагмент кода:
( rand()<0.5 ? *foo : *bar } = sub { say "Hello World!" };
foo();
Вероятность 50%, что это будет работать нормально, и 50% вероятность того, что она даст ошибку Undefined. Решение принимается во время выполнения, поэтому до этого невозможно сказать, что это будет. Это, конечно, надуманный случай, чтобы продемонстрировать точку, но генерация подпрограмм времени исполнения (или времени компиляции) не является чем-то необычным в реальном коде. Например, посмотрите, как Moose
добавляет функции, которые создают методы. Статический анализ исходного кода никогда не сможет полностью проанализировать такой код.
B::Lint
, вероятно, примерно так же хорош, как может быть достигнуто до начала выполнения.