File Coverage

blib/lib/Perl/Critic/Policy/ErrorHandling/RequireCheckingReturnValueOfEval.pm
Criterion Covered Total %
statement 122 125 97.6
branch 70 82 85.3
condition 29 36 80.5
subroutine 21 21 100.0
pod 4 5 80.0
total 246 269 91.4


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::ErrorHandling::RequireCheckingReturnValueOfEval;
2              
3 40     40   29485 use 5.010001;
  40         204  
4 40     40   8954 use strict;
  40         228  
  40         1109  
5 40     40   254 use warnings;
  40         111  
  40         1064  
6              
7 40     40   228 use Readonly;
  40         102  
  40         2025  
8              
9 40     40   292 use Scalar::Util qw< refaddr >;
  40         99  
  40         2260  
10              
11 40         2145 use Perl::Critic::Utils qw< :booleans :characters :severities hashify
12 40     40   295 precedence_of >;
  40         112  
13 40     40   15777 use parent 'Perl::Critic::Policy';
  40         141  
  40         288  
14              
15             our $VERSION = '1.146';
16              
17             #-----------------------------------------------------------------------------
18              
19             Readonly::Scalar my $DESC => 'Return value of eval not tested.';
20             ## no critic (RequireInterpolationOfMetachars)
21             Readonly::Scalar my $EXPL =>
22             q<You can't depend upon the value of $@/$EVAL_ERROR to tell whether an eval failed.>;
23             ## use critic
24              
25             Readonly::Hash my %BOOLEAN_OPERATORS => hashify qw< || && // or and >;
26             Readonly::Hash my %POSTFIX_OPERATORS =>
27             hashify qw< for foreach if unless while until >;
28              
29             Readonly::Scalar my $PRECEDENCE_OF_EQUALS => precedence_of( q{=} );
30              
31             #-----------------------------------------------------------------------------
32              
33 107     107 0 1658 sub supported_parameters { return () }
34 107     107 1 472 sub default_severity { return $SEVERITY_MEDIUM }
35 74     74 1 365 sub default_themes { return qw( core bugs ) }
36 19     19 1 68 sub applies_to { return 'PPI::Token::Word' }
37              
38             #-----------------------------------------------------------------------------
39              
40             sub violates {
41 384     384 1 761 my ( $self, $elem, undef ) = @_;
42              
43 384 100       820 return if $elem->content() ne 'eval';
44              
45 113 50       666 my $evaluated = $elem->snext_sibling() or return; # Nothing to eval!
46 113         3239 my $following = $evaluated->snext_sibling();
47              
48 113 100       2357 return if _is_returned( $elem ); # GitHub #324
49 111 100       341 return if _is_in_right_hand_side_of_assignment($elem);
50 89 100       224 return if _is_in_postfix_expression($elem);
51             return if
52 72 100       419 _is_in_correct_position_in_a_condition_or_foreach_loop_collection(
53             $elem,
54             $following,
55             );
56              
57 44 100       133 return if _scan_backwards_for_grep( $elem ); # RT 69489
58              
59 43 100 100     558 if ( $following and $following->isa('PPI::Token::Operator') ) {
60 14 100       45 return if $BOOLEAN_OPERATORS{ $following->content() };
61 6 100       110 return if q{?} eq $following->content;
62             }
63              
64 33         145 return $self->violation($DESC, $EXPL, $elem);
65             }
66              
67             #-----------------------------------------------------------------------------
68              
69             sub _is_in_right_hand_side_of_assignment {
70 111     111   254 my ($elem) = @_;
71              
72 111         256 my $previous = $elem->sprevious_sibling();
73              
74 111 100       2117 if (not $previous) {
75 67         173 $previous =
76             _grandparent_for_is_in_right_hand_side_of_assignment($elem);
77             }
78              
79 111         319 while ($previous) {
80 106         197 my $base_previous = $previous;
81              
82             EQUALS_SCAN:
83 106         295 while ($previous) {
84 171 100       1963 if ( $previous->isa('PPI::Token::Operator') ) {
85 59 100       183 return $TRUE if $previous->content() =~ m/= \Z/xms;
86 37 100       242 last EQUALS_SCAN if _is_effectively_a_comma($previous);
87             }
88 116         616 $previous = $previous->sprevious_sibling();
89             }
90              
91             $previous =
92 84         1253 _grandparent_for_is_in_right_hand_side_of_assignment($base_previous);
93             }
94              
95 89         218 return;
96             }
97              
98             sub _grandparent_for_is_in_right_hand_side_of_assignment {
99 151     151   331 my ($elem) = @_;
100              
101 151 50       432 my $parent = $elem->parent() or return;
102 151 50       1142 $parent->isa('PPI::Statement') or return;
103              
104 151 50       379 my $grandparent = $parent->parent() or return;
105              
106 151 100 100     1255 if (
107             $grandparent->isa('PPI::Structure::Constructor')
108             or $grandparent->isa('PPI::Structure::List')
109             ) {
110 62         733 return $grandparent;
111             }
112              
113 89         395 return;
114             }
115              
116             #-----------------------------------------------------------------------------
117              
118             Readonly::Scalar my $CONDITION_POSITION_IN_C_STYLE_FOR_LOOP => 1;
119              
120             sub _is_in_correct_position_in_a_condition_or_foreach_loop_collection {
121 72     72   178 my ($elem, $following) = @_;
122              
123 72         178 my $parent = $elem->parent();
124 72         377 while ($parent) {
125 248 100       1349 if ( $parent->isa('PPI::Structure::Condition') ) {
126             return
127 26         69 _is_in_correct_position_in_a_structure_condition(
128             $elem, $parent, $following,
129             );
130             }
131              
132             # TECHNICAL DEBT: This code is basically shared with
133             # ProhibitUnusedCapture. I don't want to put this code
134             # into Perl::Critic::Utils::*, but I don't have time to sort out
135             # PPIx::Utilities::Structure::List yet.
136 222 100 66     887 if (
137             $parent->isa('PPI::Structure::List')
138             and my $parent_statement = $parent->statement()
139             ) {
140 34 100 66     1051 return $TRUE if
141             $parent_statement->isa('PPI::Statement::Compound')
142             and $parent_statement->type() eq 'foreach';
143             }
144              
145 218 100       670 if ( $parent->isa('PPI::Structure::For') ) {
146 10         76 my @for_loop_components = $parent->schildren();
147              
148 10 50       156 my $condition =
149             $for_loop_components[$CONDITION_POSITION_IN_C_STYLE_FOR_LOOP]
150             or return;
151              
152 10         34 return _descendant_of($elem, $condition);
153             }
154              
155 208         622 $parent = $parent->parent();
156             }
157              
158 32         171 return;
159             }
160              
161             sub _is_in_correct_position_in_a_structure_condition {
162 26     26   72 my ($elem, $parent, $following) = @_;
163              
164 26         53 my $level = $elem;
165 26   33     137 while ($level and refaddr $level != $parent) {
166 60 100       632 my $cursor = refaddr $elem == refaddr $level ? $following : $level;
167              
168             IS_FINAL_EXPRESSION_AT_DEPTH:
169 60         170 while ($cursor) {
170 64 100       637 if ( _is_effectively_a_comma($cursor) ) {
171 12         87 $cursor = $cursor->snext_sibling();
172 12         315 while ( _is_effectively_a_comma($cursor) ) {
173 2         16 $cursor = $cursor->snext_sibling();
174             }
175              
176             # Semicolon would be a syntax error here.
177 12 100       55 return if $cursor;
178 4         10 last IS_FINAL_EXPRESSION_AT_DEPTH;
179             }
180              
181 52         256 $cursor = $cursor->snext_sibling();
182             }
183              
184 52         684 my $statement = $level->parent();
185 52 50       256 return $TRUE if not $statement; # Shouldn't happen.
186 52 50       152 return $TRUE if not $statement->isa('PPI::Statement'); # Shouldn't happen.
187              
188 52         115 $level = $statement->parent();
189 52 100 100     466 if (
      66        
190             not $level
191             or (
192             not $level->isa('PPI::Structure::List')
193             and not $level->isa('PPI::Structure::Condition')
194             )
195             ) {
196             # Shouldn't happen.
197 18         116 return $TRUE;
198             }
199             }
200              
201 0         0 return $TRUE;
202             }
203              
204             # Replace with PPI implementation once it is released.
205             sub _descendant_of {
206 10     10   23 my ($cursor, $potential_ancestor) = @_;
207              
208 10 50       25 return $EMPTY if not $potential_ancestor;
209              
210 10         37 while ( refaddr $cursor != refaddr $potential_ancestor ) {
211 34 100       167 $cursor = $cursor->parent() or return $EMPTY;
212             }
213              
214 6         55 return 1;
215             }
216              
217             #-----------------------------------------------------------------------------
218              
219             sub _is_in_postfix_expression {
220 89     89   184 my ($elem) = @_;
221              
222 89         154 my $current_base = $elem;
223 89         230 while ($TRUE) {
224 97         300 my $previous = $current_base->sprevious_sibling();
225 97         2012 while ($previous) {
226 69 100 100     1001 if (
227             $previous->isa('PPI::Token::Word')
228             and $POSTFIX_OPERATORS{ $previous->content() }
229             ) {
230 17         298 return $TRUE
231             }
232 52         251 $previous = $previous->sprevious_sibling();
233             } # end while
234              
235 80 50       481 my $parent = $current_base->parent() or return;
236 80 50       559 if ( $parent->isa('PPI::Statement') ) {
237 80 100       271 return if $parent->specialized();
238              
239 42 50       262 my $grandparent = $parent->parent() or return;
240 42 100       334 return if not $grandparent->isa('PPI::Structure::List');
241              
242 8         61 $current_base = $grandparent;
243             } else {
244 0         0 $current_base = $parent;
245             }
246              
247 8 50       23 return if not $current_base->isa('PPI::Structure::List');
248             }
249              
250 0         0 return;
251             }
252              
253             #-----------------------------------------------------------------------------
254              
255             sub _scan_backwards_for_grep {
256 44     44   86 my ( $elem ) = @_;
257              
258 44         144 while ( $elem ) {
259              
260 152         388 my $parent = $elem->parent();
261              
262 152         709 while ( $elem = $elem->sprevious_sibling() ) {
263 122 100 100     3800 $elem->isa( 'PPI::Token::Word' )
264             and 'grep' eq $elem->content()
265             and return $TRUE;
266 121 100 66     559 $elem->isa( 'PPI::Token::Operator' )
267             and precedence_of( $elem ) >= $PRECEDENCE_OF_EQUALS
268             and return $FALSE;
269             }
270              
271 128         2246 $elem = $parent;
272             }
273              
274 20         67 return $FALSE;
275              
276             }
277              
278             #-----------------------------------------------------------------------------
279              
280             sub _is_effectively_a_comma {
281 115     115   270 my ($elem) = @_;
282              
283 115 100       305 return if not $elem;
284              
285             return
286 111   66     481 $elem->isa('PPI::Token::Operator')
287             && (
288             $elem->content() eq $COMMA
289             || $elem->content() eq $FATCOMMA
290             );
291             }
292              
293             #-----------------------------------------------------------------------------
294             # GitHub #324 (https://github.com/Perl-Critic/Perl-Critic/issues/324)
295             {
296             Readonly::Scalar my $RETURN => 'return';
297              
298             sub _is_returned {
299 113     113   236 my ( $elem ) = @_;
300 113         320 my $prev = $elem->sprevious_sibling();
301             return
302 113   100     2712 $prev
303             &&
304             $prev->isa( 'PPI::Token::Word' )
305             &&
306             $RETURN eq $prev->content();
307             }
308             }
309              
310             #-----------------------------------------------------------------------------
311              
312             1;
313              
314             __END__
315              
316             #-----------------------------------------------------------------------------
317              
318             =pod
319              
320             =for stopwords destructors
321              
322             =head1 NAME
323              
324             Perl::Critic::Policy::ErrorHandling::RequireCheckingReturnValueOfEval - You can't depend upon the value of C<$@>/C<$EVAL_ERROR> to tell whether an C<eval> failed.
325              
326             =head1 AFFILIATION
327              
328             This Policy is part of the core L<Perl::Critic|Perl::Critic>
329             distribution.
330              
331              
332             =head1 DESCRIPTION
333              
334             A common idiom in perl for dealing with possible errors is to use
335             C<eval> followed by a check of C<$@>/C<$EVAL_ERROR>:
336              
337             eval {
338             ...
339             };
340             if ($EVAL_ERROR) {
341             ...
342             }
343              
344             There's a problem with this: the value of C<$EVAL_ERROR> can change
345             between the end of the C<eval> and the C<if> statement. The issue is
346             object destructors:
347              
348             package Foo;
349              
350             ...
351              
352             sub DESTROY {
353             ...
354             eval { ... };
355             ...
356             }
357              
358             package main;
359              
360             eval {
361             my $foo = Foo->new();
362             ...
363             };
364             if ($EVAL_ERROR) {
365             ...
366             }
367              
368             Assuming there are no other references to C<$foo> created, when the
369             C<eval> block in C<main> is exited, C<Foo::DESTROY()> will be invoked,
370             regardless of whether the C<eval> finished normally or not. If the
371             C<eval> in C<main> fails, but the C<eval> in C<Foo::DESTROY()>
372             succeeds, then C<$EVAL_ERROR> will be empty by the time that the C<if>
373             is executed. Additional issues arise if you depend upon the exact
374             contents of C<$EVAL_ERROR> and both C<eval>s fail, because the
375             messages from both will be concatenated.
376              
377             Even if there isn't an C<eval> directly in the C<DESTROY()> method
378             code, it may invoke code that does use C<eval> or otherwise affects
379             C<$EVAL_ERROR>.
380              
381             The solution is to ensure that, upon normal exit, an C<eval> returns a
382             true value and to test that value:
383              
384             # Constructors are no problem.
385             my $object = eval { Class->new() };
386              
387             # To cover the possibility that an operation may correctly return a
388             # false value, end the block with "1":
389             if ( eval { something(); 1 } ) {
390             ...
391             }
392              
393             eval {
394             ...
395             1;
396             }
397             or do {
398             # Error handling here
399             };
400              
401             Unfortunately, you can't use the C<defined> function to test the
402             result; C<eval> returns an empty string on failure.
403              
404             Various modules have been written to take some of the pain out of
405             properly localizing and checking C<$@>/C<$EVAL_ERROR>. For example:
406              
407             use Try::Tiny;
408             try {
409             ...
410             } catch {
411             # Error handling here;
412             # The exception is in $_/$ARG, not $@/$EVAL_ERROR.
413             }; # Note semicolon.
414              
415             "But we don't use DESTROY() anywhere in our code!" you say. That may
416             be the case, but do any of the third-party modules you use have them?
417             What about any you may use in the future or updated versions of the
418             ones you already use?
419              
420              
421             =head1 CONFIGURATION
422              
423             This Policy is not configurable except for the standard options.
424              
425              
426             =head1 SEE ALSO
427              
428             See thread on perl5-porters starting here:
429             L<http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2008-06/msg00537.html>.
430              
431             For a nice, easy, non-magical way of properly handling exceptions, see
432             L<Try::Tiny|Try::Tiny>.
433              
434              
435             =head1 AUTHOR
436              
437             Elliot Shank C<< <perl@galumph.com> >>
438              
439             =head1 COPYRIGHT
440              
441             Copyright (c) 2008-2011 Elliot Shank.
442              
443             This program is free software; you can redistribute it and/or modify
444             it under the same terms as Perl itself. The full text of this license
445             can be found in the LICENSE file included with this module.
446              
447             =cut
448              
449             # Local Variables:
450             # mode: cperl
451             # cperl-indent-level: 4
452             # fill-column: 78
453             # indent-tabs-mode: nil
454             # c-indentation-style: bsd
455             # End:
456             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :