File Coverage

blib/lib/Perl/Critic/Policy/CodeLayout/ProhibitFatCommaNewline.pm
Criterion Covered Total %
statement 54 58 93.1
branch 14 18 77.7
condition 2 4 50.0
subroutine 14 14 100.0
pod 1 1 100.0
total 85 95 89.4


line stmt bran cond sub pod time code
1             # Copyright 2009, 2010, 2011, 2013, 2014, 2015, 2016, 2017, 2019, 2021 Kevin Ryde
2              
3             # Perl-Critic-Pulp is free software; you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by the
5             # Free Software Foundation; either version 3, or (at your option) any later
6             # version.
7             #
8             # Perl-Critic-Pulp is distributed in the hope that it will be useful, but
9             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11             # for more details.
12             #
13             # You should have received a copy of the GNU General Public License along
14             # with Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
15              
16              
17             # use strict;
18             # $, = "\n";
19             # sub foo {
20             # return 123;
21             # }
22             # sub x {
23             # my %h = (-foo
24             # => 'abc');
25             # print %h
26             # }
27             # x();
28              
29              
30             package Perl::Critic::Policy::CodeLayout::ProhibitFatCommaNewline;
31 40     40   32740 use 5.006;
  40         170  
32 40     40   232 use strict;
  40         93  
  40         967  
33 40     40   221 use warnings;
  40         111  
  40         1116  
34 40     40   709 use version (); # but don't import qv()
  40         2087  
  40         867  
35 40     40   896 use Perl::Critic::Utils;
  40         136752  
  40         814  
36              
37             # 1.084 for Perl::Critic::Document highest_explicit_perl_version()
38 40     40   37765 use Perl::Critic::Policy 1.084;
  40         49964  
  40         1278  
39 40     40   237 use base 'Perl::Critic::Policy';
  40         122  
  40         5624  
40              
41             our $VERSION = 99;
42              
43             # uncomment this to run the ### lines
44             # use Smart::Comments;
45              
46              
47 40     40   310 use constant supported_parameters => ();
  40         94  
  40         2771  
48 40     40   272 use constant default_severity => $Perl::Critic::Utils::SEVERITY_MEDIUM;
  40         110  
  40         2495  
49 40     40   275 use constant default_themes => qw(pulp bugs);
  40         88  
  40         2579  
50 40     40   283 use constant applies_to => ('PPI::Token::Operator');
  40         115  
  40         17941  
51              
52             my $v5008 = version->new('5.008');
53              
54             sub violates {
55 14     14 1 564377 my ($self, $elem, $document) = @_;
56              
57 14 100       55 $elem->content eq '=>'
58             or return; # some other operator
59              
60 7   50     71 my $prev = $elem->sprevious_sibling || return;
61 7 50       335 if (! $prev->isa('PPI::Token::Word')) {
62             ### previous not a word, so => acts as a plain comma, ok ...
63 0         0 return;
64             }
65 7 50       37 if (! _elems_any_newline_between ($prev, $elem)) {
66             ### no newline before =>, ok ...
67 0         0 return;
68             }
69              
70 7         30 my $word = $prev->content;
71              
72             # A builtin is never quoted by newline fat comma.
73             # PPI 1.213 gives a word "-print" where it should be a negate of a
74             # print(), so check the word "sans dash".
75 7 100       42 if (Perl::Critic::Utils::is_perl_builtin(_sans_dash($word))) {
76 3         128 return $self->violation
77             ("Fat comma after newline doesn't quote Perl builtin \"$word\"",
78             '',
79             $elem);
80             }
81              
82             # In 5.8 up words are quoted by newline fat comma, so ok.
83 4 100       153 if (defined (my $doc_version = $document->highest_explicit_perl_version)) {
84 2 100       852 if ($doc_version >= $v5008) {
85 1         6 return;
86             }
87             }
88              
89             # In 5.6 and earlier newline fat comma doesn't quote.
90 3         522 return $self->violation
91             ("Fat comma after newline doesn't quote preceding bareword \"$word\"",
92             '',
93             $elem);
94             }
95              
96             # return $str stripped of a leading "-", if it has one
97             sub _sans_dash {
98 7     7   22 my ($str) = @_;
99 7         32 $str =~ s/^-//;
100 7         41 return $str;
101             }
102              
103             # $from and $to are PPI::Element
104             # Return true if there's a "\n" newline anywhere in between those elements,
105             # not including either $from or $to themselves.
106             sub _elems_any_newline_between {
107 7     7   26 my ($from, $to) = @_;
108 7 50       38 if ($from == $to) { return 0; }
  0         0  
109 7         66 for (;;) {
110 9   50     65 $from = $from->next_sibling || return 0;
111 9 50       227 if ($from == $to) { return 0; }
  0         0  
112 9 100       70 if ($from =~ /\n/) { return 1; }
  7         70  
113             }
114             }
115              
116             1;
117             __END__
118              
119             =for stopwords Ryde bareword builtin Builtin builtins Builtins eg parens
120              
121             =head1 NAME
122              
123             Perl::Critic::Policy::CodeLayout::ProhibitFatCommaNewline - keep a fat comma on the same line as its quoted word
124              
125             =head1 DESCRIPTION
126              
127             This policy is part of the L<C<Perl::Critic::Pulp>|Perl::Critic::Pulp>
128             add-on. It reports a newline between a fat comma and preceding bareword for
129             Perl builtins,
130              
131             my %h = (caller # bad, builtin called as a function
132             => 'abc');
133              
134             And for all words when targeting Perl 5.6 and earlier,
135              
136             use 5.006;
137             my %h = (foo # bad, all words in perl 5.6 and earlier
138             => 'def');
139              
140             When there's a newline between the word and the fat comma like this the word
141             executes as a function call (builtins always, and also user defined in Perl
142             5.6 and earlier), giving its return value rather than a word string.
143              
144             Such a return value is probably not what was intended and on that basis this
145             policy is under the "bugs" theme and medium severity (see
146             L<Perl::Critic/POLICY THEMES>).
147              
148             =head2 Builtins
149              
150             Perl builtin functions with a newline always execute and give their return
151             value rather than a the quoted word.
152              
153             my %h = (print # bad, builtin print() executes
154             => "abc");
155             # %h is key "1" value "abc"
156              
157             The builtin is called with no arguments and that might provoke a warning
158             from some, but others like C<print> will quietly run.
159              
160             Dashed builtin names such as C<-print> are also function calls, with a
161             negate operator.
162              
163             my %h = (-print # bad, print() call and negate
164             => "123");
165             # h is key "-1" value "123"
166              
167             For the purposes of this policy the builtins are C<is_perl_builtin()> from
168             L<Perl::Critic::Utils>. It's possible this is more builtins than the
169             particular Perl in use, but guarding against all will help if going to a
170             newer Perl in the future.
171              
172             =head2 Non-Builtins
173              
174             In Perl 5.6 and earlier all words C<foo> execute as a function call when
175             there's a newline before the fat comma.
176              
177             sub foo {
178             return 123
179             }
180             my %h = (foo
181             => "def");
182             # in Perl 5.6 and earlier %h is key "123" value "def"
183              
184             Under C<use strict> an error is thrown if no such function, in the usual
185             way. A word builtin is a function call if it exists (with a warning about
186             being interpreted that way), or a bareword if not.
187              
188             This policy prohibits all words with newline before fat comma when targeting
189             Perl 5.6 or earlier. This means either an explicit C<use 5.006> or smaller,
190             or no such minimum C<use> at all.
191              
192             One subtle way an executing word with newline before fat comma can go
193             undetected (in 5.6 and earlier still) is an accidental redefinition of a
194             constant,
195              
196             use constant FOO => "blah";
197             use constant FOO
198             => "some value";
199             # makes a constant subr called blah (in Perl 5.6)
200              
201             C<constant.pm> might reject some return values from C<FOO()>, eg. a number,
202             but a string like "blah" here quietly expands and creates a constant
203             C<blah()>.
204              
205             The difference between Perl 5.6 and later Perl is that in 5.6 the parser
206             only looked as far as a newline for a possible quoting C<=E<gt>> fat comma.
207             In Perl 5.8 and later for non-builtins the lookahead continues beyond any
208             newlines and comments. For Perl builtins the behaviour is the same, in all
209             versions the lookahead stops at the newline.
210              
211             =head2 Avoiding Problems
212              
213             Putting the fat comma on the same line as the word ensures it quotes in all
214             cases.
215              
216             my %h = (-print => # ok, fat comma on same line quotes
217             "123");
218              
219             If for layout purposes you do want a newline then the suggestion is to give
220             a string or perhaps a parenthesized expression since that doesn't rely on
221             the C<=E<gt>> fat comma quoting. A fat comma can still emphasize a
222             key/value pair.
223              
224             my %h = ('print' # ok, string
225             =>
226             123);
227              
228             Alternately if instead a function call is really what's intended (builtin or
229             otherwise) then parens can be used in the normal way to ensure it's a call
230             (as per L<perltrap> the rule being "if it looks like a function, it is a
231             function").
232              
233             my %h = (foo() # ok, function call
234             =>
235             123);
236              
237             =head2 Disabling
238              
239             As always if you don't care about this then you can disable
240             C<ProhibitFatCommaNewline> from your F<.perlcriticrc> in the usual
241             way (see L<Perl::Critic/CONFIGURATION>),
242              
243             [-CodeLayout::ProhibitFatCommaNewline]
244              
245             =head1 SEE ALSO
246              
247             L<Perl::Critic::Pulp>, L<Perl::Critic>, L<perlop>
248              
249             =head1 HOME PAGE
250              
251             L<http://user42.tuxfamily.org/perl-critic-pulp/index.html>
252              
253             =head1 COPYRIGHT
254              
255             Copyright 2011, 2013, 2014, 2015, 2016, 2017, 2019, 2021 Kevin Ryde
256              
257             Perl-Critic-Pulp is free software; you can redistribute it and/or modify it
258             under the terms of the GNU General Public License as published by the Free
259             Software Foundation; either version 3, or (at your option) any later
260             version.
261              
262             Perl-Critic-Pulp is distributed in the hope that it will be useful, but
263             WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
264             or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
265             more details.
266              
267             You should have received a copy of the GNU General Public License along with
268             Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
269              
270             =cut