1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
package Perl::Critic::Policy::TestingAndDebugging::ProhibitNoWarnings;
use 5.010001;
use strict;
use warnings;
use Readonly;
use List::SomeUtils qw(all);
use Perl::Critic::Exception::Fatal::Internal qw{ throw_internal };
use Perl::Critic::Utils qw{ :characters :severities :data_conversion };
use parent 'Perl::Critic::Policy';
our $VERSION = '1.156';
#-----------------------------------------------------------------------------
Readonly::Scalar my $DESC => q{Warnings disabled};
Readonly::Scalar my $EXPL => [ 431 ];
#-----------------------------------------------------------------------------
sub supported_parameters {
return (
{
name => 'allow',
description => 'Permitted warning categories.',
default_string => $EMPTY,
parser => \&_parse_allow,
},
{
name => 'allow_with_category_restriction',
description =>
'Allow "no warnings" if it restricts the kinds of warnings that are turned off.',
default_string => '0',
behavior => 'boolean',
},
);
}
sub default_severity { return $SEVERITY_HIGH }
sub default_themes { return qw( core bugs pbp certrec ) }
sub applies_to { return 'PPI::Statement::Include' }
#-----------------------------------------------------------------------------
sub _parse_allow {
my ($self, undef, $config_string) = @_;
$self->{_allow} = {};
if( defined $config_string ) {
my $allowed = lc $config_string; #String of words
my %allowed = hashify( $allowed =~ m/ (experimental::\w+|\w+) /gxms );
$self->{_allow} = \%allowed;
}
return;
}
#-----------------------------------------------------------------------------
sub violates {
my ( $self, $elem, undef ) = @_;
return if $elem->type() ne 'no';
return if $elem->pragma() ne 'warnings';
my @words = _extract_potential_categories( $elem );
@words >= 2
and 'no' eq $words[0]
and 'warnings' eq $words[1]
or throw_internal
q<'no warnings' word list did not begin with qw{ no warnings }>;
splice @words, 0, 2;
return if $self->{_allow_with_category_restriction} and @words;
return if @words && all { exists $self->{_allow}->{$_} } @words;
#If we get here, then it must be a violation
return $self->violation( $DESC, $EXPL, $elem );
}
#-----------------------------------------------------------------------------
# Traverse the element, accumulating and ultimately returning things
# that might be warnings categories. These are:
# * Words (because of the 'foo' in 'no warnings foo => "bar"');
# * Quotes (because of 'no warnings "foo"');
# * qw{} strings (obviously);
# * Nodes (because of 'no warnings ( "foo", "bar" )').
# We don't lop off the 'no' and 'warnings' because we recurse.
# RT #74647.
{
Readonly::Array my @HANDLER => (
[ 'PPI::Token::Word' => sub { return $_[0]->content() } ],
[ 'PPI::Token::QuoteLike::Words' =>
sub { return $_[0]->literal() }, ],
[ 'PPI::Token::Quote' => sub { return $_[0]->string() } ],
[ 'PPI::Node' => sub { _extract_potential_categories( $_[0] ) } ],
);
sub _extract_potential_categories {
my ( $elem ) = @_;
my @words;
foreach my $child ( $elem->schildren() ) {
foreach my $hdlr ( @HANDLER ) {
$child->isa( $hdlr->[0] )
or next;
push @words, $hdlr->[1]->( $child );
last;
}
}
return @words;
}
}
1;
__END__
#-----------------------------------------------------------------------------
=pod
=for stopwords perllexwarn
=head1 NAME
Perl::Critic::Policy::TestingAndDebugging::ProhibitNoWarnings - Prohibit various flavors of C<no warnings>.
=head1 AFFILIATION
This Policy is part of the core L<Perl::Critic|Perl::Critic>
distribution.
=head1 DESCRIPTION
There are good reasons for disabling certain kinds of warnings. But
if you were wise enough to C<use warnings> in the first place, then it
doesn't make sense to disable them completely. By default, any
C<no warnings> statement will violate this policy. However, you can
configure this Policy to allow certain types of warnings to be
disabled (See L<"CONFIGURATION">). A bare C<no warnings>
statement will always raise a violation.
=head1 CONFIGURATION
The permitted warning types can be configured via the C<allow> option.
The value is a list of whitespace-delimited warning types that you
want to be able to disable. See L<perllexwarn|perllexwarn> for a list
of possible warning types. An example of this customization:
[TestingAndDebugging::ProhibitNoWarnings]
allow = uninitialized once
If a true value is specified for the
C<allow_with_category_restriction> option, then any C<no warnings>
that restricts the set of warnings that are turned off will pass.
[TestingAndDebugging::ProhibitNoWarnings]
allow_with_category_restriction = 1
=head1 SEE ALSO
L<Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings|Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings>
=head1 AUTHOR
Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
=head1 COPYRIGHT
Copyright (c) 2005-2021 Imaginative Software Systems. All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself. The full text of this license can be found in
the LICENSE file included with this module
=cut
##############################################################################
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
# fill-column: 78
# indent-tabs-mode: nil
# c-indentation-style: bsd
# End:
# ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :
|