Заставьте Perl предупредить меня об отсутствии неиспользуемых функций

perl -wle 'if (0) {no_such_func()}'

Вышеописанное работает без ошибок, несмотря на -w, потому что no_such_func() никогда не вызывается.

Как заставить Perl проверять все функции / модули, на которые я ссылаюсь, даже те, которые я не использую?

В более реалистичном случае некоторые функции можно вызывать только в особых случаях, но я все же хотел бы убедиться, что они существуют.

РЕДАКТИРОВАТЬ: я установил perlcritic, но я думаю, что я все еще делаю что-то не так. Я создал этот файл:

#!/bin/perl -w   
use strict; 
if (0) {no_such_func();}

и perlcritic сказал, что все в порядке ("источник в порядке"). Неужели статический анализ может уловить отсутствие no_such_func()? Программа также работает нормально (и не выводит).

3 ответа

Решение

Вы не можете сделать это, потому что Perl не видит, существуют ли функции до времени выполнения. Не может Рассмотрим функцию, которая только получает evalв существовании:

eval 'sub foo { return $_[0]+1 }';

Эта строка кода создаст подпрограмму во время выполнения.

Или учтите, что Perl может использовать символические ссылки

my $func = 'func';
$func = "no_such_" . $func;
&$func;

В этом случае он звонит вашему no_such_func функция, но вы не можете сказать с помощью статического анализа.

Кстати, если вы хотите найти функции, на которые никогда не ссылаются, хотя бы с помощью статического анализа, то вы можете использовать такой инструмент, как Perl::Critic. См. http://perlcritic.com/ или установите Perl:: Critic из CPAN.

Хм, это сложно: когда Perl анализирует вызов функции, он не всегда знает, будет ли эта функция существовать. Это тот случай, когда функция вызывается до объявления:

foo();
sub foo { say 42 }

Иногда, функция может быть доступна только во время выполнения:

my $bar = sub { say 42 };
my $baz = sub { say "" };
*foo = rand > 0.5 ? $bar : $baz;
foo();

(Здесь я бы хотел упомянуть мем "Только Perl может анализировать Perl".)

Я уверен, что вы могли бы взломать внутренние компоненты Perl, чтобы жаловаться, когда функция не может быть решена до выполнения, но это не очень полезно, учитывая приведенные выше случаи использования.

Вы можете принудительно проверять время компиляции, если вы вызываете все подпрограммы без скобок. Таким образом, следующее не удастся:

$ perl -e 'use strict; my $condvar; if ($condvar) {no_such_func}'                     
Bareword "no_such_func" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.

(Тем не менее, это не сбой, если вы пишете if (0)Похоже, что оптимизатор Perl удаляет весь блок без дальнейшей проверки)

Это приводит к тому, что вы должны определить все подпрограммы перед их использованием. Если вы так работаете, то иногда необходимы "предварительные" декларации. Но тогда возможно, что предварительное объявление никогда не получит определения, что является еще одним возможным случаем ошибки.

Другие вопросы по тегам