File Coverage

blib/lib/Perl/Critic/Policy/ControlStructures/ProhibitPostfixControls.pm
Criterion Covered Total %
statement 40 40 100.0
branch 21 26 80.7
condition 3 3 100.0
subroutine 11 11 100.0
pod 4 5 80.0
total 79 85 92.9


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls;
2              
3 40     40   28252 use 5.010001;
  40         198  
4 40     40   269 use strict;
  40         128  
  40         993  
5 40     40   230 use warnings;
  40         114  
  40         1105  
6 40     40   259 use Readonly;
  40         139  
  40         2494  
7              
8 40     40   323 use Perl::Critic::Utils qw{ :characters :severities :data_conversion :classification };
  40         154  
  40         2217  
9 40     40   22168 use parent 'Perl::Critic::Policy';
  40         144  
  40         280  
10              
11             our $VERSION = '1.146';
12              
13             #-----------------------------------------------------------------------------
14              
15             Readonly::Hash my %PAGES_OF => (
16             if => [ 93, 94 ],
17             unless => [ 96, 97 ],
18             until => [ 96, 97 ],
19             for => [ 96 ],
20             foreach => [ 96 ],
21             while => [ 96 ],
22             when => q<Similar to "if", postfix "when" should only be used with flow-control>,
23             );
24              
25             #-----------------------------------------------------------------------------
26              
27             sub supported_parameters {
28             return (
29             {
30 103     103 0 2279 name => 'allow',
31             description => 'The permitted postfix controls.',
32             default_string => $EMPTY,
33             behavior => 'enumeration',
34             enumeration_values => [ sort keys %PAGES_OF ],
35             enumeration_allow_multiple_values => 1,
36             },
37             {
38             name => 'flowcontrol',
39             description => 'The exempt flow control functions.',
40             default_string => 'carp cluck confess croak die exit goto warn',
41             behavior => 'string list',
42             },
43             );
44             }
45              
46 109     109 1 521 sub default_severity { return $SEVERITY_LOW }
47 84     84 1 385 sub default_themes { return qw(core pbp cosmetic) }
48 42     42 1 129 sub applies_to { return 'PPI::Token::Word' }
49              
50             #-----------------------------------------------------------------------------
51              
52             sub violates {
53 511     511 1 1015 my ( $self, $elem, undef ) = @_;
54              
55 511         1085 my $expl = $PAGES_OF{$elem};
56 511 100       6577 return if not $expl;
57              
58 120 100       372 return if is_hash_key($elem);
59 106 50       355 return if is_method_call($elem);
60 106 50       566 return if is_subroutine_name($elem);
61 106 50       323 return if is_included_module_name($elem);
62 106 50       304 return if is_package_declaration($elem);
63              
64             # Skip controls that are allowed
65 106 100       449 return if exists $self->{_allow}->{ $elem->content() };
66              
67             # Skip Compound variety (these are good)
68 94         583 my $stmnt = $elem->statement();
69 94 50       1271 return if not $stmnt;
70 94 100       363 return if $stmnt->isa('PPI::Statement::Compound');
71 78 100       293 return if $stmnt->isa('PPI::Statement::When');
72              
73             # Handle special cases
74 77         186 my $content = $elem->content();
75 77 100 100     435 if ($content eq 'if' or $content eq 'when') {
76             # Postfix 'if' allowed with loop breaks, or other
77             # flow-controls like 'die', 'warn', and 'croak'
78 55 100       213 return if $stmnt->isa('PPI::Statement::Break');
79 45 100       154 return if defined $self->{_flowcontrol}{ $stmnt->schild(0)->content() };
80             }
81              
82             # If we get here, it must be postfix.
83 36         332 my $desc = qq{Postfix control "$content" used};
84 36         155 return $self->violation($desc, $expl, $elem);
85             }
86              
87             1;
88              
89             __END__
90              
91             =pod
92              
93             =for stopwords flowcontrol brian foy
94              
95             =head1 NAME
96              
97             Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls - Write C<if($condition){ do_something() }> instead of C<do_something() if $condition>.
98              
99              
100             =head1 AFFILIATION
101              
102             This Policy is part of the core L<Perl::Critic|Perl::Critic>
103             distribution.
104              
105              
106             =head1 DESCRIPTION
107              
108             Conway discourages using postfix control structures (C<if>, C<for>,
109             C<unless>, C<until>, C<when>, C<while>) because they hide control
110             flow. The C<unless> and C<until> controls are particularly evil
111             because they lead to double-negatives that are hard to comprehend.
112             The only tolerable usage of a postfix C<if>/C<when> is when it follows
113             a loop break such as C<last>, C<next>, C<redo>, or C<continue>.
114              
115             do_something() if $condition; # not ok
116             if ($condition) { do_something() } # ok
117              
118             do_something() while $condition; # not ok
119             while ($condition) { do_something() } # ok
120              
121             do_something() unless $condition; # not ok
122             do_something() unless ! $condition; # really bad
123             if (! $condition) { do_something() } # ok
124              
125             do_something() until $condition; # not ok
126             do_something() until ! $condition; # really bad
127             while (! $condition) { do_something() } # ok
128              
129             do_something($_) for @list; # not ok
130              
131             LOOP:
132             for my $n (0..100) {
133             next if $condition; # ok
134             last LOOP if $other_condition; # also ok
135              
136             next when m< 0 \z >xms; # fine too
137             }
138              
139              
140             =head1 CONFIGURATION
141              
142             A set of constructs to be ignored by this policy can specified by
143             giving a value for 'allow' of a string of space-delimited keywords:
144             C<if>, C<for>, C<unless>, C<until>, C<when>, and/or C<while>. An
145             example of specifying allowed flow-control structures in a
146             F<.perlcriticrc> file:
147              
148             [ControlStructures::ProhibitPostfixControls]
149             allow = for if until
150              
151             By default, all postfix control keywords are prohibited.
152              
153             The set of flow-control functions that are exempt from the restriction
154             can also be configured with the 'flowcontrol' directive in your
155             F<.perlcriticrc> file:
156              
157             [ControlStructures::ProhibitPostfixControls]
158             flowcontrol = warn die carp croak cluck confess goto exit
159              
160             This is useful if you're using additional modules that add things like
161             C<assert> or C<throw>.
162              
163              
164             =head1 NOTES
165              
166             The C<die>, C<croak>, and C<confess> functions are frequently used as
167             flow-controls just like C<next> or C<last>. So this Policy does
168             permit you to use a postfix C<if> when the statement begins with one
169             of those functions. It is also pretty common to use C<warn>, C<carp>,
170             and C<cluck> with a postfix C<if>, so those are allowed too.
171              
172             The C<when> keyword was added to the language after Perl Best
173             Practices was written. This policy treats C<when> the same way it
174             does C<if>, i.e. it's allowed after flow-control constructs. Thanks
175             to brian d foy for the
176             L<inspiration|http://www.effectiveperlprogramming.com/blog/543>.
177              
178              
179             =head1 BUGS
180              
181             Look for the C<do {} while> case and change the explanation to point
182             to page 123 when it is found. RT #37905.
183              
184              
185             =head1 AUTHOR
186              
187             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
188              
189              
190             =head1 COPYRIGHT
191              
192             Copyright (c) 2005-2011 Imaginative Software Systems. All rights reserved.
193              
194             This program is free software; you can redistribute it and/or modify
195             it under the same terms as Perl itself. The full text of this license
196             can be found in the LICENSE file included with this module.
197              
198             =cut
199              
200             # Local Variables:
201             # mode: cperl
202             # cperl-indent-level: 4
203             # fill-column: 78
204             # indent-tabs-mode: nil
205             # c-indentation-style: bsd
206             # End:
207             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :