File Coverage

blib/lib/Perl/Lint/Policy/Variables/RequireLocalizedPunctuationVars.pm
Criterion Covered Total %
statement 97 101 96.0
branch 52 70 74.2
condition 13 17 76.4
subroutine 8 8 100.0
pod 0 1 0.0
total 170 197 86.2


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::Variables::RequireLocalizedPunctuationVars;
2 133     133   70252 use strict;
  133         170  
  133         3250  
3 133     133   428 use warnings;
  133         150  
  133         2501  
4 133     133   52393 use B::Keywords;
  133         108328  
  133         5393  
5 133     133   60861 use List::MoreUtils qw/apply uniq/;
  133         1023416  
  133         809  
6 133     133   65126 use Perl::Lint::Constants::Type;
  133         180  
  133         61321  
7 133     133   593 use parent "Perl::Lint::Policy";
  133         150  
  133         749  
8              
9             use constant {
10 133         85395 DESC => 'Magic variable "%s" should be assigned as "local"',
11             EXPL => [81, 82],
12 133     133   6921 };
  133         158  
13              
14             my %var_token_types = (
15             &VAR => 1,
16             &ARRAY_VAR => 1,
17             &HASH_VAR => 1,
18             &GLOBAL_VAR => 1,
19             &GLOBAL_ARRAY_VAR => 1,
20             &GLOBAL_HASH_VAR => 1,
21              
22             &PROGRAM_ARGUMENT => 1,
23             &LIBRARY_DIRECTORIES => 1,
24             &INCLUDE => 1,
25             &ENVIRONMENT => 1,
26             &SIGNAL => 1,
27             &SPECIFIC_VALUE => 1,
28             &ARRAY_SIZE => 1,
29             );
30              
31             my @globals = (
32             @B::Keywords::Arrays,
33             @B::Keywords::Hashes,
34             @B::Keywords::Scalars,
35             );
36             push @globals, map { "*$_" } grep { substr($_, 0, 1) ne '*' } @B::Keywords::Filehandles;
37             my %globals = map { $_ => 1 } @globals;
38              
39             sub evaluate {
40 15     15 0 25 my ($class, $file, $tokens, $src, $args) = @_;
41              
42 15         26 my @exemptions = qw/$_ $ARG @_/;
43 15 100       29 if (my $this_policies_arg = $args->{require_localized_punctuation_vars}) {
44 2   50     76 push @exemptions, split(/\s+/, $this_policies_arg->{allow} || '');
45             }
46 15         22 my %exemptions = map { $_ => 1 } @exemptions;
  200         246  
47              
48 15         23 my @violations;
49 15         44 for (my $i = 0, my $token_type, my $variable; my $token = $tokens->[$i]; $i++) {
50 7243         4664 $token_type = $token->{type};
51              
52 7243 100       7494 if ($token_type == LOCAL_DECL) {
53 638         443 $token = $tokens->[++$i];
54              
55 638 50       659 last if !$token;
56 638 100       697 if ($token->{type} == LEFT_PAREN) {
57 155         87 my $lpnum = 1;
58 155         186 for ($i++; $token = $tokens->[$i]; $i++) {
59 344         228 $token_type = $token->{type};
60              
61 344 50       592 if ($token_type == LEFT_PAREN) {
    100          
62 0         0 $lpnum++;
63             }
64             elsif ($token_type == RIGHT_PAREN) {
65 155 50       203 last if --$lpnum <= 0;
66             }
67             }
68             }
69              
70 638         775 next;
71             }
72              
73 6605         4328 $variable = $token->{data};
74 6605 100       10182 if ($token_type == MOD) {
    100          
    100          
75 9         8 $token = $tokens->[++$i];
76 9         9 $token_type = $token->{type};
77              
78 9 50       15 last if !$token;
79 9 100       17 if ($token_type == NOT) {
    50          
80 4         5 $variable .= $token->{data};
81 4         4 $token_type = VAR; # XXX
82             }
83             elsif ($token_type == BIT_XOR) {
84 5         9 $variable .= $token->{data};
85              
86 5         6 $token = $tokens->[++$i];
87 5         5 $token_type = $token->{type};
88              
89 5 50       8 last if !$token;
90              
91 5 50       8 if ($token_type == KEY) {
92 5         5 $variable .= $token->{data};
93 5         6 $token_type = VAR; # XXX
94             }
95             }
96             }
97             elsif ($token_type == SPECIFIC_VALUE) {
98 303         230 $token = $tokens->[$i+1];
99 303 50       312 next if !$token;
100              
101 303 100       371 if ($token->{type} == KEY) {
102 110         76 $i++;
103 110         81 $variable .= $token->{data};
104 110         76 $token_type = SPECIFIC_VALUE;
105             }
106             }
107             elsif ($token_type == GLOB) {
108 28         22 $token = $tokens->[++$i];
109              
110 28 50       31 last if !$token;
111 28         21 $token_type = $token->{type};
112 28 50 100     73 if (
      100        
      66        
113             $token_type == KEY ||
114             $token_type == TYPE_STDIN ||
115             $token_type == TYPE_STDOUT ||
116             $token_type == TYPE_STDERR
117             ) {
118 28         25 $variable .= $token->{data};
119 28         19 $token_type = VAR; # XXX
120             }
121             } ## fall through
122              
123 6605 100       11106 if ($var_token_types{$token_type}) {
124 974         630 my $line = $token->{line};
125              
126 974         735 my $before_token = $tokens->[$i-1];
127 974 50 33     2340 if ($before_token && $before_token->{type} == ASSIGN) {
128 0         0 next;
129             }
130              
131 974         642 $token = $tokens->[++$i];
132 974 50       1052 last if !$token;
133 974         610 $token_type = $token->{type};
134              
135 974 100       1396 if ($token_type == LEFT_BRACKET) {
    100          
136 11         11 my $lbnum = 1;
137 11         16 for ($i++; $token = $tokens->[$i]; $i++) {
138 22         14 $token_type = $token->{type};
139 22 50       44 if ($token_type == LEFT_BRACKET) {
    100          
140 0         0 $lbnum++;
141             }
142             elsif ($token_type == RIGHT_BRACKET) {
143 11 50       16 last if --$lbnum <= 0;
144             }
145             }
146 11         9 $token = $tokens->[++$i];
147              
148 11         13 substr($variable, 0, 1) = '@';
149             }
150             elsif ($token_type == LEFT_BRACE) {
151 12         9 my $lbnum = 1;
152 12         19 for ($i++; $token = $tokens->[$i]; $i++) {
153 24         11 $token_type = $token->{type};
154 24 50       50 if ($token_type == LEFT_BRACE) {
    100          
155 0         0 $lbnum++;
156             }
157             elsif ($token_type == RIGHT_BRACE) {
158 12 50       17 last if --$lbnum <= 0;
159             }
160             }
161 12         5 $token = $tokens->[++$i];
162              
163 12         12 substr($variable, 0, 1) = '%';
164             }
165              
166 974 50       998 last if !$token;
167              
168 974 100       1039 if ($token->{type} == RIGHT_PAREN) {
169 302         205 $token = $tokens->[++$i];
170 302 50       338 last if !$token;
171             }
172              
173 974 100       1083 next if $token->{type} != ASSIGN;
174              
175 968 100 100     2448 if ($globals{$variable} && !$exemptions{$variable}) {
176 501         1432 push @violations, {
177             filename => $file,
178             line => $line,
179             description => DESC,
180             explanation => EXPL,
181             policy => __PACKAGE__,
182             };
183             }
184             }
185             }
186              
187 15         90 return \@violations;
188             }
189              
190             1;
191