File Coverage

blib/lib/Perl/Lint/Policy/Variables/ProhibitReusedNames.pm
Criterion Covered Total %
statement 79 85 92.9
branch 27 32 84.3
condition 15 20 75.0
subroutine 12 12 100.0
pod 0 1 0.0
total 133 150 88.6


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::Variables::ProhibitReusedNames;
2 133     133   91857 use strict;
  133         302  
  133         4829  
3 133     133   583 use warnings;
  133         171  
  133         3410  
4 133     133   66483 use List::Flatten ();
  133         36283  
  133         2473  
5 133     133   918 use List::Util ();
  133         256  
  133         2119  
6 133     133   1152 use Perl::Lint::Constants::Type;
  133         251  
  133         84999  
7 133     133   1364 use parent "Perl::Lint::Policy";
  133         213  
  133         847  
8              
9             use constant {
10 133         91430 DESC => 'Reused variable name in lexical scope: ',
11             EXPL => 'Invent unique variable names',
12 133     133   12299 };
  133         231  
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 35 my ($class, $file, $tokens, $src, $args) = @_;
28              
29 20         51 my @allows = qw/$self $class/;
30 20 100       48 if (my $this_policies_arg = $args->{prohibit_reused_names}) {
31 1   50     5 push @allows, split(/\s+/, $this_policies_arg->{allow} || '');
32             }
33              
34 20         73 my @violations;
35              
36 20         25 my $depth = 0;
37 20         38 my @local_vars_by_depth = ([]);
38 20         77 for (my $i = 0, my $token_type; my $token = $tokens->[$i]; $i++) {
39 321         334 $token_type = $token->{type};
40 321 100 100     1725 if ($token_type == LEFT_BRACE
      100        
      100        
41             || $token_type == HASH_DEREFERENCE
42             || $token_type == ARRAY_DEREFERENCE
43             || $token_type == SCALAR_DEREFERENCE
44             ) {
45 49         42 $depth++;
46 49         55 push @local_vars_by_depth, [];
47 49         95 next;
48             }
49              
50 272 100       374 if ($token_type == RIGHT_BRACE) {
51 49         117 pop @local_vars_by_depth;
52 49         49 $depth--;
53 49         106 next;
54             }
55              
56 223 100       303 if ($token_type == PACKAGE) {
57 3         6 $local_vars_by_depth[$depth] = [];
58 3         8 next;
59             }
60              
61 220 100 100     742 if ($token_type == VAR_DECL || $token_type == OUR_DECL) {
62 64         50 $i++;
63 64         62 $token = $tokens->[$i];
64 64         63 $token_type = $token->{type};
65              
66 64         53 my @vars;
67 64 100       101 if ($token_type == LEFT_PAREN) {
68 4         4 my $lpnum = 1;
69 4         9 for ($i++; $token = $tokens->[$i]; $i++) {
70 17         14 $token_type = $token->{type};
71              
72 17 50       26 if ($token_type == LEFT_PAREN) {
73 0         0 $lpnum++;
74 0         0 next;
75             }
76              
77 17 100       24 if ($token_type == RIGHT_PAREN) {
78 4 50       10 last if --$lpnum <= 0;
79 0         0 next;
80             }
81              
82 13 100       33 if ($var_token_types{$token_type}) {
83 8         12 my $token_data = $token->{data};
84 8 50   16   22 if (List::Util::any { $_ eq $token_data } @allows) {
  16         21  
85 0         0 next;
86             }
87              
88 8 100       28 if (
89             List::Util::any {
90 17     17   65 $_ eq $token_data
91             } List::Flatten::flat(@local_vars_by_depth)
92             ) {
93 4         15 push @violations, {
94             filename => $file,
95             line => $token->{line},
96             description => DESC . $token_data,
97             explanation => EXPL,
98             policy => __PACKAGE__,
99             };
100 4         12 next;
101             }
102              
103             # XXX
104 4 50 33     14 if ($depth < 0 && scalar @local_vars_by_depth < -$depth) {
105 0         0 next;
106             }
107 4         5 push @{$local_vars_by_depth[$depth]}, $token_data;
  4         7  
108 4         12 next;
109             }
110             }
111 4         8 next;
112             }
113              
114 60         82 my $token_data = $token->{data};
115              
116 60 100   120   265 if (List::Util::any { $_ eq $token_data } @allows) {
  120         173  
117 6         26 next;
118             }
119              
120 54 100       223 if (
121             List::Util::any {
122 48     48   263 $_ eq $token_data
123             } List::Flatten::flat(@local_vars_by_depth)
124             ) {
125 24         105 push @violations, {
126             filename => $file,
127             line => $token->{line},
128             description => DESC,
129             explanation => EXPL,
130             policy => __PACKAGE__,
131             };
132 24         88 next;
133             }
134              
135             # XXX
136 30 50 33     193 if ($depth < 0 && scalar @local_vars_by_depth < -$depth) {
137 0         0 next;
138             }
139              
140 30         25 push @{$local_vars_by_depth[$depth]}, $token_data;
  30         54  
141 30         79 next;
142             }
143             }
144              
145 20         107 return \@violations;
146             }
147              
148             1;
149