1 ##############################################################################
2 # $URL: http://perlcritic.tigris.org/svn/perlcritic/trunk/Perl-Critic/lib/Perl/Critic/Policy/ControlStructures/ProhibitPostfixControls.pm $
3 # $Date: 2008-07-03 10:19:10 -0500 (Thu, 03 Jul 2008) $
6 ##############################################################################
8 package Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls;
15 use Perl::Critic::Utils qw{ :characters :severities :data_conversion :classification };
16 use base 'Perl::Critic::Policy';
18 our $VERSION = '1.088';
20 #-----------------------------------------------------------------------------
22 Readonly::Hash my %PAGES_OF => (
31 # These functions can have postfix 'if'.
32 my @DEFAULT_FLOW_CONTROL = qw( warn die carp croak cluck confess goto exit );
34 #-----------------------------------------------------------------------------
36 sub supported_parameters {
40 description => 'The permitted postfix controls.',
41 default_string => $EMPTY,
42 behavior => 'enumeration',
43 enumeration_values => [ sort keys %PAGES_OF ],
44 enumeration_allow_multiple_values => 1,
47 name => 'flowcontrol',
48 description => 'The exempt flow control functions.',
49 default_string => 'carp cluck confess croak die exit goto warn',
50 behavior => 'string list',
55 sub default_severity { return $SEVERITY_LOW }
56 sub default_themes { return qw(core pbp cosmetic) }
57 sub applies_to { return 'PPI::Token::Word' }
59 #-----------------------------------------------------------------------------
62 my ( $self, $elem, undef ) = @_;
64 my $expl = $PAGES_OF{$elem};
67 return if is_hash_key($elem);
68 return if is_method_call($elem);
69 return if is_subroutine_name($elem);
70 return if is_included_module_name($elem);
71 return if is_package_declaration($elem);
73 # Skip controls that are allowed
74 return if exists $self->{_allow}->{$elem};
76 # Skip Compound variety (these are good)
77 my $stmnt = $elem->statement();
79 return if $stmnt->isa('PPI::Statement::Compound');
81 # Handle special cases
82 if ( $elem eq 'if' ) {
83 # Postfix 'if' allowed with loop breaks, or other
84 # flow-controls like 'die', 'warn', and 'croak'
85 return if $stmnt->isa('PPI::Statement::Break');
86 return if defined $self->{_flowcontrol}{ $stmnt->schild(0) };
89 # If we get here, it must be postfix.
90 my $desc = qq{Postfix control "$elem" used};
91 return $self->violation( $desc, $expl, $elem );
100 =for stopwords flowcontrol
104 Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls - Write C<if($condition){ do_something() }> instead of C<do_something() if $condition>.
108 This Policy is part of the core L<Perl::Critic> distribution.
113 Conway discourages using postfix control structures (C<if>, C<for>,
114 C<unless>, C<until>, C<while>) because they hide control flow. The
115 C<unless> and C<until> controls are particularly evil because they
116 lead to double-negatives that are hard to comprehend. The only
117 tolerable usage of a postfix C<if> is when it follows a loop break
118 such as C<last>, C<next>, C<redo>, or C<continue>.
120 do_something() if $condition; #not ok
121 if($condition){ do_something() } #ok
123 do_something() while $condition; #not ok
124 while($condition){ do_something() } #ok
126 do_something() unless $condition; #not ok
127 do_something() unless ! $condition; #really bad
128 if(! $condition){ do_something() } #ok
130 do_something() until $condition; #not ok
131 do_something() until ! $condition; #really bad
132 while(! $condition){ do_something() } #ok
134 do_something($_) for @list; #not ok
138 next if $condition; #ok
139 last LOOP if $other_condition; #also ok
144 A set of constructs to be ignored by this policy can specified by
145 giving a value for 'allow' of a string of space-delimited keywords:
146 C<if>, C<for>, C<unless>, C<until>, and/or C<while>. An example of
147 specifying allowed flow-control structures in a F<.perlcriticrc> file:
149 [ControlStructures::ProhibitPostfixControls]
152 By default, all postfix control keywords are prohibited.
154 The set of flow-control functions that are exempt from the restriction
155 can also be configured with the 'flowcontrol' directive in your
156 F<.perlcriticrc> file:
158 [ControlStructures::ProhibitPostfixControls]
159 flowcontrol = warn die carp croak cluck confess goto exit
163 The C<die>, C<croak>, and C<confess> functions are frequently used as
164 flow-controls just like C<next> or C<last>. So this Policy does
165 permit you to use a postfix C<if> when the statement begins with one
166 of those functions. It is also pretty common to use C<warn>, C<carp>,
167 and C<cluck> with a postfix C<if>, so those are allowed too.
172 Jeffrey Ryan Thalhammer <thaljef@cpan.org>
176 Copyright (c) 2005-2008 Jeffrey Ryan Thalhammer. All rights reserved.
178 This program is free software; you can redistribute it and/or modify
179 it under the same terms as Perl itself. The full text of this license
180 can be found in the LICENSE file included with this module.
186 # cperl-indent-level: 4
188 # indent-tabs-mode: nil
189 # c-indentation-style: bsd
191 # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :