跟踪导入的子例程的源

时间:2014-11-20 18:12:26

标签: perl

在加载测试框架之前,我修改了一个使用27个模块的相当大的单元测试:

use Test::Most;

当脚本到达此行时,它会输出以下警告:

mytest.t ........... Subroutine main::explain redefined at mytest.t line 84.

现在我可以通过在调用use之前简单地取消定义子例程来隐藏重新定义的消息。

BEGIN {
    undef *explain;    # Method imported somewhere before.  Hide the redefine messages
}

use Test::Most;

但是,我想确定哪个模块正在导入另一个版本的解释。

可以使用消除过程并在我收到警告之前注释掉所有内容,但如果有更直接的路径来确定来源会很好。

2 个答案:

答案 0 :(得分:2)

在提供警告的行之前插入use Devel::Peek qw( ); BEGIN { Devel::Peek::Dump(\&foo); }会告诉您哪个包(COMP_STASH)和文件名(FILE)。

也可以为您提供行号的解决方案。可以遍历函数的操作码树,直到找到nextstate(这可能是树的第一个操作)。可以从op中提取文件名和行号。 nextstate操作设置运行时警告发出的文件和行号。

注意:

  • #line指令会影响两种解决方案。

  • 如果模块导出导入的子模块,则两个解决方案都会提供原始包和原始文件,而不是中间人。

答案 1 :(得分:2)

您可以使用perl的内省工具(称为B):

use B;
my $gv = B::svref_2object(\&explain)->GV;
printf "%s::%s file %s line %s\n", $gv->STASH->NAME, $gv->NAME, $gv->FILE, $gv->LINE;

Test::Most::explain file /usr/share/perl5/Test/Most.pm line 175

(行是sub的结尾,而不是开头)