File Coverage

blib/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMixedBooleanOperators.pm
Criterion Covered Total %
statement 34 34 100.0
branch 12 12 100.0
condition 3 3 100.0
subroutine 13 13 100.0
pod 4 5 80.0
total 66 67 98.5


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators;
2              
3 40     40   27059 use 5.010001;
  40         175  
4 40     40   223 use strict;
  40         89  
  40         818  
5 40     40   556 use warnings;
  40         106  
  40         1064  
6 40     40   236 use Readonly;
  40         98  
  40         2081  
7              
8 40     40   346 use Perl::Critic::Utils qw{ :severities :data_conversion };
  40         133  
  40         2244  
9 40     40   6691 use parent 'Perl::Critic::Policy';
  40         99  
  40         233  
10              
11              
12             #-----------------------------------------------------------------------------
13              
14             our $VERSION = '1.146';
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 97     97 0 1655 sub supported_parameters { return () }
43 80     80 1 356 sub default_severity { return $SEVERITY_HIGH }
44 92     92 1 412 sub default_themes { return qw( core bugs pbp certrec ) }
45 40     40 1 137 sub applies_to { return 'PPI::Statement' }
46              
47             #-----------------------------------------------------------------------------
48              
49             sub violates {
50              
51 320     320 1 703 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 320 100       1058 return if exists $EXEMPT_TYPES{ ref $elem };
60              
61 119 100 100     1176 if ( $elem->find_first(\&_low_boolean)
62             && $elem->find_first(\&_high_boolean) ) {
63              
64 6         153 return $self->violation( $DESC, $EXPL, $elem );
65             }
66 113         1564 return; #ok!
67             }
68              
69             #-----------------------------------------------------------------------------
70              
71             sub _low_boolean {
72 686     686   8557 my (undef, $elem) = @_;
73 686 100       2247 return if $elem->isa('PPI::Statement');
74 683 100       2316 $elem->isa('PPI::Token::Operator') || return 0;
75 78         233 return exists $LOW_BOOLEANS{$elem};
76             }
77              
78             #-----------------------------------------------------------------------------
79              
80             sub _high_boolean {
81 105     105   1548 my (undef, $elem) = @_;
82 105 100       373 return if $elem->isa('PPI::Statement');
83 104 100       344 $elem->isa('PPI::Token::Operator') || return 0;
84 20         53 return exists $HIGH_BOOLEANS{$elem};
85             }
86              
87             1;
88              
89             __END__
90              
91             #-----------------------------------------------------------------------------
92              
93             =pod
94              
95             =head1 NAME
96              
97             Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators - Write C< !$foo && $bar || $baz > instead of C< not $foo && $bar or $baz>.
98              
99             =head1 AFFILIATION
100              
101             This Policy is part of the core L<Perl::Critic|Perl::Critic>
102             distribution.
103              
104              
105             =head1 DESCRIPTION
106              
107             Conway advises against combining the low-precedence booleans ( C<and
108             or not> ) with the high-precedence boolean operators ( C<&& || !> ) in
109             the same expression. Unless you fully understand the differences
110             between the high and low-precedence operators, it is easy to
111             misinterpret expressions that use both. And even if you do understand
112             them, it is not always clear if the author actually intended it.
113              
114             next if not $foo || $bar; #not ok
115             next if !$foo || $bar; #ok
116             next if !( $foo || $bar ); #ok
117              
118              
119             =head1 CONFIGURATION
120              
121             This Policy is not configurable except for the standard options.
122              
123              
124             =head1 AUTHOR
125              
126             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
127              
128             =head1 COPYRIGHT
129              
130             Copyright (c) 2005-2011 Imaginative Software Systems. All rights reserved.
131              
132             This program is free software; you can redistribute it and/or modify
133             it under the same terms as Perl itself. The full text of this license
134             can be found in the LICENSE file included with this module.
135              
136             =cut
137              
138             # Local Variables:
139             # mode: cperl
140             # cperl-indent-level: 4
141             # fill-column: 78
142             # indent-tabs-mode: nil
143             # c-indentation-style: bsd
144             # End:
145             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :