File Coverage

blib/lib/Perl/Critic/Policy/BuiltinFunctions/ProhibitStringyEval.pm
Criterion Covered Total %
statement 73 73 100.0
branch 43 54 79.6
condition 3 3 100.0
subroutine 16 16 100.0
pod 4 5 80.0
total 139 151 92.0


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval;
2              
3 40     40   26919 use 5.010001;
  40         239  
4 40     40   290 use strict;
  40         160  
  40         853  
5 40     40   231 use warnings;
  40         122  
  40         1171  
6              
7 40     40   254 use Readonly;
  40         176  
  40         2070  
8              
9 40     40   332 use PPI::Document;
  40         122  
  40         1422  
10              
11 40     40   262 use Perl::Critic::Utils qw{ :booleans :severities :classification :ppi $SCOLON };
  40         155  
  40         2275  
12 40     40   17133 use parent 'Perl::Critic::Policy';
  40         135  
  40         283  
13              
14             our $VERSION = '1.148';
15              
16             #-----------------------------------------------------------------------------
17              
18             Readonly::Scalar my $DESC => q{Expression form of "eval"};
19             Readonly::Scalar my $EXPL => [ 161 ];
20              
21             #-----------------------------------------------------------------------------
22              
23             # The maximum number of statements that may appear in an import-only eval
24             # string:
25             Readonly::Scalar my $MAX_STATEMENTS => 3;
26              
27             #-----------------------------------------------------------------------------
28              
29             sub supported_parameters {
30             return (
31             {
32 98     98 0 2062 name => 'allow_includes',
33             description => q<Allow eval of "use" and "require" strings.>,
34             default_string => '0',
35             behavior => 'boolean',
36             },
37             );
38             }
39 133     133 1 574 sub default_severity { return $SEVERITY_HIGHEST }
40 92     92 1 402 sub default_themes { return qw( core pbp bugs certrule ) }
41 44     44 1 170 sub applies_to { return 'PPI::Token::Word' }
42              
43             #-----------------------------------------------------------------------------
44              
45             sub violates {
46 458     458 1 979 my ( $self, $elem, undef ) = @_;
47              
48 458 100       985 return if $elem->content() ne 'eval';
49 105 100       756 return if not is_function_call($elem);
50              
51 103         336 my $argument = first_arg($elem);
52 103 100       400 return if not $argument;
53 101 100       373 return if $argument->isa('PPI::Structure::Block');
54             return if
55 99 100 100     344 $self->{_allow_includes} and _string_eval_is_an_include($argument);
56              
57 59         1378 return $self->violation( $DESC, $EXPL, $elem );
58             }
59              
60             sub _string_eval_is_an_include {
61 48     48   114 my ($eval_argument) = @_;
62              
63 48 50       141 return if not $eval_argument->isa('PPI::Token::Quote');
64              
65 48         158 my $string = $eval_argument->string();
66 48         321 my $document;
67              
68 48 50       88 eval { $document = PPI::Document->new(\$string); 1 }
  48         173  
  48         72203  
69             or return;
70              
71 48         161 my @statements = $document->schildren;
72              
73 48 100       593 return if @statements > $MAX_STATEMENTS;
74              
75 47         100 my $structure = join q{,}, map { $_->class } @statements;
  92         329  
76              
77 47         342 my $package_class = qr{PPI::Statement::Package}xms;
78 47         134 my $include_class = qr{PPI::Statement::Include}xms;
79 47         104 my $statement_class = qr{PPI::Statement}xms;
80              
81 47 100       503 return if $structure !~ m{
82             ^
83             (?:$package_class,)? # Optional "package"
84             $include_class
85             (?:,$statement_class)? # Optional follow-on number
86             $
87             }xms;
88              
89 45 100       286 my $is_q = $eval_argument->isa('PPI::Token::Quote::Single')
90             or $eval_argument->isa('PPI::Token::Quote::Literal');
91              
92 45         122 for my $statement (@statements) {
93 89 100       432 if ( $statement->isa('PPI::Statement::Package') ) {
    100          
94 22 50       64 _string_eval_accept_package($statement) or return;
95             } elsif ( $statement->isa('PPI::Statement::Include') ) {
96 45 100       97 _string_eval_accept_include( $statement, $is_q ) or return;
97             } else {
98 22 100       54 _string_eval_accept_follow_on($statement) or return;
99             }
100             }
101              
102 40         292 return $TRUE;
103             }
104              
105             sub _string_eval_accept_package {
106 22     22   50 my ($package) = @_;
107              
108 22 50       59 return if not defined $package; # RT 60179
109 22 50       70 return if not $package->isa('PPI::Statement::Package');
110 22 50       70 return if not $package->file_scoped;
111              
112 22         702 return $TRUE;
113             }
114              
115             sub _string_eval_accept_include {
116 45     45   96 my ( $include, $is_single_quoted ) = @_;
117              
118 45 50       112 return if not defined $include; # RT 60179
119 45 50       131 return if not $include->isa('PPI::Statement::Include');
120 45 100       168 return if $include->type() eq 'no';
121              
122 44 100       1061 if ($is_single_quoted) {
123             # Don't allow funky inclusion of arbitrary code (note we do allow
124             # interpolated values in interpolating strings because they can't
125             # entirely screw with the syntax).
126 36 100       101 return if $include->find('PPI::Token::Symbol');
127             }
128              
129 42         9726 return $TRUE;
130             }
131              
132             sub _string_eval_accept_follow_on {
133 22     22   53 my ($follow_on) = @_;
134              
135 22 50       68 return if not $follow_on->isa('PPI::Statement');
136              
137 22         57 my @follow_on_components = $follow_on->schildren();
138              
139 22 50       251 return if @follow_on_components > 2;
140 22 100       86 return if not $follow_on_components[0]->isa('PPI::Token::Number');
141 20 50       44 return $TRUE if @follow_on_components == 1;
142              
143 20         64 return $follow_on_components[1]->content() eq $SCOLON;
144             }
145              
146             1;
147              
148             __END__
149              
150             #-----------------------------------------------------------------------------
151              
152             =pod
153              
154             =for stopwords SIGNES
155              
156             =head1 NAME
157              
158             Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval - Write C<eval { my $foo; bar($foo) }> instead of C<eval "my $foo; bar($foo);">.
159              
160              
161             =head1 AFFILIATION
162              
163             This Policy is part of the core L<Perl::Critic|Perl::Critic>
164             distribution.
165              
166              
167             =head1 DESCRIPTION
168              
169             The string form of C<eval> is recompiled every time it is executed,
170             whereas the block form is only compiled once. Also, the string form
171             doesn't give compile-time warnings.
172              
173             eval "print $foo"; # not ok
174             eval {print $foo}; # ok
175              
176              
177             =head1 CONFIGURATION
178              
179             There is an C<allow_includes> boolean option for this Policy. If set, then
180             strings that look like they only include an optional "package" statement
181             followed by a single "use" or "require" statement (with the possible following
182             statement that consists of a single number) are allowed. With this option
183             set, the following are flagged as indicated:
184              
185             eval 'use Foo'; # ok
186             eval 'require Foo'; # ok
187             eval "use $thingy;"; # ok
188             eval "require $thingy;"; # ok
189             eval 'package Pkg; use Foo'; # ok
190             eval 'package Pkg; require Foo'; # ok
191             eval "package $pkg; use $thingy;"; # ok
192             eval "package $pkg; require $thingy;"; # ok
193             eval "use $thingy; 1;"; # ok
194             eval "require $thingy; 1;"; # ok
195             eval "package $pkg; use $thingy; 1;"; # ok
196             eval "package $pkg; require $thingy; 1;"; # ok
197              
198             eval 'use Foo; blah;'; # still not ok
199             eval 'require Foo; 2; 1;'; # still not ok
200             eval 'use $thingy;'; # still not ok
201             eval 'no Foo'; # still not ok
202              
203             If you don't understand why the number is allowed, see
204             L<Perl::Critic::Policy::ErrorHandling::RequireCheckingReturnValueOfEval|Perl::Critic::Policy::ErrorHandling::RequireCheckingReturnValueOfEval>.
205              
206             This option inspired by Ricardo SIGNES'
207             L<Perl::Critic::Policy::Lax::ProhibitStringyEval::ExceptForRequire|Perl::Critic::Policy::Lax::ProhibitStringyEval::ExceptForRequire>.
208              
209              
210             =head1 SEE ALSO
211              
212             L<Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep|Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep>
213              
214             L<Perl::Critic::Policy::BuiltinFunctions::RequireBlockMap|Perl::Critic::Policy::BuiltinFunctions::RequireBlockMap>
215              
216              
217             =head1 AUTHOR
218              
219             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
220              
221              
222             =head1 COPYRIGHT
223              
224             Copyright (c) 2005-2011 Imaginative Software Systems. All rights reserved.
225              
226             This program is free software; you can redistribute it and/or modify
227             it under the same terms as Perl itself. The full text of this license
228             can be found in the LICENSE file included with this module.
229              
230             =cut
231              
232             # Local Variables:
233             # mode: cperl
234             # cperl-indent-level: 4
235             # fill-column: 78
236             # indent-tabs-mode: nil
237             # c-indentation-style: bsd
238             # End:
239             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :