File Coverage

blib/lib/Perl/Lint/Policy/Variables/ProhibitUnusedVariables.pm
Criterion Covered Total %
statement 83 89 93.2
branch 34 38 89.4
condition 6 6 100.0
subroutine 8 8 100.0
pod 0 1 0.0
total 131 142 92.2


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::Variables::ProhibitUnusedVariables;
2 133     133   69281 use strict;
  133         171  
  133         3236  
3 133     133   463 use warnings;
  133         144  
  133         2374  
4 133     133   741 use List::Flatten ();
  133         340  
  133         1341  
5 133     133   365 use List::Util ();
  133         172  
  133         1521  
6 133     133   744 use Perl::Lint::Constants::Type;
  133         151  
  133         60029  
7 133     133   615 use parent "Perl::Lint::Policy";
  133         145  
  133         557  
8              
9             use constant {
10 133         73002 DESC => '"%s" is declared but not used.',
11             EXPL => 'Unused variables clutter code and make it harder to read',
12 133     133   6648 };
  133         162  
13              
14             my %var_token_types = (
15             &LOCAL_VAR => 1,
16             &LOCAL_ARRAY_VAR => 1,
17             &LOCAL_HASH_VAR => 1,
18             &GLOBAL_VAR => 1,
19             &GLOBAL_ARRAY_VAR => 1,
20             &GLOBAL_HASH_VAR => 1,
21             &VAR => 1,
22             &ARRAY_VAR => 1,
23             &HASH_VAR => 1,
24             );
25              
26             sub evaluate {
27 20     20 0 30 my ($class, $file, $tokens, $src, $args) = @_;
28              
29 20         11 my @violations;
30             my $depth;
31 0         0 my %vars_by_depth;
32 20         50 for (my $i = 0, my $token_type; my $token = $tokens->[$i]; $i++) {
33 230         160 $token_type = $token->{type};
34              
35 230 100       249 if ($token_type == LEFT_BRACE) {
36 17         9 $depth++;
37 17         27 next;
38             }
39              
40 213 100       225 if ($token_type == RIGHT_BRACE) {
41 17         21 for my $variable (keys %vars_by_depth) {
42             push @violations, {
43             filename => $file,
44 6         34 line => $vars_by_depth{$variable},
45             description => sprintf(DESC, $variable),
46             explanation => EXPL,
47             policy => __PACKAGE__,
48             };
49             }
50 17         19 %vars_by_depth = ();
51              
52 17         16 $depth--;
53 17         24 next;
54             }
55              
56 196 100       211 if ($token_type == VAR_DECL) {
57 23         24 $token = $tokens->[++$i];
58 23 100       30 if ($token->{type} == LEFT_PAREN) {
59 2         1 my $lpnum = 1;
60 2         3 my %vars_in_paren;
61 2         4 for ($i++; $token = $tokens->[$i]; $i++) {
62 10         8 $token_type = $token->{type};
63              
64 10 50       12 if ($token_type == LEFT_PAREN) {
65 0         0 $lpnum++;
66 0         0 next;
67             }
68              
69 10 100       14 if ($token_type == RIGHT_PAREN) {
70 2 50       5 last if --$lpnum <= 0;
71 0         0 next;
72             }
73              
74 8 100       13 if ($var_token_types{$token_type}) {
75 5         8 $vars_in_paren{$token->{data}} = $token->{line};
76 5         9 next;
77             }
78             }
79              
80 2         3 $token = $tokens->[$i+1];
81 2 100       4 if ($token->{type} != ASSIGN) {
82 1         4 %vars_by_depth = (%vars_by_depth, %vars_in_paren);
83             }
84              
85 2         7 next;
86             }
87              
88 21         22 my $next_token = $tokens->[$i+1];
89 21 100       31 if ($next_token->{type} != ASSIGN) {
90 14         23 $vars_by_depth{$token->{data}} = $token->{line};
91             }
92 21         34 next;
93             }
94              
95 173 100 100     436 if ($token_type == OUR_DECL || $token_type == LOCAL_DECL) {
96 2         8 for ($i++; $token = $tokens->[$i]; $i++) {
97 4 100       9 if ($token->{type} == SEMI_COLON) {
98 2         4 last;
99             }
100             }
101 2         3 next;
102             }
103              
104 171 100       250 if ($var_token_types{$token_type}) {
105 10         11 my $variable = $token->{data};
106              
107 10         8 $token = $tokens->[$i+1];
108 10         8 $token_type = $token->{type};
109 10 100       22 if ($token_type == LEFT_BRACKET) {
    100          
110 1         4 $variable = '@' . substr $variable, 1;
111             }
112             elsif ($token_type == LEFT_BRACE) {
113 1         4 $variable = '%' . substr $variable, 1;
114             }
115              
116 10         9 delete $vars_by_depth{$variable};
117 10         16 next;
118             }
119              
120 161 100 100     477 if (
121             $token_type == REG_REPLACE_TO ||
122             $token_type == REG_EXP
123             ) {
124 11         12 my $regex = $token->{data};
125              
126 11         28 while ($regex =~ /(\\*)([\$\@]\w+[\{\[]?)/gc) { # XXX
127 5 50       11 if (length($1) % 2 == 0) {
128             # not escaped
129 5         7 my $variable = $2;
130 5         6 my $last_char = substr $variable, -1, 1;
131 5 100       18 if ($last_char eq '{') {
    50          
132 3         6 $variable = '%' . substr $variable, 1, -1;
133             }
134             elsif ($last_char eq '[') {
135 0         0 $variable = '@' . substr $variable, 1, -1;
136             }
137              
138 5         6 delete $vars_by_depth{$variable};
139 5         12 next;
140             }
141             else {
142             # escaped
143 0         0 next;
144             }
145             }
146              
147 11         17 next;
148             }
149             }
150              
151 20         27 for my $variable (keys %vars_by_depth) {
152             push @violations, {
153             filename => $file,
154 4         31 line => $vars_by_depth{$variable},
155             description => sprintf(DESC, $variable),
156             explanation => EXPL,
157             policy => __PACKAGE__,
158             };
159             }
160              
161 20         68 return \@violations;
162             }
163              
164             1;
165