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   95677 use strict;
  133         253  
  133         4816  
3 133     133   590 use warnings;
  133         193  
  133         3408  
4 133     133   1795 use List::Flatten ();
  133         498  
  133         1599  
5 133     133   714 use List::Util ();
  133         188  
  133         1889  
6 133     133   977 use Perl::Lint::Constants::Type;
  133         238  
  133         91318  
7 133     133   812 use parent "Perl::Lint::Policy";
  133         229  
  133         787  
8              
9             use constant {
10 133         95102 DESC => '"%s" is declared but not used.',
11             EXPL => 'Unused variables clutter code and make it harder to read',
12 133     133   9212 };
  133         252  
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 43 my ($class, $file, $tokens, $src, $args) = @_;
28              
29 20         25 my @violations;
30             my $depth;
31 0         0 my %vars_by_depth;
32 20         72 for (my $i = 0, my $token_type; my $token = $tokens->[$i]; $i++) {
33 230         236 $token_type = $token->{type};
34              
35 230 100       369 if ($token_type == LEFT_BRACE) {
36 17         18 $depth++;
37 17         35 next;
38             }
39              
40 213 100       370 if ($token_type == RIGHT_BRACE) {
41 17         42 for my $variable (keys %vars_by_depth) {
42 6         43 push @violations, {
43             filename => $file,
44             line => $vars_by_depth{$variable},
45             description => sprintf(DESC, $variable),
46             explanation => EXPL,
47             policy => __PACKAGE__,
48             };
49             }
50 17         39 %vars_by_depth = ();
51              
52 17         17 $depth--;
53 17         44 next;
54             }
55              
56 196 100       293 if ($token_type == VAR_DECL) {
57 23         34 $token = $tokens->[++$i];
58 23 100       44 if ($token->{type} == LEFT_PAREN) {
59 2         3 my $lpnum = 1;
60 2         3 my %vars_in_paren;
61 2         7 for ($i++; $token = $tokens->[$i]; $i++) {
62 10         13 $token_type = $token->{type};
63              
64 10 50       15 if ($token_type == LEFT_PAREN) {
65 0         0 $lpnum++;
66 0         0 next;
67             }
68              
69 10 100       17 if ($token_type == RIGHT_PAREN) {
70 2 50       8 last if --$lpnum <= 0;
71 0         0 next;
72             }
73              
74 8 100       19 if ($var_token_types{$token_type}) {
75 5         8 $vars_in_paren{$token->{data}} = $token->{line};
76 5         77 next;
77             }
78             }
79              
80 2         4 $token = $tokens->[$i+1];
81 2 100       18 if ($token->{type} != ASSIGN) {
82 1         7 %vars_by_depth = (%vars_by_depth, %vars_in_paren);
83             }
84              
85 2         8 next;
86             }
87              
88 21         30 my $next_token = $tokens->[$i+1];
89 21 100       46 if ($next_token->{type} != ASSIGN) {
90 14         35 $vars_by_depth{$token->{data}} = $token->{line};
91             }
92 21         53 next;
93             }
94              
95 173 100 100     551 if ($token_type == OUR_DECL || $token_type == LOCAL_DECL) {
96 2         10 for ($i++; $token = $tokens->[$i]; $i++) {
97 4 100       14 if ($token->{type} == SEMI_COLON) {
98 2         5 last;
99             }
100             }
101 2         7 next;
102             }
103              
104 171 100       322 if ($var_token_types{$token_type}) {
105 10         21 my $variable = $token->{data};
106              
107 10         15 $token = $tokens->[$i+1];
108 10         15 $token_type = $token->{type};
109 10 100       27 if ($token_type == LEFT_BRACKET) {
    100          
110 1         5 $variable = '@' . substr $variable, 1;
111             }
112             elsif ($token_type == LEFT_BRACE) {
113 1         3 $variable = '%' . substr $variable, 1;
114             }
115              
116 10         17 delete $vars_by_depth{$variable};
117 10         25 next;
118             }
119              
120 161 100 100     719 if (
121             $token_type == REG_REPLACE_TO ||
122             $token_type == REG_EXP
123             ) {
124 11         19 my $regex = $token->{data};
125              
126 11         48 while ($regex =~ /(\\*)([\$\@]\w+[\{\[]?)/gc) { # XXX
127 5 50       22 if (length($1) % 2 == 0) {
128             # not escaped
129 5         11 my $variable = $2;
130 5         10 my $last_char = substr $variable, -1, 1;
131 5 100       14 if ($last_char eq '{') {
    50          
132 3         8 $variable = '%' . substr $variable, 1, -1;
133             }
134             elsif ($last_char eq '[') {
135 0         0 $variable = '@' . substr $variable, 1, -1;
136             }
137              
138 5         12 delete $vars_by_depth{$variable};
139 5         20 next;
140             }
141             else {
142             # escaped
143 0         0 next;
144             }
145             }
146              
147 11         34 next;
148             }
149             }
150              
151 20         54 for my $variable (keys %vars_by_depth) {
152 4         26 push @violations, {
153             filename => $file,
154             line => $vars_by_depth{$variable},
155             description => sprintf(DESC, $variable),
156             explanation => EXPL,
157             policy => __PACKAGE__,
158             };
159             }
160              
161 20         113 return \@violations;
162             }
163              
164             1;
165