The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

##############################################################################
# $Date: 2010-12-14 20:31:40 -0600 (Tue, 14 Dec 2010) $
# $Author: clonezone $
# $Revision: 4011 $
##############################################################################
use 5.006001;
use strict;
use Perl::Critic::Utils qw{ :severities :data_conversion };
#-----------------------------------------------------------------------------
our $VERSION = '1.112_001';
#-----------------------------------------------------------------------------
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 ) }
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');
$elem->isa('PPI::Token::Operator') || return 0;
return exists $LOW_BOOLEANS{$elem};
}
#-----------------------------------------------------------------------------
sub _high_boolean {
my (undef, $elem) = @_;
return if $elem->isa('PPI::Statement');
$elem->isa('PPI::Token::Operator') || return 0;
return 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-2010 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 :