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   68187 use strict;
  133         186  
  133         3116  
3 133     133   400 use warnings;
  133         132  
  133         2423  
4 133     133   51975 use List::Flatten ();
  133         27782  
  133         1891  
5 133     133   539 use List::Util ();
  133         175  
  133         1572  
6 133     133   925 use Perl::Lint::Constants::Type;
  133         194  
  133         58986  
7 133     133   950 use parent "Perl::Lint::Policy";
  133         163  
  133         708  
8              
9             use constant {
10 133         67649 DESC => 'Reused variable name in lexical scope: ',
11             EXPL => 'Invent unique variable names',
12 133     133   8708 };
  133         201  
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 31 my ($class, $file, $tokens, $src, $args) = @_;
28              
29 20         27 my @allows = qw/$self $class/;
30 20 100       42 if (my $this_policies_arg = $args->{prohibit_reused_names}) {
31 1   50     7 push @allows, split(/\s+/, $this_policies_arg->{allow} || '');
32             }
33              
34 20         21 my @violations;
35              
36 20         18 my $depth = 0;
37 20         22 my @local_vars_by_depth = ([]);
38 20         55 for (my $i = 0, my $token_type; my $token = $tokens->[$i]; $i++) {
39 321         221 $token_type = $token->{type};
40 321 100 100     1404 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         23 $depth++;
46 49         42 push @local_vars_by_depth, [];
47 49         83 next;
48             }
49              
50 272 100       303 if ($token_type == RIGHT_BRACE) {
51 49         37 pop @local_vars_by_depth;
52 49         41 $depth--;
53 49         69 next;
54             }
55              
56 223 100       230 if ($token_type == PACKAGE) {
57 3         5 $local_vars_by_depth[$depth] = [];
58 3         6 next;
59             }
60              
61 220 100 100     601 if ($token_type == VAR_DECL || $token_type == OUR_DECL) {
62 64         51 $i++;
63 64         48 $token = $tokens->[$i];
64 64         39 $token_type = $token->{type};
65              
66 64         51 my @vars;
67 64 100       74 if ($token_type == LEFT_PAREN) {
68 4         5 my $lpnum = 1;
69 4         7 for ($i++; $token = $tokens->[$i]; $i++) {
70 17         15 $token_type = $token->{type};
71              
72 17 50       20 if ($token_type == LEFT_PAREN) {
73 0         0 $lpnum++;
74 0         0 next;
75             }
76              
77 17 100       20 if ($token_type == RIGHT_PAREN) {
78 4 50       7 last if --$lpnum <= 0;
79 0         0 next;
80             }
81              
82 13 100       22 if ($var_token_types{$token_type}) {
83 8         8 my $token_data = $token->{data};
84 8 50   16   17 if (List::Util::any { $_ eq $token_data } @allows) {
  16         16  
85 0         0 next;
86             }
87              
88 8 100       21 if (
89             List::Util::any {
90 17     17   50 $_ eq $token_data
91             } List::Flatten::flat(@local_vars_by_depth)
92             ) {
93             push @violations, {
94             filename => $file,
95             line => $token->{line},
96 4         13 description => DESC . $token_data,
97             explanation => EXPL,
98             policy => __PACKAGE__,
99             };
100 4         10 next;
101             }
102              
103             # XXX
104 4 50 33     10 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         5  
108 4         6 next;
109             }
110             }
111 4         7 next;
112             }
113              
114 60         54 my $token_data = $token->{data};
115              
116 60 100   120   190 if (List::Util::any { $_ eq $token_data } @allows) {
  120         135  
117 6         21 next;
118             }
119              
120 54 100       162 if (
121             List::Util::any {
122 48     48   211 $_ eq $token_data
123             } List::Flatten::flat(@local_vars_by_depth)
124             ) {
125             push @violations, {
126             filename => $file,
127             line => $token->{line},
128 24         76 description => DESC,
129             explanation => EXPL,
130             policy => __PACKAGE__,
131             };
132 24         62 next;
133             }
134              
135             # XXX
136 30 50 33     192 if ($depth < 0 && scalar @local_vars_by_depth < -$depth) {
137 0         0 next;
138             }
139              
140 30         30 push @{$local_vars_by_depth[$depth]}, $token_data;
  30         43  
141 30         63 next;
142             }
143             }
144              
145 20         71 return \@violations;
146             }
147              
148             1;
149