如何使用Devel :: Declare注入多行?

Sch*_*ern 15 perl

我想用来Devel::Declare注入多行Perl代码.但是,Devel::Declare::set_linestr()不能处理多行.

通常我会将多个语句一起作为一行加入.这些语句必须在单独的行上以保留其行号以用于错误报告目的.这是为了解决Method :: Signatures中的这个bug以及这个相关的bug.我愿意接受其他解决方案.

例如,Method :: Signatures目前会转换此代码......

use Method::Signatures;

func hello(
    $who = "World",
    $greeting = get_greeting($who)
) {
    die "$greeting, $who";
}
Run Code Online (Sandbox Code Playgroud)

......进入这...

func  \&hello; sub hello  { BEGIN { Method::Signatures->inject_scope('') }; my $who = (@_ > 0) ? ($_[0]) : ( get_greeting($who)); my $greeting = (@_ > 1) ? ($_[1]) : ( "Hello"); Method::Signatures->too_many_args_error(2) if @_ > 2;
    die "$greeting, $who";
}
Run Code Online (Sandbox Code Playgroud)

die $who 然后报告第4行而不是第7行.

我希望它是这个(或者可能涉及的东西#line).

func  \&hello; sub hello  { BEGIN { Method::Signatures->inject_scope('') };
    my $who = (@_ > 0) ? ($_[0]) : ( "World");
    my $greeting = (@_ > 1) ? ($_[1]) : ( get_greeting($who));
    Method::Signatures->too_many_args_error(2) if @_ > 2;
    die "$greeting, $who";
}
Run Code Online (Sandbox Code Playgroud)

这不仅忠实地再现了行号,而且如果get_greeting它从正确的行调用它将会报告.

tob*_*ink 3

根据您自己的回答,以下工作有效:

sub __empty() { '' }

sub parse_proto {
    my $self = shift;
    return q[print __LINE__."\n"; Foo::__empty(
);print __LINE__."\n"; Foo::__empty(
);print __LINE__."\n";];
}
Run Code Online (Sandbox Code Playgroud)

但会带来不可接受的开销,因为__empty()必须为每个参数调用该函数。__empty()通过使用永远不会计算为 true 的条件进行有条件调用,可以消除开销。

sub __empty() { '' }

sub parse_proto {
    my $self = shift;
    return q[print __LINE__."\n"; 0 and Foo::__empty(
);print __LINE__."\n"; 0 and Foo::__empty(
);print __LINE__."\n";];
}
Run Code Online (Sandbox Code Playgroud)