File Coverage

blib/lib/Perl/Critic/Policy/TryTiny/RequireUse.pm
Criterion Covered Total %
statement 33 35 94.2
branch 8 12 66.6
condition 12 21 57.1
subroutine 11 12 91.6
pod 4 5 80.0
total 68 85 80.0


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::TryTiny::RequireUse;
2              
3             $Perl::Critic::Policy::TryTiny::RequireUse::VERSION = '0.04';
4              
5 1     1   311072 use strict;
  1         3  
  1         25  
6 1     1   5 use warnings;
  1         2  
  1         23  
7              
8 1     1   5 use Readonly;
  1         1  
  1         45  
9 1     1   6 use Perl::Critic::Utils qw{ :severities :classification :ppi };
  1         1  
  1         60  
10              
11 1     1   348 use base 'Perl::Critic::Policy';
  1         3  
  1         455  
12              
13             Readonly::Scalar my $DESC => q{Missing "use Try::Tiny"};
14             Readonly::Scalar my $EXPL => q{Try::Tiny blocks will execute even if the try/catch/finally functions have not been imported};
15              
16 5     5 0 1241664 sub supported_parameters { return() }
17 2     2 1 33 sub default_severity { return $SEVERITY_HIGHEST }
18 0     0 1 0 sub default_themes { return qw( bugs ) }
19 5     5 1 458066 sub applies_to { return 'PPI::Token::Word' }
20              
21             sub violates {
22 26     26 1 826 my ($self, $try, $doc) = @_;
23              
24             return
25 26 50 66     57 unless $try->content() eq 'try'
      66        
26             and $try->snext_sibling()
27             and $try->snext_sibling->isa('PPI::Structure::Block');
28              
29 3         225 my $try_package = _find_package( $try );
30              
31             my $included = $doc->find_any(sub{
32 63 50 66 63   683 $_[1]->isa('PPI::Statement::Include')
      33        
      66        
      33        
33             and
34             defined( $_[1]->module() )
35             and (
36             $_[1]->module() eq 'Error'
37             or
38             $_[1]->module() eq 'Syntax::Feature::Try'
39             or
40             $_[1]->module() eq 'Try'
41             or
42             $_[1]->module() eq 'Try::Catch'
43             or
44             $_[1]->module() eq 'Try::Tiny'
45             or
46             $_[1]->module() eq 'TryCatch'
47             ) and
48             $_[1]->type() eq 'use'
49             and
50             _find_package( $_[1] ) eq $try_package
51 3         99 });
52              
53 3 100       74 return if $included;
54              
55 2         15 return $self->violation( $DESC, $EXPL, $try );
56             }
57              
58             sub _find_package {
59 5     5   308 my ($element) = @_;
60              
61 5         11 my $original = $element;
62              
63 5         18 while ($element) {
64 14 100       253 if ($element->isa('PPI::Statement::Package')) {
65             # If this package statements is a block package, meaning: package { # stuff in package }
66             # then if we're a descendant of it its our package.
67 5 50       21 return $element->namespace() if $element->ancestor_of( $original );
68              
69             # If we've hit a non-block package then thats our package.
70 5         80 my $blocks = $element->find_any('PPI::Structure::Block');
71 5 50       1281 return $element->namespace() if !$blocks;
72             }
73              
74             # Keep walking backwards until we match the above logic or we get to
75             # the document root (main).
76 9   66     33 $element = $element->sprevious_sibling() || $element->parent();
77             }
78              
79 0           return 'main';
80             }
81              
82             1;
83             __END__
84              
85             =head1 NAME
86              
87             Perl::Critic::Policy::TryTiny::RequireUse - Requires that code which utilizes
88             Try::Tiny actually use()es it.
89              
90             =head1 DESCRIPTION
91              
92             A common problem with L<Try::Tiny> is forgetting to use the module in the first
93             place. For example:
94              
95             perl -e 'try { print "hello" } catch { print "world" }'
96             Can't call method "catch" without a package or object reference at -e line 1.
97             helloworld
98              
99             If you forget this then both code blocks will be run and an exception will be thrown.
100             While this seems like a rare issue, when I first implemented this policy I found
101             several cases of this issue in real live code and due to layers of exception handling
102             it had gotten lost and nobody realized that there was a bug happening due to the missing
103             use statements.
104              
105             This policy is OK if you use L<Error>, L<Syntax::Feature::Try>, L<Try>, L<Try::Catch>,
106             and L<TryCatch> modules which also export the C<try> function.
107              
108             =head1 SEE ALSO
109              
110             =over
111              
112             =item *
113              
114             The L<Perl::Critic::Policy::Dynamic::NoIndirect> policy provides a more generic
115             solution to this problem (as the author has reported to me). Consider it as an
116             alternative to this policy.
117              
118             =back
119              
120             =head1 AUTHOR
121              
122             Aran Clary Deltac <bluefeetE<64>gmail.com>
123              
124             =head1 CONTRIBUTORS
125              
126             =over
127              
128             =item *
129              
130             Graham TerMarsch <grahamE<64>howlingfrog.com>
131              
132             =back
133              
134             =head1 ACKNOWLEDGEMENTS
135              
136             Thanks to L<ZipRecruiter|https://www.ziprecruiter.com/>
137             for encouraging their employees to contribute back to the open
138             source ecosystem. Without their dedication to quality software
139             development this distribution would not exist.
140              
141             =head1 LICENSE
142              
143             This library is free software; you can redistribute it and/or modify
144             it under the same terms as Perl itself.
145