Neither perlcritic
nor perltidy
execute any of the code they analyse/manipulate.
To properly parse Perl code, part of it needs to be executed.
For example,
BEGIN {
if (rand() < 0.5) {
*f = sub { 5 };
} else {
*f = sub() { 5 };
}
}
print f + 2;
randomly outputs 5
or 7
because the last statement is randomly compiled as one of the following:
print( f( +2 ) ); # rand() >= 0.5
print( f() + 2 ); # rand() < 0.5
Ok, so that's pretty far-fetched. Or is it? How is that different than
use Module qw( f ); # No different than a BEGIN block.
print f + 2;
Ok, so prototypes are discouraged. But what about
say "foo"; # This is a sub call.
use feature qw( say );
say "foo"; # This isn't a sub call; this is the say operator.
This means that correctly parsing code that uses the say
operator (not counting CORE::say
) requires executing code. A lot code uses the say
operator.
But, if you account for a few common special cases, and if you accept a certain amount of imprecision (like whether say
is a sub call or the say
operator), one could parse Perl code fairly accurately without executing any of it. This is the idea behind PPI.
perlcritic
uses PPI. It doesn't execute any of the code it analyses.
perltidy
uses its own parser. It doesn't execute any of the code it analyses.
perl -c
will execute BEGIN
blocks (including use
statements) and the like.
perlcritic
and all seemed well... until I tried compiling the code and got a whole bunch more errors. – Disadvantaged