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   97513 use strict;
  133         282  
  133         4824  
3 133     133   575 use warnings;
  133         192  
  133         3388  
4 133     133   69836 use B::Keywords;
  133         140423  
  133         7874  
5 133     133   79293 use List::MoreUtils qw/apply uniq/;
  133         1354052  
  133         1300  
6 133     133   86802 use Perl::Lint::Constants::Type;
  133         247  
  133         89470  
7 133     133   950 use parent "Perl::Lint::Policy";
  133         211  
  133         1278  
8              
9             use constant {
10 133         115385 DESC => 'Magic variable "%s" should be assigned as "local"',
11             EXPL => [81, 82],
12 133     133   9684 };
  133         224  
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 40 my ($class, $file, $tokens, $src, $args) = @_;
41              
42 15         52 my @exemptions = qw/$_ $ARG @_/;
43 15 100       55 if (my $this_policies_arg = $args->{require_localized_punctuation_vars}) {
44 2   50     42 push @exemptions, split(/\s+/, $this_policies_arg->{allow} || '');
45             }
46 15         45 my %exemptions = map { $_ => 1 } @exemptions;
  200         353  
47              
48 15         35 my @violations;
49 15         69 for (my $i = 0, my $token_type, my $variable; my $token = $tokens->[$i]; $i++) {
50 7243         7018 $token_type = $token->{type};
51              
52 7243 100       9154 if ($token_type == LOCAL_DECL) {
53 638         529 $token = $tokens->[++$i];
54              
55 638 50       840 last if !$token;
56 638 100       932 if ($token->{type} == LEFT_PAREN) {
57 155         107 my $lpnum = 1;
58 155         239 for ($i++; $token = $tokens->[$i]; $i++) {
59 344         304 $token_type = $token->{type};
60              
61 344 50       730 if ($token_type == LEFT_PAREN) {
    100          
62 0         0 $lpnum++;
63             }
64             elsif ($token_type == RIGHT_PAREN) {
65 155 50       254 last if --$lpnum <= 0;
66             }
67             }
68             }
69              
70 638         1069 next;
71             }
72              
73 6605         5981 $variable = $token->{data};
74 6605 100       12959 if ($token_type == MOD) {
    100          
    100          
75 9         16 $token = $tokens->[++$i];
76 9         13 $token_type = $token->{type};
77              
78 9 50       18 last if !$token;
79 9 100       27 if ($token_type == NOT) {
    50          
80 4         9 $variable .= $token->{data};
81 4         6 $token_type = VAR; # XXX
82             }
83             elsif ($token_type == BIT_XOR) {
84 5         9 $variable .= $token->{data};
85              
86 5         8 $token = $tokens->[++$i];
87 5         6 $token_type = $token->{type};
88              
89 5 50       13 last if !$token;
90              
91 5 50       11 if ($token_type == KEY) {
92 5         8 $variable .= $token->{data};
93 5         9 $token_type = VAR; # XXX
94             }
95             }
96             }
97             elsif ($token_type == SPECIFIC_VALUE) {
98 303         293 $token = $tokens->[$i+1];
99 303 50       419 next if !$token;
100              
101 303 100       504 if ($token->{type} == KEY) {
102 110         84 $i++;
103 110         123 $variable .= $token->{data};
104 110         109 $token_type = SPECIFIC_VALUE;
105             }
106             }
107             elsif ($token_type == GLOB) {
108 28         35 $token = $tokens->[++$i];
109              
110 28 50       91 last if !$token;
111 28         36 $token_type = $token->{type};
112 28 50 100     128 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         37 $variable .= $token->{data};
119 28         26 $token_type = VAR; # XXX
120             }
121             } ## fall through
122              
123 6605 100       14731 if ($var_token_types{$token_type}) {
124 974         834 my $line = $token->{line};
125              
126 974         820 my $before_token = $tokens->[$i-1];
127 974 50 33     2883 if ($before_token && $before_token->{type} == ASSIGN) {
128 0         0 next;
129             }
130              
131 974         915 $token = $tokens->[++$i];
132 974 50       1428 last if !$token;
133 974         891 $token_type = $token->{type};
134              
135 974 100       1693 if ($token_type == LEFT_BRACKET) {
    100          
136 11         11 my $lbnum = 1;
137 11         24 for ($i++; $token = $tokens->[$i]; $i++) {
138 22         21 $token_type = $token->{type};
139 22 50       58 if ($token_type == LEFT_BRACKET) {
    100          
140 0         0 $lbnum++;
141             }
142             elsif ($token_type == RIGHT_BRACKET) {
143 11 50       41 last if --$lbnum <= 0;
144             }
145             }
146 11         14 $token = $tokens->[++$i];
147              
148 11         16 substr($variable, 0, 1) = '@';
149             }
150             elsif ($token_type == LEFT_BRACE) {
151 12         12 my $lbnum = 1;
152 12         21 for ($i++; $token = $tokens->[$i]; $i++) {
153 24         24 $token_type = $token->{type};
154 24 50       59 if ($token_type == LEFT_BRACE) {
    100          
155 0         0 $lbnum++;
156             }
157             elsif ($token_type == RIGHT_BRACE) {
158 12 50       21 last if --$lbnum <= 0;
159             }
160             }
161 12         10 $token = $tokens->[++$i];
162              
163 12         16 substr($variable, 0, 1) = '%';
164             }
165              
166 974 50       1269 last if !$token;
167              
168 974 100       1469 if ($token->{type} == RIGHT_PAREN) {
169 302         273 $token = $tokens->[++$i];
170 302 50       416 last if !$token;
171             }
172              
173 974 100       1501 next if $token->{type} != ASSIGN;
174              
175 968 100 100     3229 if ($globals{$variable} && !$exemptions{$variable}) {
176 510         2115 push @violations, {
177             filename => $file,
178             line => $line,
179             description => DESC,
180             explanation => EXPL,
181             policy => __PACKAGE__,
182             };
183             }
184             }
185             }
186              
187 15         211 return \@violations;
188             }
189              
190             1;
191