【问题标题】:Prevent compiler execution of BEGIN / UNITCHECK / CHECK / INIT blocks防止编译器执行 BEGIN / UNITCHECK / CHECK / INIT 块
【发布时间】:2020-09-04 12:32:45
【问题描述】:

我想检测我的 perl 代码中的语法错误。我发现perlcritic 错过了其中的许多,(例如,在任何if 之前插入随机的else,因此尝试使用perl -cw 进行编译看起来是唯一可行的选择。

但是,我不想在检查错误时打开自己执行代码。

This perlmonks post 表示在 BEGIN、INIT、UNITCHECK 和 CHECK 块可以/确实在编译时被执行。

我可以在不运行任何代码的情况下检查perl 代码的语法吗?

如果删除或重命名可能导致执行的块怎么办?

【问题讨论】:

  • perlcritic 和 perl-tidy 不运行代码,
  • @choroba 我尝试使用 perlcritic 进行 linting,一切似乎都很好......直到我尝试编译代码并遇到更多错误。

标签: perl perl-critic


【解决方案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 语句)等。

【讨论】:

  • 感谢您的出色解释。语法错误怎么办?当然可以在不执行的情况下检测到它们吗?我目前在我的vim linters 中同时使用perlcritic 和(勉强)perl -cw,因为语法错误似乎需要后者。
  • 你的意思是语法错误?不,我使用了一个示例,根据随机数生成了两种不同的语法。我可以很容易地使它们的语法不兼容(例如,使用(&amp;) 而不是())。
猜你喜欢
  • 1970-01-01
  • 2011-05-30
  • 1970-01-01
  • 2014-07-07
  • 2019-11-08
  • 2015-02-10
  • 2018-12-15
相关资源
最近更新 更多