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   69756 use strict;
  133         190  
  133         3101  
3 133     133   405 use warnings;
  133         147  
  133         2341  
4 133     133   51297 use List::Flatten ();
  133         26537  
  133         1831  
5 133     133   534 use List::Util ();
  133         168  
  133         1536  
6 133     133   899 use Perl::Lint::Constants::Type;
  133         181  
  133         58579  
7 133     133   902 use parent "Perl::Lint::Policy";
  133         159  
  133         608  
8              
9             use constant {
10 133         67141 DESC => 'Reused variable name in lexical scope: ',
11             EXPL => 'Invent unique variable names',
12 133     133   8270 };
  133         181  
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         36 my @allows = qw/$self $class/;
30 20 100       49 if (my $this_policies_arg = $args->{prohibit_reused_names}) {
31 1   50     6 push @allows, split(/\s+/, $this_policies_arg->{allow} || '');
32             }
33              
34 20         13 my @violations;
35              
36 20         18 my $depth = 0;
37 20         32 my @local_vars_by_depth = ([]);
38 20         56 for (my $i = 0, my $token_type; my $token = $tokens->[$i]; $i++) {
39 321         218 $token_type = $token->{type};
40 321 100 100     1406 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         30 $depth++;
46 49         50 push @local_vars_by_depth, [];
47 49         74 next;
48             }
49              
50 272 100       308 if ($token_type == RIGHT_BRACE) {
51 49         37 pop @local_vars_by_depth;
52 49         39 $depth--;
53 49         72 next;
54             }
55              
56 223 100       230 if ($token_type == PACKAGE) {
57 3         5 $local_vars_by_depth[$depth] = [];
58 3         7 next;
59             }
60              
61 220 100 100     572 if ($token_type == VAR_DECL || $token_type == OUR_DECL) {
62 64         44 $i++;
63 64         54 $token = $tokens->[$i];
64 64         50 $token_type = $token->{type};
65              
66 64         46 my @vars;
67 64 100       86 if ($token_type == LEFT_PAREN) {
68 4         4 my $lpnum = 1;
69 4         8 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       19 if ($token_type == RIGHT_PAREN) {
78 4 50       8 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   26 if (List::Util::any { $_ eq $token_data } @allows) {
  16         19  
85 0         0 next;
86             }
87              
88 8 100       35 if (
89             List::Util::any {
90 17     17   54 $_ eq $token_data
91             } List::Flatten::flat(@local_vars_by_depth)
92             ) {
93             push @violations, {
94             filename => $file,
95             line => $token->{line},
96 4         15 description => DESC . $token_data,
97             explanation => EXPL,
98             policy => __PACKAGE__,
99             };
100 4         13 next;
101             }
102              
103             # XXX
104 4 50 33     11 if ($depth < 0 && scalar @local_vars_by_depth < -$depth) {
105 0         0 next;
106             }
107 4         2 push @{$local_vars_by_depth[$depth]}, $token_data;
  4         8  
108 4         7 next;
109             }
110             }
111 4         9 next;
112             }
113              
114 60         53 my $token_data = $token->{data};
115              
116 60 100   120   201 if (List::Util::any { $_ eq $token_data } @allows) {
  120         133  
117 6         20 next;
118             }
119              
120 54 100       175 if (
121             List::Util::any {
122 48     48   203 $_ eq $token_data
123             } List::Flatten::flat(@local_vars_by_depth)
124             ) {
125             push @violations, {
126             filename => $file,
127             line => $token->{line},
128 24         78 description => DESC,
129             explanation => EXPL,
130             policy => __PACKAGE__,
131             };
132 24         59 next;
133             }
134              
135             # XXX
136 30 50 33     158 if ($depth < 0 && scalar @local_vars_by_depth < -$depth) {
137 0         0 next;
138             }
139              
140 30         21 push @{$local_vars_by_depth[$depth]}, $token_data;
  30         40  
141 30         67 next;
142             }
143             }
144              
145 20         68 return \@violations;
146             }
147              
148             1;
149