File Coverage

blib/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitEmptyCommas.pm
Criterion Covered Total %
statement 42 43 97.6
branch 11 12 91.6
condition 14 18 77.7
subroutine 11 11 100.0
pod 1 1 100.0
total 79 85 92.9


line stmt bran cond sub pod time code
1             # Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019 Kevin Ryde
2              
3             # This file is part of Perl-Critic-Pulp.
4              
5             # Perl-Critic-Pulp is free software; you can redistribute it and/or modify
6             # it under the terms of the GNU General Public License as published by the
7             # Free Software Foundation; either version 3, or (at your option) any later
8             # version.
9             #
10             # Perl-Critic-Pulp is distributed in the hope that it will be useful, but
11             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13             # for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
17              
18              
19             package Perl::Critic::Policy::ValuesAndExpressions::ProhibitEmptyCommas;
20 40     40   31415 use 5.006;
  40         157  
21 40     40   235 use strict;
  40         91  
  40         959  
22 40     40   208 use warnings;
  40         93  
  40         1165  
23 40     40   219 use base 'Perl::Critic::Policy';
  40         93  
  40         6031  
24 40     40   181522 use Perl::Critic::Utils;
  40         101  
  40         746  
25 40     40   35952 use Perl::Critic::Pulp::Utils;
  40         95  
  40         2598  
26              
27             # uncomment this to run the ### lines
28             # use Smart::Comments;
29              
30             our $VERSION = 98;
31              
32              
33 40     40   300 use constant supported_parameters => ();
  40         110  
  40         2754  
34 40     40   253 use constant default_severity => $Perl::Critic::Utils::SEVERITY_LOW;
  40         128  
  40         2320  
35 40     40   256 use constant default_themes => qw(pulp cosmetic);
  40         165  
  40         2369  
36 40     40   272 use constant applies_to => ('PPI::Token::Operator');
  40         94  
  40         10242  
37              
38             sub violates {
39 72     72 1 647775 my ($self, $elem, $document) = @_;
40              
41 72 100       205 $Perl::Critic::Pulp::Utils::COMMA{$elem} or return;
42              
43 54         345 my $prev = $elem->sprevious_sibling;
44 54 100 100     1576 if ($prev && ! ($prev->isa('PPI::Token::Operator')
      100        
45             && $Perl::Critic::Pulp::Utils::COMMA{$prev})) {
46             # have a previous element and it's not a comma operator
47 30         91 return;
48             }
49              
50             # A statement like
51             #
52             # return bless({@_}, $class)
53             #
54             # is parsed by PPI as
55             #
56             # PPI::Structure::List ( ... )
57             # PPI::Statement::Compound
58             # PPI::Structure::Block { ... }
59             # PPI::Statement
60             # PPI::Token::Magic '@_'
61             # PPI::Statement::Expression
62             # PPI::Token::Operator ','
63             # PPI::Token::Symbol '$class'
64             #
65             # so the "{@_}" bit is not an immediate predecessor of the "," operator.
66             # If our $elem has no $prev then also look outwards to see if it's at the
67             # start of an expression which is in a list and there's something
68             # preceding in the list.
69             #
70 24 100       134 if (! $prev) {
71 11         37 my $parent = $elem->parent;
72 11 50 66     98 if ($parent->isa('PPI::Statement::Expression')
      66        
73             && $parent->parent->isa('PPI::Structure::List')
74             && $parent->sprevious_sibling) {
75 0         0 return;
76             }
77             }
78              
79             # An expression like
80             #
81             # [{%a},{}]
82             #
83             # is parsed by PPI 1.215 as
84             #
85             # PPI::Statement
86             # PPI::Structure::Constructor [ ... ]
87             # PPI::Statement::Compound
88             # PPI::Structure::Block { ... }
89             # PPI::Statement
90             # PPI::Token::Symbol '%a'
91             # PPI::Statement
92             # PPI::Token::Operator ','
93             # PPI::Structure::Constructor { ... }
94             #
95             # so the "{%a}" bit is not an immediate predecessor of the "," operator.
96             # If our $elem has no $prev then also look upwards to see if it's at the
97             # start of an statement which is in a constructor and there's something
98             # preceding in that constructor.
99             #
100 24 100       264 if (! $prev) {
101 11         30 my $parent = $elem->parent;
102             ### parent: ref $parent
103 11 100 66     78 if ($parent->isa('PPI::Statement')
      66        
104             && $parent->parent->isa('PPI::Structure::Constructor')
105             && $parent->sprevious_sibling) {
106 5         151 return;
107             }
108             }
109              
110             # $prev is either nothing or a comma operator
111 19         118 return $self->violation ('Empty comma operator',
112             '',
113             $elem);
114             }
115              
116             1;
117             __END__
118              
119             =for stopwords Ryde
120              
121             =head1 NAME
122              
123             Perl::Critic::Policy::ValuesAndExpressions::ProhibitEmptyCommas - disallow empty consecutive commas
124              
125             =head1 DESCRIPTION
126              
127             This policy is part of the L<C<Perl::Critic::Pulp>|Perl::Critic::Pulp>
128             add-on. It prohibits empty comma operators C<,> or C<=E<gt>> meaning either
129             consecutive commas or a comma at the start of a list or expression.
130              
131             print 'foo',,'bar'; # bad
132             @a = (,1,2); # bad
133             foo (x, => 123); # bad
134             a =>=> 456; # bad
135             for (; $i++<10; $i++,,) # bad
136             func (,) # bad
137              
138             Extra commas like this are harmless and simply collapse out when the program
139             runs (see L<perldata/List value constructors>), so this policy is only under
140             the "cosmetic" theme (see L<Perl::Critic/POLICY THEMES>). Usually this sort
141             of thing is just a stray, or leftover from cut and paste, or perhaps some
142             over-enthusiastic column layout. Occasionally it can be something more
143             dubious,
144              
145             # did you mean 1..6 range operator?
146             @a = (1,,6); # bad
147              
148             # this is two args, did you want three?
149             foo (1, , 2); # bad
150              
151             # this is three args, probably you forgot a value
152             bar (abc => , # bad
153             def => 20);
154              
155             A comma at the end of a list or call is allowed. That's quite usual and can
156             be a good thing when cutting and pasting lines (see C<RequireTrailingCommas>
157             to mandate them!).
158              
159             @b = ("foo",
160             "bar", # ok
161             );
162              
163             If you use multiple commas in some systematic way for code layout you can
164             always disable C<ProhibitEmptyCommas> from your F<.perlcriticrc> file in the
165             usual way (see L<Perl::Critic/CONFIGURATION>),
166              
167             [-ValuesAndExpressions::ProhibitEmptyCommas]
168              
169             =head1 SEE ALSO
170              
171             L<Perl::Critic::Pulp>,
172             L<Perl::Critic>,
173             L<Perl::Critic::Policy::CodeLayout::RequireTrailingCommas>,
174             L<Perl::Critic::Policy::ValuesAndExpressions::ProhibitCommaSeparatedStatements>,
175             L<Perl::Critic::Policy::Tics::ProhibitManyArrows>
176              
177             =head1 HOME PAGE
178              
179             http://user42.tuxfamily.org/perl-critic-pulp/index.html
180              
181             =head1 COPYRIGHT
182              
183             Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019 Kevin Ryde
184              
185             Perl-Critic-Pulp is free software; you can redistribute it and/or modify it
186             under the terms of the GNU General Public License as published by the Free
187             Software Foundation; either version 3, or (at your option) any later
188             version.
189              
190             Perl-Critic-Pulp is distributed in the hope that it will be useful, but
191             WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
192             or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
193             more details.
194              
195             You should have received a copy of the GNU General Public License along with
196             Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
197              
198             =cut