File Coverage

blib/lib/Perl/Lint/Policy/ErrorHandling/RequireCheckingReturnValueOfEval.pm
Criterion Covered Total %
statement 111 111 100.0
branch 74 74 100.0
condition 76 87 87.3
subroutine 6 6 100.0
pod 0 1 0.0
total 267 279 95.7


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::ErrorHandling::RequireCheckingReturnValueOfEval;
2 133     133   72244 use strict;
  133         182  
  133         3145  
3 133     133   426 use warnings;
  133         153  
  133         2491  
4 133     133   801 use Perl::Lint::Constants::Type;
  133         147  
  133         60756  
5 133     133   573 use parent "Perl::Lint::Policy";
  133         171  
  133         549  
6              
7             use constant {
8 133         93159 DESC => 'Return value of eval not tested.',
9             EXPL => q{You can't depend upon the value of $@/$EVAL_ERROR to tell whether an eval failed.},
10 133     133   6912 };
  133         167  
11              
12             sub evaluate {
13 17     17 0 25 my ($class, $file, $tokens, $args) = @_;
14              
15 17         15 my @violations;
16 17         16 my $token_num = scalar @$tokens;
17 17         11 my $assigned = 0;
18 17         12 my $is_in_grep = 0;
19 17         13 my $left_paren_num = 0;
20 17         11 my $left_brace_num = 0;
21 17         10 my $left_bracket_num = 0;
22 17         33 for (my $i = 0; $i < $token_num; $i++) {
23 719         514 my $token = $tokens->[$i];
24 719         452 my $token_type = $token->{type};
25 719         494 my $token_data = $token->{data};
26              
27 719 100 100     5074 if ($token_type == ASSIGN) {
    100 100        
    100 100        
    100 100        
    100 100        
    100 66        
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
28 29         41 $assigned = 1;
29             }
30             elsif ($token_type == COMMA) {
31 23 100 66     90 if (
      100        
32             $left_paren_num <= 0 &&
33             $left_brace_num <= 0 &&
34             $left_bracket_num <= 0
35             ) {
36 17         24 $assigned = 0;
37             }
38             }
39             elsif ($token_type == LEFT_PAREN) {
40 14         16 $left_paren_num++;
41             }
42             elsif ($token_type == LEFT_BRACE) {
43 97         116 $left_brace_num++;
44             }
45             elsif ($token_type == LEFT_BRACKET) {
46 11         15 $left_bracket_num++;
47             }
48             elsif ($token_type == RIGHT_PAREN) {
49 14         20 $left_paren_num--;
50             }
51             elsif ($token_type == RIGHT_BRACE) {
52 96         122 $left_brace_num--;
53             }
54             elsif ($token_type == RIGHT_BRACKET) {
55 11         15 $left_bracket_num--;
56             }
57             elsif ($token_type == BUILTIN_FUNC && $token_data eq 'grep') {
58 1         2 $is_in_grep = 1;
59             }
60             elsif (
61             !$assigned &&
62             !$is_in_grep &&
63             $token_type == BUILTIN_FUNC &&
64             $token_data eq 'eval'
65             ) {
66 36         29 my $is_ternary = 0;
67 36         22 my $is_proper = 0;
68 36         24 my $left_brace_num = 0;
69              
70             # XXX not good cuz run twice
71 36         48 for (my $j = $i + 1; $j < $token_num; $j++) {
72 266         175 my $token = $tokens->[$j];
73 266         176 my $token_type = $token->{type};
74              
75 266 100 100     1408 if ($token_type == LEFT_BRACE) {
    100 66        
    100 100        
    100 100        
    100          
76 37         43 $left_brace_num++;
77             }
78             elsif ($token_type == RIGHT_BRACE) {
79 43         58 $left_brace_num--;
80             }
81             elsif ($token_type == THREE_TERM_OP) {
82 2         4 $is_ternary = 1;
83             }
84             elsif (
85             $left_brace_num <= 0 &&
86             (
87             $token_type == AND ||
88             $token_type == OR ||
89             $token_type == ALPHABET_AND ||
90             $token_type == ALPHABET_OR
91             )
92             ) {
93 8         11 $is_proper = 1;
94             }
95             elsif (
96             $left_brace_num <= 0 &&
97             $token_type == SEMI_COLON ||
98             !$tokens->[$j+1]
99             ) {
100 36         32 last;
101             }
102             }
103              
104 36 100 66     71 if (!$is_ternary && !$is_proper) {
105             push @violations, {
106             filename => $file,
107             line => $token->{line},
108 26         90 description => DESC,
109             explanation => EXPL,
110             policy => __PACKAGE__,
111             };
112             }
113             }
114             elsif ($token_type == IF_STATEMENT) {
115 28         25 my $left_paren_num = 0;
116 28         16 my $left_paren_found = 0;
117 28         19 my $exists_eval = 0;
118 28         21 my $exists_eval_global = 0;
119 28         13 my $exists_comma = 0;
120 28         42 my $last_token = {type => -1, data => ''};
121 28         45 for ($i++; $i < $token_num; $i++) {
122 254         163 my $token = $tokens->[$i];
123 254         179 my $token_type = $token->{type};
124              
125 254 100 100     585 if ($token_type == BUILTIN_FUNC && $token->{data} eq 'eval') {
    100          
    100          
    100          
126 30         23 $exists_eval = 1;
127 30         17 $exists_eval_global = 1;
128             }
129             elsif ($token_type == COMMA) {
130 22         16 $exists_comma = 1;
131              
132 22         16 my $next_token = $tokens->[$i + 1];
133 22         15 my $next_token_type = $next_token->{type};
134 22 100 100     100 if (
135             $next_token_type != COMMA &&
136             $next_token_type != RIGHT_PAREN
137             ) {
138 16         10 $last_token = $next_token;
139             }
140             }
141             elsif ($token_type == LEFT_PAREN) {
142 41         20 $left_paren_num++;
143 41         24 $left_paren_found++;
144 41         27 $exists_eval = 0;
145 41         26 $exists_comma = 0;
146             }
147             elsif ($token_type == RIGHT_PAREN) {
148 41 100 66     170 if (
      66        
      66        
      100        
149             $last_token->{type} != BUILTIN_FUNC &&
150             $last_token->{data} ne 'eval' &&
151             ($exists_eval_global || $exists_eval) && $exists_comma
152             ) {
153             push @violations, {
154             filename => $file,
155             line => $token->{line},
156 8         22 description => DESC,
157             explanation => EXPL,
158             policy => __PACKAGE__,
159             };
160             }
161 41         27 $left_paren_num--;
162 41         23 $exists_eval = 0;
163 41         23 $exists_comma = 0;
164             }
165              
166 254 100 100     1204 if (
      66        
      100        
167             ($left_paren_num <= 0 && $left_paren_found) ||
168             $token == SEMI_COLON ||
169             !$tokens->[$i+1]
170             ) {
171 28         60 last;
172             }
173             }
174             }
175             elsif (
176             $token_type == FOREACH_STATEMENT ||
177             $token_type == WHILE_STATEMENT
178             ) {
179 21         16 my $left_paren_num = 0;
180 21         13 my $left_paren_found = 0;
181 21         28 for ($i++; $i < $token_num; $i++) {
182 187         133 my $token = $tokens->[$i];
183 187         113 my $token_type = $token->{type};
184              
185 187 100       254 if ($token_type == LEFT_PAREN) {
    100          
186 26         19 $left_paren_num++;
187 26         17 $left_paren_found++;
188             }
189             elsif ($token_type == RIGHT_PAREN) {
190 26         16 $left_paren_num--;
191             }
192              
193 187 100 100     913 if (
      66        
      100        
194             ($left_paren_num <= 0 && $left_paren_found) ||
195             $token == SEMI_COLON ||
196             !$tokens->[$i+1]
197             ) {
198 21         34 last;
199             }
200             }
201             }
202             elsif ($token_type == FOR_STATEMENT) {
203 12         10 my $left_paren_num = 0;
204 12         10 my $left_paren_found = 0;
205 12         4 my $assigned = 0;
206 12         11 my $block = 1;
207 12         15 for ($i++; $i < $token_num; $i++) {
208 145         125 my $token = $tokens->[$i];
209 145         95 my $token_type = $token->{type};
210              
211 145 100 100     478 if ($token_type == ASSIGN) {
    100 100        
    100 66        
    100          
    100          
212 4         3 $assigned = 1;
213             }
214             elsif ($token_type == LEFT_PAREN) {
215 16         8 $left_paren_num++;
216 16         13 $left_paren_found++;
217             }
218             elsif ($token_type == RIGHT_PAREN) {
219 16         9 $left_paren_num--;
220             }
221             elsif ($token_type == SEMI_COLON) {
222 31         18 $block++;
223 31         21 $assigned = 0;
224             }
225             elsif (
226             !$assigned &&
227             $block & 1 &&
228             $token_type == BUILTIN_FUNC &&
229             $token->{data} eq 'eval'
230             ) {
231             push @violations, {
232             filename => $file,
233             line => $token->{line},
234 4         10 description => DESC,
235             explanation => EXPL,
236             policy => __PACKAGE__,
237             };
238             }
239              
240 145 100 66     281 if ($left_paren_num <= 0 && $left_paren_found) {
241 12         18 last;
242             }
243             }
244             }
245             elsif ($token_type == SEMI_COLON || !$tokens->[$i+1]) {
246 75         59 $assigned = 0;
247 75         90 $is_in_grep = 0;
248             }
249             }
250 17         61 return \@violations;
251             }
252              
253             1;
254