File Coverage

blib/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitArrayAssignAref.pm
Criterion Covered Total %
statement 43 43 100.0
branch 14 16 87.5
condition 7 10 70.0
subroutine 11 11 100.0
pod 1 1 100.0
total 76 81 93.8


line stmt bran cond sub pod time code
1             # Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019 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             # eg.
18             # perlcritic -s ProhibitArrayAssignAref /usr/lib/perl5/Template/Test.pm
19              
20              
21             package Perl::Critic::Policy::ValuesAndExpressions::ProhibitArrayAssignAref;
22 40     40   58615 use 5.006;
  40         163  
23 40     40   250 use strict;
  40         101  
  40         946  
24 40     40   214 use warnings;
  40         111  
  40         1324  
25              
26 40     40   240 use base 'Perl::Critic::Policy';
  40         91  
  40         4961  
27 40     40   148794 use Perl::Critic::Utils;
  40         106  
  40         856  
28 40     40   52643 use Perl::Critic::Pulp;
  40         151  
  40         1874  
29              
30             # uncomment this to run the ### lines
31             #use Smart::Comments;
32              
33             our $VERSION = 98;
34              
35 40     40   270 use constant supported_parameters => ();
  40         91  
  40         2553  
36 40     40   329 use constant default_severity => $Perl::Critic::Utils::SEVERITY_MEDIUM;
  40         95  
  40         2362  
37 40     40   287 use constant default_themes => qw(pulp bugs);
  40         147  
  40         2230  
38 40         10241 use constant applies_to => ('PPI::Token::Symbol',
39 40     40   275 'PPI::Token::Cast');
  40         130  
40              
41             sub violates {
42 24     24 1 509353 my ($self, $elem, $document) = @_;
43              
44 24 100       120 ($elem->isa('PPI::Token::Cast') ? $elem->content : $elem->raw_type)
    100          
45             eq '@' or return;
46             ### ProhibitArrayAssignAref: $elem->content
47              
48 18         114 my $thing = 'Array';
49 18         28 for (;;) {
50 39   50     102 $elem = $elem->snext_sibling || return;
51 39 100       886 last if $elem->isa('PPI::Token::Operator');
52             ### skip: ref $elem
53              
54             # @foo[1,2] gives the [1,2] as a PPI::Structure::Subscript
55             # @{foo()}[1,2] gives the [1,2] as a PPI::Structure::Constructor
56             # the latter is probably wrong (as of PPI 1.215)
57 21 100 100     96 if ($elem->isa('PPI::Structure::Subscript')
58             || $elem->isa('PPI::Structure::Constructor')) {
59 11 100       30 if ($elem->start eq '[') {
    50          
60 5         80 $thing = 'Array slice';
61             } elsif ($elem->start eq '{') {
62 6         180 $thing = 'Hash slice';
63             }
64             }
65             }
66             ### $thing
67             ### operator: $elem->content
68 18 50       40 $elem eq '=' or return;
69              
70 18   50     228 $elem = $elem->snext_sibling || return;
71 18 100 66     389 ($elem->isa('PPI::Structure::Constructor') && $elem->start eq '[')
72             or return;
73              
74 11         176 return $self->violation
75             ("$thing assigned a [] arrayref, should it be a () list ?",
76             '', $elem);
77             }
78              
79             1;
80             __END__
81              
82             =for stopwords Ryde arrayref parens Derefs Dereferences
83              
84             =head1 NAME
85              
86             Perl::Critic::Policy::ValuesAndExpressions::ProhibitArrayAssignAref - don't assign an anonymous arrayref to an array
87              
88             =head1 DESCRIPTION
89              
90             This policy is part of the L<C<Perl::Critic::Pulp>|Perl::Critic::Pulp>
91             add-on. It asks you not to assign an anonymous arrayref to an array
92              
93             @array = [ 1, 2, 3 ]; # bad
94              
95             The idea is that it's rather unclear whether an arrayref is intended, or
96             might have meant to be a list like
97              
98             @array = ( 1, 2, 3 );
99              
100             This policy is under the "bugs" theme (see L<Perl::Critic/POLICY THEMES>)
101             for the chance C<[]> is a mistake, and since even if it's correct it will
102             likely make anyone reading it wonder.
103              
104             A single arrayref can still be assigned to an array, but with parens to make
105             it clear,
106              
107             @array = ( [1,2,3] ); # ok
108              
109             Dereferences or array and hash slices (see L<perldata/Slices>) are
110             recognised as an array target and treated similarly,
111              
112             @$ref = [1,2,3]; # bad assign to deref
113             @{$ref} = [1,2,3]; # bad assign to deref
114             @x[1,2,3] = ['a','b','c']; # bad assign to array slice
115             @x{'a','b'} = [1,2]; # bad assign to hash slice
116              
117             =head2 List Assignment Parens
118              
119             This policy is not a blanket requirement for C<()> parens on array
120             assignments. It's normal and unambiguous to have a function call or C<grep>
121             etc without parens.
122              
123             @array = foo(); # ok
124             @array = grep {/\.txt$/} @array; # ok
125              
126             The only likely problem from lack of parens in such cases is that the C<,>
127             comma operator has lower precedence than C<=> (see L<perlop>), so something
128             like
129              
130             @array = 1,2,3; # oops, not a list
131              
132             means
133              
134             @array = (1);
135             2;
136             3;
137              
138             Normally the remaining literals in void context provoke a warning from Perl
139             itself.
140              
141             An intentional single element assignment is quite common as a statement, for
142             instance
143              
144             @ISA = 'My::Parent::Class'; # ok
145              
146             And for reference the range operator precedence is high enough,
147              
148             @array = 1..10; # ok
149              
150             But of course parens are needed if concatenating some disjoint ranges with
151             the comma operator,
152              
153             @array = (1..5, 10..15); # parens needed
154              
155             The C<qw> form gives a list too
156              
157             @array = qw(a b c); # ok
158              
159             =head1 SEE ALSO
160              
161             L<Perl::Critic>,
162             L<Perl::Critic::Pulp>
163              
164             =head1 HOME PAGE
165              
166             http://user42.tuxfamily.org/perl-critic-pulp/index.html
167              
168             =head1 COPYRIGHT
169              
170             Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019 Kevin Ryde
171              
172             Perl-Critic-Pulp is free software; you can redistribute it and/or modify it
173             under the terms of the GNU General Public License as published by the Free
174             Software Foundation; either version 3, or (at your option) any later
175             version.
176              
177             Perl-Critic-Pulp is distributed in the hope that it will be useful, but
178             WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
179             or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
180             more details.
181              
182             You should have received a copy of the GNU General Public License along with
183             Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses>.
184              
185             =cut