File: ProhibitMixedBooleanOperators.pm

package info (click to toggle)
libperl-critic-perl 1.156-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,544 kB
  • sloc: perl: 24,092; lisp: 341; makefile: 7
file content (149 lines) | stat: -rw-r--r-- 4,146 bytes parent folder | download
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
package Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators;

use 5.010001;
use strict;
use warnings;
use Readonly;

use Perl::Critic::Utils qw{ :severities :data_conversion };
use parent 'Perl::Critic::Policy';


#-----------------------------------------------------------------------------

our $VERSION = '1.156';

#-----------------------------------------------------------------------------

Readonly::Hash my %LOW_BOOLEANS  => hashify( qw( not or and ) );
Readonly::Hash my %HIGH_BOOLEANS => hashify( qw( ! || && ||= &&= //=) );

Readonly::Hash my %EXEMPT_TYPES => hashify(
    qw(
        PPI::Statement::Block
        PPI::Statement::Scheduled
        PPI::Statement::Package
        PPI::Statement::Include
        PPI::Statement::Sub
        PPI::Statement::Variable
        PPI::Statement::Compound
        PPI::Statement::Data
        PPI::Statement::End
    )
);

#-----------------------------------------------------------------------------

Readonly::Scalar my $DESC => q{Mixed high and low-precedence booleans};
Readonly::Scalar my $EXPL => [ 70 ];

#-----------------------------------------------------------------------------

sub supported_parameters { return ()                  }
sub default_severity     { return $SEVERITY_HIGH      }
sub default_themes       { return qw( core bugs pbp certrec ) }
sub applies_to           { return 'PPI::Statement'    }

#-----------------------------------------------------------------------------

sub violates {

    my ( $self, $elem, undef ) = @_;

    # PPI::Statement is the ancestor of several types of PPI elements.
    # But for this policy, we only want the ones that generally
    # represent a single statement or expression.  There might be
    # better ways to do this, such as scanning for a semi-colon or
    # some other marker.

    return if exists $EXEMPT_TYPES{ ref $elem };

    if (    $elem->find_first(\&_low_boolean)
         && $elem->find_first(\&_high_boolean) ) {

        return $self->violation( $DESC, $EXPL, $elem );
    }
    return;    #ok!
}

#-----------------------------------------------------------------------------

sub _low_boolean {
    my (undef, $elem) = @_;
    return if $elem->isa('PPI::Statement');

    return
        $elem->isa('PPI::Token::Operator')
        && exists $LOW_BOOLEANS{$elem};
}

#-----------------------------------------------------------------------------

sub _high_boolean {
    my (undef, $elem) = @_;
    return if $elem->isa('PPI::Statement');

    return
        $elem->isa('PPI::Token::Operator')
        && exists $HIGH_BOOLEANS{$elem};
}

1;

__END__

#-----------------------------------------------------------------------------

=pod

=head1 NAME

Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators - Write C< !$foo && $bar || $baz > instead of C< not $foo && $bar or $baz>.

=head1 AFFILIATION

This Policy is part of the core L<Perl::Critic|Perl::Critic>
distribution.


=head1 DESCRIPTION

Conway advises against combining the low-precedence booleans ( C<and
or not> ) with the high-precedence boolean operators ( C<&& || !> ) in
the same expression.  Unless you fully understand the differences
between the high and low-precedence operators, it is easy to
misinterpret expressions that use both.  And even if you do understand
them, it is not always clear if the author actually intended it.

    next if not $foo || $bar;  #not ok
    next if !$foo || $bar;     #ok
    next if !( $foo || $bar ); #ok


=head1 CONFIGURATION

This Policy is not configurable except for the standard options.


=head1 AUTHOR

Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>

=head1 COPYRIGHT

Copyright (c) 2005-2023 Imaginative Software Systems

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 :