File Coverage

blib/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitSingleArgArraySlice.pm
Criterion Covered Total %
statement 36 37 97.3
branch 13 16 81.2
condition 3 3 100.0
subroutine 10 11 90.9
pod 4 5 80.0
total 66 72 91.6


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::ValuesAndExpressions::ProhibitSingleArgArraySlice;
2             our $AUTHORITY = 'cpan:XSAWYERX';
3             # ABSTRACT: Prohibit using an array slice with only one index
4             $Perl::Critic::Policy::ValuesAndExpressions::ProhibitSingleArgArraySlice::VERSION = '0.004';
5 1     1   191009 use strict;
  1         1  
  1         23  
6 1     1   4 use warnings;
  1         0  
  1         22  
7              
8 1     1   4 use parent 'Perl::Critic::Policy';
  1         1  
  1         6  
9 1     1   12011 use Perl::Critic::Utils qw(:severities :classification :ppi);
  1         1  
  1         44  
10              
11 1     1   247 use constant 'DESC' => 'Single argument to array slice';
  1         2  
  1         72  
12 1         195 use constant 'EXPL' => 'Using an array slice returns a list, '
13             . 'even when accessing a single value. '
14             . 'Instead, please rewrite this as a a '
15 1     1   4 . 'single value access, not array slice.';
  1         1  
16              
17 2     2 0 12161 sub supported_parameters { () }
18 3     3 1 23 sub default_severity {$SEVERITY_HIGH}
19 0     0 1 0 sub default_themes {'bugs'}
20 2     2 1 16683 sub applies_to {'PPI::Token::Symbol'}
21              
22             # TODO Check for a function in the subscript? Strict mode?
23              
24             sub violates {
25 20     20 1 468 my ( $self, $elem ) = @_;
26 20 50       44 $elem->isa('PPI::Token::Symbol')
27             or return ();
28              
29 20 100       25 substr( "$elem", 0, 1 ) eq '@'
30             or return ();
31              
32 13         62 my $next = $elem->snext_sibling;
33 13 100 100     236 $next && $next->isa('PPI::Structure::Subscript')
34             or return ();
35              
36 8         19 my @children = $next->children;
37 8 100       37 @children > 1
38             and return ();
39              
40 6 50       11 @children == 0
41             and return $self->violation( 'Empty subscript',
42             'You have an array slice with an empty subscript', $next, );
43              
44 6         7 my $child = $children[0];
45 6         12 my @child_elements = $child->elements;
46              
47 6 100       29 @child_elements > 1
48             and return ();
49              
50 5 50       10 @children == 0
51             and return $self->violation( 'Empty expression subscript',
52             'You have an array slice with an empty expression subscript',
53             $next, );
54              
55 5         3 my $element = $child_elements[0];
56              
57             # @foo[1]
58 5 100       18 $element->isa('PPI::Token::Number')
59             or return ();
60              
61 3         10 return $self->violation( DESC(), EXPL(), $next );
62             }
63              
64             1;
65              
66             __END__
67              
68             =pod
69              
70             =encoding UTF-8
71              
72             =head1 NAME
73              
74             Perl::Critic::Policy::ValuesAndExpressions::ProhibitSingleArgArraySlice - Prohibit using an array slice with only one index
75              
76             =head1 VERSION
77              
78             version 0.004
79              
80             =head1 DESCRIPTION
81              
82             When using an array slice C<@foo[]>, you can retrieve multiple values by
83             giving more than one index. Sometimes, however, either due to typo or
84             inexperience, we might only provide a single index.
85              
86             Perl warns you about this, but it will only do this during runtime. This
87             policy allows you to detect it statically.
88              
89             # scalar context, single value retrieved
90             my $one_value = $array[$index]; # ok
91              
92             # List context, multiple values retrieved
93             my @values = @array[ $index1, $index2 ] # ok
94              
95             # Scalar context, single value retrived (the last item in the array)
96             # Perl will warn you, but only in runtime
97             my $value = @array[$index]; # not ok
98              
99             =head1 CONFIGURATION
100              
101             This policy is not configurable except for the standard options.
102              
103             =head1 SEE ALSO
104              
105             L<Perl::Critic>
106              
107             =head1 AUTHOR
108              
109             Sawyer X <xsawyerx@cpan.org>
110              
111             =head1 COPYRIGHT AND LICENSE
112              
113             This software is Copyright (c) 2016 by Sawyer X.
114              
115             This is free software, licensed under:
116              
117             The MIT (X11) License
118              
119             =cut