File Coverage

blib/lib/Perl/Critic/Policy/Plicease/ProhibitArrayAssignAref.pm
Criterion Covered Total %
statement 40 40 100.0
branch 14 16 87.5
condition 7 10 70.0
subroutine 10 10 100.0
pod 1 1 100.0
total 72 77 93.5


line stmt bran cond sub pod time code
1             # Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2021 Kevin Ryde
2              
3             # Perl-Critic-Policy-Plicease-ProhibitArrayAssignAref 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-Policy-Plicease-ProhibitArrayAssignAref 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-Policy-Plicease-ProhibitArrayAssignAref. 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::Plicease::ProhibitArrayAssignAref;
22              
23 2     2   1100035 use 5.006;
  2         8  
24 2     2   11 use strict;
  2         5  
  2         80  
25 2     2   11 use warnings;
  2         5  
  2         143  
26 2     2   14 use base 'Perl::Critic::Policy';
  2         4  
  2         1417  
27 2     2   269225 use Perl::Critic::Utils;
  2         6  
  2         64  
28              
29             # uncomment this to run the ### lines
30             #use Smart::Comments;
31              
32             # ABSTRACT: Don't assign an anonymous arrayref to an array
33             our $VERSION = '100.00'; # VERSION
34              
35 2     2   1601 use constant supported_parameters => ();
  2         5  
  2         161  
36 2     2   12 use constant default_severity => $Perl::Critic::Utils::SEVERITY_MEDIUM;
  2         4  
  2         104  
37 2     2   10 use constant default_themes => ();
  2         5  
  2         118  
38 2         462 use constant applies_to => ('PPI::Token::Symbol',
39 2     2   8 'PPI::Token::Cast');
  2         3  
40              
41             sub violates {
42 24     24 1 2869555 my ($self, $elem, $document) = @_;
43              
44 24 100       221 ($elem->isa('PPI::Token::Cast') ? $elem->content : $elem->raw_type)
    100          
45             eq '@' or return;
46             ### ProhibitArrayAssignAref: $elem->content
47              
48 18         220 my $thing = 'Array';
49 18         56 for (;;) {
50 39   50     179 $elem = $elem->snext_sibling || return;
51 39 100       1395 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     179 if ($elem->isa('PPI::Structure::Subscript')
58             || $elem->isa('PPI::Structure::Constructor')) {
59 11 100       43 if ($elem->start eq '[') {
    50          
60 5         128 $thing = 'Array slice';
61             } elsif ($elem->start eq '{') {
62 6         215 $thing = 'Hash slice';
63             }
64             }
65             }
66             ### $thing
67             ### operator: $elem->content
68 18 50       69 $elem eq '=' or return;
69              
70 18   50     304 $elem = $elem->snext_sibling || return;
71 18 100 66     638 ($elem->isa('PPI::Structure::Constructor') && $elem->start eq '[')
72             or return;
73              
74 11         269 return $self->violation
75             ("$thing assigned a [] arrayref, should it be a () list ?",
76             '', $elem);
77             }
78              
79             1;
80              
81             __END__
82              
83             =pod
84              
85             =encoding UTF-8
86              
87             =head1 NAME
88              
89             Perl::Critic::Policy::Plicease::ProhibitArrayAssignAref - Don't assign an anonymous arrayref to an array
90              
91             =head1 VERSION
92              
93             version 100.00
94              
95             =head1 DESCRIPTION
96              
97             This policy is a fork of L<Perl::Critic::Policy::ValuesAndExpressions::ProhibitArrayAssignAref>.
98             It differs from the original by not having a dependency on L<List::MoreUtils>.
99             It is unfortunately still licensed as GPL3.
100              
101             It asks you not to assign an anonymous arrayref to an array
102              
103             @array = [ 1, 2, 3 ]; # bad
104              
105             The idea is that it's rather unclear whether an arrayref is intended, or
106             might have meant to be a list like
107              
108             @array = ( 1, 2, 3 );
109              
110             This policy is under the "bugs" theme (see L<Perl::Critic/POLICY THEMES>)
111             for the chance C<[]> is a mistake, and since even if it's correct it will
112             likely make anyone reading it wonder.
113              
114             A single arrayref can still be assigned to an array, but with parens to make
115             it clear,
116              
117             @array = ( [1,2,3] ); # ok
118              
119             Dereferences or array and hash slices (see L<perldata/Slices>) are
120             recognised as an array target and treated similarly,
121              
122             @$ref = [1,2,3]; # bad assign to deref
123             @{$ref} = [1,2,3]; # bad assign to deref
124             @x[1,2,3] = ['a','b','c']; # bad assign to array slice
125             @x{'a','b'} = [1,2]; # bad assign to hash slice
126              
127             =head2 List Assignment Parens
128              
129             This policy is not a blanket requirement for C<()> parens on array
130             assignments. It's normal and unambiguous to have a function call or C<grep>
131             etc without parens.
132              
133             @array = foo(); # ok
134             @array = grep {/\.txt$/} @array; # ok
135              
136             The only likely problem from lack of parens in such cases is that the C<,>
137             comma operator has lower precedence than C<=> (see L<perlop>), so something
138             like
139              
140             @array = 1,2,3; # oops, not a list
141              
142             means
143              
144             @array = (1);
145             2;
146             3;
147              
148             Normally the remaining literals in void context provoke a warning from Perl
149             itself.
150              
151             An intentional single element assignment is quite common as a statement, for
152             instance
153              
154             @ISA = 'My::Parent::Class'; # ok
155              
156             And for reference the range operator precedence is high enough,
157              
158             @array = 1..10; # ok
159              
160             But of course parens are needed if concatenating some disjoint ranges with
161             the comma operator,
162              
163             @array = (1..5, 10..15); # parens needed
164              
165             The C<qw> form gives a list too
166              
167             @array = qw(a b c); # ok
168              
169             =head1 SEE ALSO
170              
171             =over 4
172              
173             =item L<Perl::Critic>
174              
175             =item L<Perl::Critic::Policy::ValuesAndExpressions::ProhibitArrayAssignAref>
176              
177             =back
178              
179             =head1 HOME PAGE
180              
181             =over 4
182              
183             =item L<https://github.com/uperl/Perl-Critic-Policy-Plicease-ProhibitArrayAssignAref>
184              
185             =back
186              
187             =head1 COPYRIGHT
188              
189             Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2021 Kevin Ryde
190              
191             Perl-Critic-Policy-Plicease-ProhibitArrayAssignAref is free software; you can redistribute it and/or modify it
192             under the terms of the GNU General Public License as published by the Free
193             Software Foundation; either version 3, or (at your option) any later
194             version.
195              
196             Perl-Critic-Policy-Plicease-ProhibitArrayAssignAref is distributed in the hope that it will be useful, but
197             WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
198             or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
199             more details.
200              
201             You should have received a copy of the GNU General Public License along with
202             Perl-Critic-Policy-Plicease-ProhibitArrayAssignAref. If not, see <http://www.gnu.org/licenses>.
203              
204             =head1 AUTHOR
205              
206             Original author: Kevin Ryde
207              
208             Current maintainer: Graham Ollis E<lt>plicease@cpan.orgE<gt>
209              
210             =head1 COPYRIGHT AND LICENSE
211              
212             This software is Copyright (c) 2011-2021 by Kevin Ryde.
213              
214             This is free software, licensed under:
215              
216             The GNU General Public License, Version 3, June 2007
217              
218             =cut