我怎样才能抽出未定义的子程序?
How can I smoke out undefined subroutines?
我想扫描代码库以识别当前无法访问的所有未定义子例程实例。
举个例子:
use strict;
use warnings;
my $flag = 0;
if ( $flag ) {
undefined_sub();
}
观察结果
当 $flag
计算结果为真时,发出以下警告:
Undefined subroutine &main::undefined_sub called at - line 6
我不想依赖在 运行 时发出的警告来识别未定义的子例程
strict
和 warnings
用法在这里没有帮助。 use strict 'subs'
没有效果。
连下面的代码片断都没有了
$ perl -Mstrict -we 'exit 0; undefined_sub()'
你要求的至少在某种意义上是不可能的。考虑以下代码片段:
( rand()<0.5 ? *foo : *bar } = sub { say "Hello World!" };
foo();
有 50% 的几率 运行 正常,有 50% 的几率会出现 "Undefined subroutine" 错误。该决定是在 运行 时间做出的,因此无法在此之前告诉它会是什么。这当然是为了证明一点而设计的案例,但是 运行 时间(或编译时)子例程的生成在实际代码中并不少见。例如,查看 Moose
如何添加创建方法的函数。静态源代码分析永远无法完全分析这样的代码。
B::Lint
可能是 运行 之前的最佳状态。
要查找对未在编译时定义的子程序的调用,您可以使用 B::Lint,如下所示:
a.pl
:
use List::Util qw( min );
sub defined_sub { }
sub defined_later;
sub undefined_sub;
defined_sub();
defined_later();
undefined_sub();
undeclared_sub();
min();
max(); # XXX Didn't import
List::Util::max();
List::Util::mac(); # XXX Typo!
sub defined_later { }
测试:
$ perl -MO=Lint,undefined-subs a.pl
Undefined subroutine 'undefined_sub' called at a.pl line 9
Nonexistent subroutine 'undeclared_sub' called at a.pl line 10
Nonexistent subroutine 'max' called at a.pl line 12
Nonexistent subroutine 'List::Util::mac' called at a.pl line 14
a.pl syntax OK
请注意,这仅适用于子调用。不检查方法调用(例如 Class->method
和 method Class
)。但是你问的是子调用。
请注意 foo $x
是一个有效的方法调用(使用 间接方法调用 语法)意味着 $x->foo
如果 foo
不是一个有效的函数或子函数,所以 B::Lint 不会捕捉到它。但它会捕获 foo($x)
.
也许Subroutines::ProhibitCallsToUndeclaredSubs policy from Perl::Critic可以提供帮助
This Policy checks that every unqualified subroutine call has a matching subroutine declaration in the current file, or that it explicitly appears in the import list for one of the included modules.
这个"policy"是Perl::Critic::StricterSubs的一部分,需要安装。那里还有一些政策。这被认为是 4 级违规,因此您可以
perlcritic -4 script.pl
并解析 neither declared nor explicitly imported
的输出,或使用
perlcritic -4 --single-policy ProhibitCallsToUndeclaredSubs script.pl
一些合法用途仍被标记,因为它要求明确导入所有潜艇。
这是一个静态分析器,我认为应该符合您的目的。
我想扫描代码库以识别当前无法访问的所有未定义子例程实例。
举个例子:
use strict;
use warnings;
my $flag = 0;
if ( $flag ) {
undefined_sub();
}
观察结果
当
$flag
计算结果为真时,发出以下警告:Undefined subroutine &main::undefined_sub called at - line 6
我不想依赖在 运行 时发出的警告来识别未定义的子例程
strict
和warnings
用法在这里没有帮助。use strict 'subs'
没有效果。连下面的代码片断都没有了
$ perl -Mstrict -we 'exit 0; undefined_sub()'
你要求的至少在某种意义上是不可能的。考虑以下代码片段:
( rand()<0.5 ? *foo : *bar } = sub { say "Hello World!" };
foo();
有 50% 的几率 运行 正常,有 50% 的几率会出现 "Undefined subroutine" 错误。该决定是在 运行 时间做出的,因此无法在此之前告诉它会是什么。这当然是为了证明一点而设计的案例,但是 运行 时间(或编译时)子例程的生成在实际代码中并不少见。例如,查看 Moose
如何添加创建方法的函数。静态源代码分析永远无法完全分析这样的代码。
B::Lint
可能是 运行 之前的最佳状态。
要查找对未在编译时定义的子程序的调用,您可以使用 B::Lint,如下所示:
a.pl
:
use List::Util qw( min );
sub defined_sub { }
sub defined_later;
sub undefined_sub;
defined_sub();
defined_later();
undefined_sub();
undeclared_sub();
min();
max(); # XXX Didn't import
List::Util::max();
List::Util::mac(); # XXX Typo!
sub defined_later { }
测试:
$ perl -MO=Lint,undefined-subs a.pl
Undefined subroutine 'undefined_sub' called at a.pl line 9
Nonexistent subroutine 'undeclared_sub' called at a.pl line 10
Nonexistent subroutine 'max' called at a.pl line 12
Nonexistent subroutine 'List::Util::mac' called at a.pl line 14
a.pl syntax OK
请注意,这仅适用于子调用。不检查方法调用(例如 Class->method
和 method Class
)。但是你问的是子调用。
请注意 foo $x
是一个有效的方法调用(使用 间接方法调用 语法)意味着 $x->foo
如果 foo
不是一个有效的函数或子函数,所以 B::Lint 不会捕捉到它。但它会捕获 foo($x)
.
也许Subroutines::ProhibitCallsToUndeclaredSubs policy from Perl::Critic可以提供帮助
This Policy checks that every unqualified subroutine call has a matching subroutine declaration in the current file, or that it explicitly appears in the import list for one of the included modules.
这个"policy"是Perl::Critic::StricterSubs的一部分,需要安装。那里还有一些政策。这被认为是 4 级违规,因此您可以
perlcritic -4 script.pl
并解析 neither declared nor explicitly imported
的输出,或使用
perlcritic -4 --single-policy ProhibitCallsToUndeclaredSubs script.pl
一些合法用途仍被标记,因为它要求明确导入所有潜艇。
这是一个静态分析器,我认为应该符合您的目的。