首页 > 解决方案 > 我如何简明地检查警告类别,直到我的包中的层次结构的根?

问题描述

我知道如何use warnings::register为我的模块创建自定义警告类别。但是,如果我创建警告类别Module::category并使用 警告warnif()no warnings 'Module'则不会抑制警告。我怎样才能简明扼要地检查Module::categoryModule

MCVE

package Provider;
use strict; use warnings;

use warnings::register qw(undefined);

sub foo {
    warnings::warnif('Provider::undefined', "Undefined parameter!");
}

package Consumer;
use strict; use warnings;

Provider::foo;      # warns - OK

{
    no warnings 'Provider::undefined';
    Provider::foo;  # does not warn - OK
}

{
    no warnings 'Provider';
    Provider::foo;  # _DOES_ warn - oops  <===========
}

其他调查

如果我检查内部警告的状态Provider::foo(),我发现no warnings 'Provider'它没有触及Provider::undefined

sub foo {
    print "$_: @{[warnings::enabled($_) ? 'enabled' : 'disabled']}\n"
        foreach qw(Provider::undefined Provider);
 }

Provider::undefined: enabled
Provider: enabled
Provider::undefined: disabled
Provider: enabled
Provider::undefined: enabled
Provider: disabled

对于上面的三个测试。

一种解决方法

sub foo {
    my $should_warn = 1;
    foreach (qw(Provider::undefined Provider)) {
        if(!warnings::enabled($_)) {
            $should_warn = 0;
            last;
        }
    }
    warnings::warn('Provider::undefined', "Undefined parameter!")
        if $should_warn;
}

...但在我将它包装在一个模块中并将其放在 CPAN 上之前,我想知道是否有其他人已经这样做了,或者知道更好的方法:)。谷歌和 SO 搜索不可用。

标签: perlwarningshierarchypragma

解决方案


use warnings::register qw(undefined);声明引入了两种新的警告类别,'Provider'以及'Provider::undefined'. 所以检查两者

sub foo {
    if (warnings::enabled('Provider') and 
        warnings::enabled('Provider::undefined')) 
    {
        warnings::warn('Undefined parameter');
    }   
}

如果任一类别被抑制,这将不会触发

{
    no warnings 'Provider';               # EITHER stops it
    #no warnings 'Provider::undefined';

    Provider::foo;                        # does not warn
}

要求两者都no warnings停止它们or::enabled条件中的使用foo


为了减少Provider在模块的 subs 中的输入,您可以为此设置一个实用程序 sub,例如

my $to_warn = sub  {
    return 0 if not warnings::enabled(__PACKAGE__);
    warnings::enabled(__PACKAGE__ . '::' . $_) 
        or return 0  for @_;
    return 1;
};

然后可以做

warnings::warn('Undefined parameter') if $to_warn->('undefined');

可以在 中设置更多默认值$to_warn。现在Provider根本不需要输入名称:)

回想一下,$to_warn必须在使用之前定义,或者至少预先声明。


推荐阅读