Как обнаружить недостижимый код в условном Perl, который всегда оценивается как ложный?
Я новичок в Perl, и в настоящее время мне поручено привести в порядок и поддерживать большой и довольно грязный проект Perl. Я использую Perl-критик, чтобы помочь мне обнаружить проблемы в коде (а также научить меня передовым методам).
В существующем коде есть места, где кодер создал недоступный код. Например, они добавили '&& 0' как ленивый способ закомментировать некоторые ветви кода:
if ($req->param('donut') && 0) {
unreachable code...
} else {
always branches to here...
}
Я надеялся, что Perl или Critic предупредят меня о недостижимом коде в таких случаях (когда у условного выражения есть постоянное значение, равное false), но это не так.
Есть ли какой-нибудь инструмент или фрагмент сценария, который я мог бы использовать для надежного обнаружения подобных вещей?
Очевидно, что я мог бы искать '&& 0' в исходном коде, но существует несколько способов, которыми кодировщик мог создать недоступный код, кроме добавления '&& 0' в оператор if.
2 ответа
Используя B:: Deparse, вы можете обнаружить недоступный код в некоторых ситуациях:
perl -MO=Deparse -e 'if (0 && $x) {print 1} else {print 2}'
do {
print 2
};
-e syntax OK
Это не так просто, если 0 не первое условие:
perl -MO=Deparse -e 'if ($x && 0) {print 1} else {print 2}'
if ($x and 0) {
print 1;
}
else {
print 2;
}
-e syntax OK
Почему это отличается? Хорошо, если 0 идет последним, все условия перед ним должны быть проверены. У них могут быть побочные эффекты, которые все еще будут происходить. Также, &&
форсирует скалярный контекст, поэтому он может изменить поведение кода, вызываемого при оценке условия.
Это не объясняет, почему сам блок не компилируется, извините. Я думаю, это будет слишком сложно.
Согласно ответу Чоробы, B::Deparse сможет показать вам случаи, когда код так явно недоступен, что компилятор Perl оптимизирует его. Но в общем случае это невозможно обнаружить. Следующий код включает в себя фактически недоступный блок.
use 5.006;
if ($] < 5) { ... }
Так как $]
переменная, которая возвращает текущую работающую версию Perl, которая гарантированно будет не ниже 5.006 use
линия. Но вам понадобятся довольно умные методы, чтобы понять это с помощью статического анализа исходного кода. (Помимо этого, хотя это и необычная вещь, можно изменить $]
во время выполнения - см. Acme::Futuristic::Perl - в этом случае код станет доступным.)
Если у вас есть достойный набор тестов для вашего кода, Devel:: Cover может быть полезен. Вы устанавливаете переменную среды PERL5OPT
в -MDevel::Cover
, затем запустите ваш набор тестов (обратите внимание, что он будет работать немного медленнее, чем обычно), затем выполните команду cover
который создаст симпатичный HTML-отчет. В этом отчете будет указано, какие подпрограммы не были выполнены, какие ветви никогда не использовались и т. Д.