File Coverage

blib/lib/Perl/Critic/Policy/ControlStructures/ProhibitPostfixControls.pm
Criterion Covered Total %
statement 40 40 100.0
branch 16 26 61.5
condition 2 3 66.6
subroutine 11 11 100.0
pod 4 5 80.0
total 73 85 85.8


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls;
2              
3 40     40   27348 use 5.010001;
  40         217  
4 40     40   261 use strict;
  40         135  
  40         886  
5 40     40   237 use warnings;
  40         166  
  40         1026  
6 40     40   240 use Readonly;
  40         113  
  40         2240  
7              
8 40     40   304 use Perl::Critic::Utils qw{ :characters :severities :data_conversion :classification };
  40         142  
  40         2596  
9 40     40   22138 use parent 'Perl::Critic::Policy';
  40         132  
  40         324  
10              
11             our $VERSION = '1.150';
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 91     91 0 2188 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 92     92 1 338 sub default_severity { return $SEVERITY_LOW }
47 84     84 1 330 sub default_themes { return qw(core pbp cosmetic) }
48 30     30 1 95 sub applies_to { return 'PPI::Token::Word' }
49              
50             #-----------------------------------------------------------------------------
51              
52             sub violates {
53 329     329 1 538 my ( $self, $elem, undef ) = @_;
54              
55 329         545 my $expl = $PAGES_OF{$elem};
56 329 100       3446 return if not $expl;
57              
58 29 50       102 return if is_hash_key($elem);
59 29 50       122 return if is_method_call($elem);
60 29 50       190 return if is_subroutine_name($elem);
61 29 50       561 return if is_included_module_name($elem);
62 29 50       85 return if is_package_declaration($elem);
63              
64             # Skip controls that are allowed
65 29 50       106 return if exists $self->{_allow}->{ $elem->content() };
66              
67             # Skip Compound variety (these are good)
68 29         132 my $stmnt = $elem->statement();
69 29 50       342 return if not $stmnt;
70 29 100       120 return if $stmnt->isa('PPI::Statement::Compound');
71 19 50       58 return if $stmnt->isa('PPI::Statement::When');
72              
73             # Handle special cases
74 19         44 my $content = $elem->content();
75 19 100 66     108 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 3 50       17 return if $stmnt->isa('PPI::Statement::Break');
79 3 50       15 return if defined $self->{_flowcontrol}{ $stmnt->schild(0)->content() };
80             }
81              
82             # If we get here, it must be postfix.
83 19         101 my $desc = qq{Postfix control "$content" used};
84 19         65 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 :