Предотвратить выполнение компилятором блоков BEGIN/UNITCHECK/CHECK/INIT

Я хочу обнаружить грамматические ошибки в моем коде Perl. Я обнаружил, что perlcritic пропускает многие из них (например, случайный else вставляется перед любым if, поэтому попытка скомпилировать с perl -cw выглядит как единственный жизнеспособный вариант.

Однако я не хочу открывать себя для выполнения кода при проверке на наличие ошибок.

Этот пост perlmonks показывает, что в блоках BEGIN, INIT, UNITCHECK и CHECK можно/можно получить выполняется при компиляции.

Могу ли я проверить грамматику perl кода, не запуская его?

Как насчет удаления или переименования блока, который может привести к выполнению?


person Tom Hale    schedule 04.09.2020    source источник
comment
perlcritic и perl-tidy не запускают код,   -  person choroba    schedule 04.09.2020
comment
@choroba Я пробовал анализировать с помощью perlcritic, и все казалось хорошо ... пока я не попытался скомпилировать код и не получил еще целую кучу ошибок.   -  person Tom Hale    schedule 04.09.2020


Ответы (1)


Ни perlcritic, ни perltidy выполняют любой код, который они анализируют/манипулируют.


Чтобы правильно разобрать код Perl, часть его должна быть выполнена.

Например,

BEGIN {
   if (rand() < 0.5) {
      *f = sub { 5 };
   } else {
      *f = sub() { 5 };
   }
}

print f + 2;

случайным образом выводит 5 или 7, потому что последний оператор компилируется случайным образом как один из следующих:

print( f( +2 ) );   # rand() >= 0.5
print( f() + 2 );   # rand() < 0.5

Хорошо, так что это довольно надуманно. Или это? Чем это отличается от

use Module qw( f );   # No different than a BEGIN block.

print f + 2;

Итак, прототипы не приветствуются. Но что насчет

say "foo";   # This is a sub call.

use feature qw( say );

say "foo";   # This isn't a sub call; this is the say operator.

Это означает, что для правильного синтаксического анализа кода, в котором используется оператор say (не считая CORE::say), требуется выполнение кода. В коде лота используется оператор say.

Но если принять во внимание несколько общих особых случаев и принять некоторую неточность (например, является ли say подвызовом или оператором say), код Perl можно достаточно точно проанализировать, не выполняя его. В этом заключается идея PPI.

  • perlcritic использует PPI. Он не выполняет анализируемый код.
  • perltidy использует собственный синтаксический анализатор. Он не выполняет анализируемый код.
  • perl -c выполнит BEGIN блоков (включая use операторов) и тому подобное.
person ikegami    schedule 04.09.2020
comment
Спасибо за это отличное объяснение. Как быть с грамматическими ошибками? Неужели их можно обнаружить без казни? В настоящее время я использую как perlcritic, так и (неохотно) perl -cw в своих vim линтерах, так как последний, кажется, требуется для грамматических ошибок. - person Tom Hale; 04.09.2020
comment
Вы имеете в виду синтаксические ошибки? Нет. Я использовал пример создания двух разных синтаксисов на основе случайного числа. Я мог легко сделать их несовместимыми синтаксисами (например, используя (&) вместо ()). - person ikegami; 04.09.2020