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   103936 use strict;
  133         307  
  133         6479  
3 133     133   654 use warnings;
  133         1142  
  133         3719  
4 133     133   963 use Perl::Lint::Constants::Type;
  133         204  
  133         91875  
5 133     133   819 use parent "Perl::Lint::Policy";
  133         324  
  133         801  
6              
7             use constant {
8 133         130456 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   8852 };
  133         240  
11              
12             sub evaluate {
13 17     17 0 31 my ($class, $file, $tokens, $args) = @_;
14              
15 17         22 my @violations;
16 17         22 my $token_num = scalar @$tokens;
17 17         19 my $assigned = 0;
18 17         21 my $is_in_grep = 0;
19 17         18 my $left_paren_num = 0;
20 17         16 my $left_brace_num = 0;
21 17         15 my $left_bracket_num = 0;
22 17         38 for (my $i = 0; $i < $token_num; $i++) {
23 719         633 my $token = $tokens->[$i];
24 719         583 my $token_type = $token->{type};
25 719         662 my $token_data = $token->{data};
26              
27 719 100 100     6075 if ($token_type == ASSIGN) {
    100 100        
    100 100        
    100 100        
    100 100        
    100 66        
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
28 29         48 $assigned = 1;
29             }
30             elsif ($token_type == COMMA) {
31 23 100 66     107 if (
      100        
32             $left_paren_num <= 0 &&
33             $left_brace_num <= 0 &&
34             $left_bracket_num <= 0
35             ) {
36 17         29 $assigned = 0;
37             }
38             }
39             elsif ($token_type == LEFT_PAREN) {
40 14         82 $left_paren_num++;
41             }
42             elsif ($token_type == LEFT_BRACE) {
43 97         179 $left_brace_num++;
44             }
45             elsif ($token_type == LEFT_BRACKET) {
46 11         21 $left_bracket_num++;
47             }
48             elsif ($token_type == RIGHT_PAREN) {
49 14         23 $left_paren_num--;
50             }
51             elsif ($token_type == RIGHT_BRACE) {
52 96         207 $left_brace_num--;
53             }
54             elsif ($token_type == RIGHT_BRACKET) {
55 11         21 $left_bracket_num--;
56             }
57             elsif ($token_type == BUILTIN_FUNC && $token_data eq 'grep') {
58 1         4 $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         26 my $is_ternary = 0;
67 36         26 my $is_proper = 0;
68 36         30 my $left_brace_num = 0;
69              
70             # XXX not good cuz run twice
71 36         56 for (my $j = $i + 1; $j < $token_num; $j++) {
72 266         242 my $token = $tokens->[$j];
73 266         226 my $token_type = $token->{type};
74              
75 266 100 100     1691 if ($token_type == LEFT_BRACE) {
    100 66        
    100 100        
    100 100        
    100          
76 37         56 $left_brace_num++;
77             }
78             elsif ($token_type == RIGHT_BRACE) {
79 43         59 $left_brace_num--;
80             }
81             elsif ($token_type == THREE_TERM_OP) {
82 2         3 $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         15 $is_proper = 1;
94             }
95             elsif (
96             $left_brace_num <= 0 &&
97             $token_type == SEMI_COLON ||
98             !$tokens->[$j+1]
99             ) {
100 36         36 last;
101             }
102             }
103              
104 36 100 66     92 if (!$is_ternary && !$is_proper) {
105 26         159 push @violations, {
106             filename => $file,
107             line => $token->{line},
108             description => DESC,
109             explanation => EXPL,
110             policy => __PACKAGE__,
111             };
112             }
113             }
114             elsif ($token_type == IF_STATEMENT) {
115 28         24 my $left_paren_num = 0;
116 28         29 my $left_paren_found = 0;
117 28         24 my $exists_eval = 0;
118 28         22 my $exists_eval_global = 0;
119 28         22 my $exists_comma = 0;
120 28         56 my $last_token = {type => -1, data => ''};
121 28         53 for ($i++; $i < $token_num; $i++) {
122 254         203 my $token = $tokens->[$i];
123 254         217 my $token_type = $token->{type};
124              
125 254 100 100     717 if ($token_type == BUILTIN_FUNC && $token->{data} eq 'eval') {
    100          
    100          
    100          
126 30         28 $exists_eval = 1;
127 30         21 $exists_eval_global = 1;
128             }
129             elsif ($token_type == COMMA) {
130 22         18 $exists_comma = 1;
131              
132 22         19 my $next_token = $tokens->[$i + 1];
133 22         20 my $next_token_type = $next_token->{type};
134 22 100 100     60 if (
135             $next_token_type != COMMA &&
136             $next_token_type != RIGHT_PAREN
137             ) {
138 16         14 $last_token = $next_token;
139             }
140             }
141             elsif ($token_type == LEFT_PAREN) {
142 41         38 $left_paren_num++;
143 41         31 $left_paren_found++;
144 41         31 $exists_eval = 0;
145 41         32 $exists_comma = 0;
146             }
147             elsif ($token_type == RIGHT_PAREN) {
148 41 100 66     236 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 8         27 push @violations, {
154             filename => $file,
155             line => $token->{line},
156             description => DESC,
157             explanation => EXPL,
158             policy => __PACKAGE__,
159             };
160             }
161 41         35 $left_paren_num--;
162 41         30 $exists_eval = 0;
163 41         35 $exists_comma = 0;
164             }
165              
166 254 100 100     1459 if (
      66        
      100        
167             ($left_paren_num <= 0 && $left_paren_found) ||
168             $token == SEMI_COLON ||
169             !$tokens->[$i+1]
170             ) {
171 28         81 last;
172             }
173             }
174             }
175             elsif (
176             $token_type == FOREACH_STATEMENT ||
177             $token_type == WHILE_STATEMENT
178             ) {
179 21         18 my $left_paren_num = 0;
180 21         17 my $left_paren_found = 0;
181 21         36 for ($i++; $i < $token_num; $i++) {
182 187         140 my $token = $tokens->[$i];
183 187         158 my $token_type = $token->{type};
184              
185 187 100       300 if ($token_type == LEFT_PAREN) {
    100          
186 26         22 $left_paren_num++;
187 26         20 $left_paren_found++;
188             }
189             elsif ($token_type == RIGHT_PAREN) {
190 26         18 $left_paren_num--;
191             }
192              
193 187 100 100     1159 if (
      66        
      100        
194             ($left_paren_num <= 0 && $left_paren_found) ||
195             $token == SEMI_COLON ||
196             !$tokens->[$i+1]
197             ) {
198 21         46 last;
199             }
200             }
201             }
202             elsif ($token_type == FOR_STATEMENT) {
203 12         12 my $left_paren_num = 0;
204 12         9 my $left_paren_found = 0;
205 12         9 my $assigned = 0;
206 12         12 my $block = 1;
207 12         17 for ($i++; $i < $token_num; $i++) {
208 145         141 my $token = $tokens->[$i];
209 145         124 my $token_type = $token->{type};
210              
211 145 100 100     574 if ($token_type == ASSIGN) {
    100 100        
    100 66        
    100          
    100          
212 4         6 $assigned = 1;
213             }
214             elsif ($token_type == LEFT_PAREN) {
215 16         10 $left_paren_num++;
216 16         13 $left_paren_found++;
217             }
218             elsif ($token_type == RIGHT_PAREN) {
219 16         13 $left_paren_num--;
220             }
221             elsif ($token_type == SEMI_COLON) {
222 31         26 $block++;
223 31         26 $assigned = 0;
224             }
225             elsif (
226             !$assigned &&
227             $block & 1 &&
228             $token_type == BUILTIN_FUNC &&
229             $token->{data} eq 'eval'
230             ) {
231 4         12 push @violations, {
232             filename => $file,
233             line => $token->{line},
234             description => DESC,
235             explanation => EXPL,
236             policy => __PACKAGE__,
237             };
238             }
239              
240 145 100 66     358 if ($left_paren_num <= 0 && $left_paren_found) {
241 12         27 last;
242             }
243             }
244             }
245             elsif ($token_type == SEMI_COLON || !$tokens->[$i+1]) {
246 75         58 $assigned = 0;
247 75         134 $is_in_grep = 0;
248             }
249             }
250 17         111 return \@violations;
251             }
252              
253             1;
254