File Coverage

blib/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMixedBooleanOperators.pm
Criterion Covered Total %
statement 28 32 87.5
branch 4 8 50.0
condition 3 9 33.3
subroutine 12 13 92.3
pod 4 5 80.0
total 51 67 76.1


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators;
2              
3 40     40   26392 use 5.010001;
  40         150  
4 40     40   225 use strict;
  40         94  
  40         864  
5 40     40   219 use warnings;
  40         124  
  40         979  
6 40     40   207 use Readonly;
  40         100  
  40         2564  
7              
8 40     40   355 use Perl::Critic::Utils qw{ :severities :data_conversion };
  40         103  
  40         2020  
9 40     40   7071 use parent 'Perl::Critic::Policy';
  40         108  
  40         231  
10              
11              
12             #-----------------------------------------------------------------------------
13              
14             our $VERSION = '1.150';
15              
16             #-----------------------------------------------------------------------------
17              
18             Readonly::Hash my %LOW_BOOLEANS => hashify( qw( not or and ) );
19             Readonly::Hash my %HIGH_BOOLEANS => hashify( qw( ! || && ||= &&= //=) );
20              
21             Readonly::Hash my %EXEMPT_TYPES => hashify(
22             qw(
23             PPI::Statement::Block
24             PPI::Statement::Scheduled
25             PPI::Statement::Package
26             PPI::Statement::Include
27             PPI::Statement::Sub
28             PPI::Statement::Variable
29             PPI::Statement::Compound
30             PPI::Statement::Data
31             PPI::Statement::End
32             )
33             );
34              
35             #-----------------------------------------------------------------------------
36              
37             Readonly::Scalar my $DESC => q{Mixed high and low-precedence booleans};
38             Readonly::Scalar my $EXPL => [ 70 ];
39              
40             #-----------------------------------------------------------------------------
41              
42 89     89 0 1670 sub supported_parameters { return () }
43 74     74 1 323 sub default_severity { return $SEVERITY_HIGH }
44 92     92 1 379 sub default_themes { return qw( core bugs pbp certrec ) }
45 32     32 1 114 sub applies_to { return 'PPI::Statement' }
46              
47             #-----------------------------------------------------------------------------
48              
49             sub violates {
50              
51 294     294 1 506 my ( $self, $elem, undef ) = @_;
52              
53             # PPI::Statement is the ancestor of several types of PPI elements.
54             # But for this policy, we only want the ones that generally
55             # represent a single statement or expression. There might be
56             # better ways to do this, such as scanning for a semi-colon or
57             # some other marker.
58              
59 294 100       772 return if exists $EXEMPT_TYPES{ ref $elem };
60              
61 97 50 33     785 if ( $elem->find_first(\&_low_boolean)
62             && $elem->find_first(\&_high_boolean) ) {
63              
64 0         0 return $self->violation( $DESC, $EXPL, $elem );
65             }
66 97         1086 return; #ok!
67             }
68              
69             #-----------------------------------------------------------------------------
70              
71             sub _low_boolean {
72 521     521   5480 my (undef, $elem) = @_;
73 521 50       1429 return if $elem->isa('PPI::Statement');
74              
75             return
76             $elem->isa('PPI::Token::Operator')
77 521   66     1741 && exists $LOW_BOOLEANS{$elem};
78             }
79              
80             #-----------------------------------------------------------------------------
81              
82             sub _high_boolean {
83 0     0     my (undef, $elem) = @_;
84 0 0         return if $elem->isa('PPI::Statement');
85              
86             return
87             $elem->isa('PPI::Token::Operator')
88 0   0       && exists $HIGH_BOOLEANS{$elem};
89             }
90              
91             1;
92              
93             __END__
94              
95             #-----------------------------------------------------------------------------
96              
97             =pod
98              
99             =head1 NAME
100              
101             Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators - Write C< !$foo && $bar || $baz > instead of C< not $foo && $bar or $baz>.
102              
103             =head1 AFFILIATION
104              
105             This Policy is part of the core L<Perl::Critic|Perl::Critic>
106             distribution.
107              
108              
109             =head1 DESCRIPTION
110              
111             Conway advises against combining the low-precedence booleans ( C<and
112             or not> ) with the high-precedence boolean operators ( C<&& || !> ) in
113             the same expression. Unless you fully understand the differences
114             between the high and low-precedence operators, it is easy to
115             misinterpret expressions that use both. And even if you do understand
116             them, it is not always clear if the author actually intended it.
117              
118             next if not $foo || $bar; #not ok
119             next if !$foo || $bar; #ok
120             next if !( $foo || $bar ); #ok
121              
122              
123             =head1 CONFIGURATION
124              
125             This Policy is not configurable except for the standard options.
126              
127              
128             =head1 AUTHOR
129              
130             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
131              
132             =head1 COPYRIGHT
133              
134             Copyright (c) 2005-2023 Imaginative Software Systems
135              
136             This program is free software; you can redistribute it and/or modify
137             it under the same terms as Perl itself. The full text of this license
138             can be found in the LICENSE file included with this module.
139              
140             =cut
141              
142             # Local Variables:
143             # mode: cperl
144             # cperl-indent-level: 4
145             # fill-column: 78
146             # indent-tabs-mode: nil
147             # c-indentation-style: bsd
148             # End:
149             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :