File Coverage

blib/lib/Perl/Lint/Policy/Variables/RequireNegativeIndices.pm
Criterion Covered Total %
statement 67 67 100.0
branch 35 40 87.5
condition 19 24 79.1
subroutine 6 6 100.0
pod 0 1 0.0
total 127 138 92.0


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::Variables::RequireNegativeIndices;
2 133     133   70780 use strict;
  133         162  
  133         3255  
3 133     133   440 use warnings;
  133         139  
  133         2528  
4 133     133   854 use Perl::Lint::Constants::Type;
  133         413  
  133         59718  
5 133     133   607 use parent "Perl::Lint::Policy";
  133         158  
  133         542  
6              
7             use constant {
8 133         57796 DESC => 'Negative array index should be used',
9             EXPL => [88],
10 133     133   6858 };
  133         153  
11              
12             my %var_token_types = (
13             &VAR => 1,
14             &GLOBAL_VAR => 1,
15             );
16              
17             my %array_dereference_token_types = (
18             &ARRAY_DEREFERENCE => 1,
19             &ARRAY_SIZE_DEREFERENCE => 1,
20             );
21              
22             my %array_var_token_types = (
23             &ARRAY_VAR => 1,
24             &GLOBAL_ARRAY_VAR => 1,
25             );
26              
27             sub evaluate {
28 5     5 0 12 my ($class, $file, $tokens, $src, $args) = @_;
29              
30 5         4 my @violations;
31 5         21 for (my $i = 0, my $token_type, my $token_data; my $token = $tokens->[$i]; $i++) {
32 118         75 $token_type = $token->{type};
33 118         89 $token_data = $token->{data};
34              
35 118         75 my $is_reference = 0;
36 118 100 100     308 if ($var_token_types{$token_type} || $token_type == SHORT_SCALAR_DEREFERENCE) {
37 45         30 my $var_name;
38 45 100       63 if ($token_type == SHORT_SCALAR_DEREFERENCE) {
39 9         9 $token = $tokens->[++$i];
40 9 50       13 last if !$token;
41              
42 9         10 $var_name = $token->{data};
43 9         7 $is_reference = 1;
44             }
45             else {
46 36         40 $var_name = substr($token->{data}, 1);
47             }
48              
49 45         39 $token = $tokens->[++$i];
50 45 50       60 last if !$token;
51              
52 45 100       52 if ($token->{type} == POINTER) {
53 13         10 $is_reference = 1;
54 13         11 $token = $tokens->[++$i];
55 13 50       18 last if !$token;
56             }
57              
58 45 100       65 if ($token->{type} == LEFT_BRACKET) {
59 36         29 my $nlbracket = 1;
60 36         70 for ($i++; $token = $tokens->[$i]; $i++) {
61 138         104 $token_type = $token->{type};
62              
63 138 100       153 if ($token_type == LEFT_BRACKET) {
64 1         2 $nlbracket++;
65 1         3 next;
66             }
67              
68 137 100       144 if ($token_type == RIGHT_BRACKET) {
69 37 100       80 last if --$nlbracket <= 0;
70 1         2 next;
71             }
72              
73 100 100 100     250 if (
      66        
74             $token_type == ARRAY_SIZE ||
75             ($is_reference && $token_type == SHORT_ARRAY_DEREFERENCE)
76             ) {
77 14         10 $token = $tokens->[++$i];
78 14 50       21 last if !$token;
79              
80 14         11 $token_type = $token->{type};
81              
82 14         13 my $array_size_data;
83 14 100 66     40 if ($is_reference && $var_token_types{$token_type}) {
    100          
84 2         6 $array_size_data = substr $token->{data}, 1;
85             }
86             elsif ($token->{type} == KEY) {
87 11         9 $array_size_data = $token->{data};
88             }
89              
90 14 100       19 if ($array_size_data) {
91 13         18 $array_size_data =~ s/\W.*\Z//; # XXX workaround
92             # ref: https://github.com/goccy/p5-Compiler-Lexer/issues/48
93 13 100       22 if ($array_size_data eq $var_name) {
94             push @violations, {
95             filename => $file,
96             line => $token->{line},
97 10         34 description => DESC,
98             explanation => EXPL,
99             policy => __PACKAGE__,
100             };
101             }
102             }
103              
104 14         26 next;
105             }
106              
107 86 100 100     209 if (
      66        
108             $token_type == ARRAY_DEREFERENCE ||
109             ($is_reference && $token_type == ARRAY_SIZE_DEREFERENCE)
110             ) {
111 5         6 $token = $tokens->[++$i];
112 5 50       9 last if !$token;
113             } # fall through
114 86 100 66     331 if (
      66        
115             (!$is_reference && $array_var_token_types{$token_type}) ||
116             $array_dereference_token_types{$token_type}
117             ) {
118 11         29 ($token_data = substr $token->{data}, 1) =~ s/\W.*\Z//; # XXX workaround
119             # ref: https://github.com/goccy/p5-Compiler-Lexer/issues/48
120 11 100       17 if ($token_data eq $var_name) {
121             push @violations, {
122             filename => $file,
123             line => $token->{line},
124 8         26 description => DESC,
125             explanation => EXPL,
126             policy => __PACKAGE__,
127             };
128             }
129 11         20 next;
130             }
131             }
132             }
133             }
134              
135             }
136              
137 5         22 return \@violations;
138             }
139              
140             1;
141