如果您有一个代码覆盖率接近 100% 的测试套件,您可以使用它来查找所有调用站点。
给定调用堆栈中位置的参数,caller
内置函数返回
- 调用者的包名
- 文件名
- 电话号码
- 完全限定的子名称
- ……还有更多
我们现在可以添加一些记录调用位置的代码。我们可以将结果放入某种数据结构中进行自动处理,也可以将报告写入日志文件。例如
sub this_logs {
{
# seperate scope to not pollute your sub
state $log_fh //= do {
open my $fh, ">", "record_callsites.log"; # assuming autodie;
$fh;
};
state $seen = {};
my (undef, undef, undef, $sub) = caller(1);
my ($package, $file, $line, ) = caller(0);
my $site = $sub ? "$sub()" : "pkg $package";
unless ($seen->{$file}{$line}++) {
say {$log_fh} "CALL from $site at $file line $line";
}
}
my ($param1, $param2) = @_;
# etc
}
假设你所有的代码都是
this_logs(1, 2, 3); # direct call
foo(); # call from same package
my $sub = "this_" . "logs";
baz($sub); # call by name
Foo::bar(); # call from different package
foo(); # duplicate call
sub foo {
return this_logs(5, 6, 7);
}
sub baz {
shift()->(1, 2, 3); # no strict refs for this, please
};
package Foo;
sub bar {
main::this_logs();
}
这将产生日志文件
CALL from pkg main at - line 20
CALL from main::foo() at - line 28
CALL from main::baz() at - line 31
CALL from Foo::bar() at - line 3
(文件名-
表示标准输入)
因此,给定一个合适的测试套件,它能够找到无法被 grep 的调用站点。
如果您有一个非白痴编辑器,您还可以发出一个脚本,依次打开每个文件并将光标定位在正确的行上:
say "kate -l $line $file";
say "vim +$line $file";