File Coverage

blib/lib/Perl/Critic/Policy/Subroutines/RequireArgUnpacking.pm
Criterion Covered Total %
statement 132 139 94.9
branch 88 108 81.4
condition 44 66 66.6
subroutine 25 26 96.1
pod 4 5 80.0
total 293 344 85.1


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Subroutines::RequireArgUnpacking;
2              
3 40     40   28969 use 5.010001;
  40         161  
4 40     40   243 use strict;
  40         91  
  40         829  
5 40     40   202 use warnings;
  40         100  
  40         954  
6              
7 40     40   213 use Carp;
  40         89  
  40         2358  
8 40     40   261 use English qw(-no_match_vars);
  40         125  
  40         278  
9 40     40   14692 use Readonly;
  40         104  
  40         1918  
10              
11 40     40   280 use File::Spec;
  40         146  
  40         1544  
12              
13 40         2141 use Perl::Critic::Utils qw<
14             :booleans :characters :classification hashify :severities words_from_string
15 40     40   274 >;
  40         143  
16 40     40   22010 use parent 'Perl::Critic::Policy';
  40         143  
  40         290  
17              
18             our $VERSION = '1.148';
19              
20             #-----------------------------------------------------------------------------
21              
22             Readonly::Scalar my $AT => q{@};
23             Readonly::Scalar my $AT_ARG => q{@_}; ## no critic (InterpolationOfMetachars)
24             Readonly::Scalar my $DEREFERENCE => q{->};
25             Readonly::Scalar my $DOLLAR => q{$};
26             Readonly::Scalar my $DOLLAR_ARG => q{$_}; ## no critic (InterpolationOfMetaChars)
27              
28             Readonly::Scalar my $DESC => qq{Always unpack $AT_ARG first};
29             Readonly::Scalar my $EXPL => [178];
30              
31             #-----------------------------------------------------------------------------
32              
33             sub supported_parameters {
34             return (
35             {
36 117     117 0 3274 name => 'short_subroutine_statements',
37             description =>
38             'The number of statements to allow without unpacking.',
39             default_string => '0',
40             behavior => 'integer',
41             integer_minimum => 0,
42             },
43             {
44             name => 'allow_subscripts',
45             description =>
46             'Should unpacking from array slices and elements be allowed?',
47             default_string => $FALSE,
48             behavior => 'boolean',
49             },
50             {
51             name => 'allow_delegation_to',
52             description =>
53             'Allow the usual delegation idiom to these namespaces/subroutines',
54             behavior => 'string list',
55             list_always_present_values => [ qw< SUPER:: NEXT:: > ],
56             },
57             {
58             name => 'allow_closures',
59             description => 'Allow unpacking by a closure',
60             default_string => $FALSE,
61             behavior => 'boolean',
62             },
63             );
64             }
65              
66 87     87 1 450 sub default_severity { return $SEVERITY_HIGH }
67 86     86 1 392 sub default_themes { return qw( core pbp maintenance ) }
68 56     56 1 181 sub applies_to { return 'PPI::Statement::Sub' }
69              
70             #-----------------------------------------------------------------------------
71              
72             sub violates {
73 46     46 1 190 my ( $self, $elem, undef ) = @_;
74              
75             # forward declaration?
76 46 100       181 return if not $elem->block;
77              
78 45         1169 my @statements = $elem->block->schildren;
79              
80             # empty sub?
81 45 100       1671 return if not @statements;
82              
83             # Don't apply policy to short subroutines
84              
85             # Should we instead be doing a find() for PPI::Statement
86             # instances? That is, should we count all statements instead of
87             # just top-level statements?
88 44 100       158 return if $self->{_short_subroutine_statements} >= @statements;
89              
90             # look for explicit dereferences of @_, including '$_[0]'
91             # You may use "... = @_;" in the first paragraph of the sub
92             # Don't descend into nested or anonymous subs
93 43         117 my $state = 'unpacking'; # still in unpacking paragraph
94 43         95 for my $statement (@statements) {
95              
96 129         344 my @magic = _get_arg_symbols($statement);
97              
98 129         5569 my $saw_unpack = $FALSE;
99              
100             MAGIC:
101 129         277 for my $magic (@magic) {
102             # allow conditional checks on the size of @_
103 74 100       194 next MAGIC if _is_size_check($magic);
104              
105 30 100       179 if ('unpacking' eq $state) {
106 22 100       73 if ($self->_is_unpack($magic)) {
107 11         245 $saw_unpack = $TRUE;
108 11         37 next MAGIC;
109             }
110             }
111              
112             # allow @$_[] construct in "... for ();"
113             # Check for "print @$_[] for ()" construct (rt39601)
114             next MAGIC
115 19 50 33     440 if _is_cast_of_array($magic) and _is_postfix_foreach($magic);
116              
117             # allow $$_[], which is equivalent to $_->[] and not a use
118             # of @_ at all.
119             next MAGIC
120 19 50       63 if _is_cast_of_scalar( $magic );
121              
122             # allow delegation of the form "$self->SUPER::foo( @_ );"
123             next MAGIC
124 19 100       229 if $self->_is_delegation( $magic );
125              
126             # If we make it this far, it is a violation
127 13         177 return $self->violation( $DESC, $EXPL, $elem );
128             }
129 116 100       648 if (not $saw_unpack) {
130 105         241 $state = 'post_unpacking';
131             }
132             }
133 30         129 return; # OK
134             }
135              
136             sub _is_unpack {
137 22     22   57 my ($self, $magic) = @_;
138              
139 22         61 my $prev = $magic->sprevious_sibling();
140 22         546 my $next = $magic->snext_sibling();
141              
142             # If we have a subscript, we're dealing with an array slice on @_
143             # or an array element of @_. See RT #34009.
144 22 100 100     549 if ( $next and $next->isa('PPI::Structure::Subscript') ) {
145 10 100       50 $self->{_allow_subscripts} or return;
146 4         13 $next = $next->snext_sibling;
147             }
148              
149 16 50 100     211 return $TRUE if
      66        
      33        
      66        
150             $prev
151             and $prev->isa('PPI::Token::Operator')
152             and is_assignment_operator($prev->content())
153             and (
154             not $next
155             or $next->isa('PPI::Token::Structure')
156             and $SCOLON eq $next->content()
157             );
158 5         24 return;
159             }
160              
161             sub _is_size_check {
162 74     74   162 my ($magic) = @_;
163              
164             # No size check on $_[0]. RT #34009.
165 74 100       208 $AT eq $magic->raw_type or return;
166              
167 64         533 my $prev = $magic->sprevious_sibling;
168 64         1595 my $next = $magic->snext_sibling;
169              
170 64 100 100     1467 if ( $prev || $next ) {
171              
172 50 100 66     113 return $TRUE
173             if _legal_before_size_check( $prev )
174             and _legal_after_size_check( $next );
175             }
176              
177 24         232 my $parent = $magic;
178             {
179 24 50       43 $parent = $parent->parent()
  40         117  
180             or return;
181 40         270 $prev = $parent->sprevious_sibling();
182 40         930 $next = $parent->snext_sibling();
183 40 100 100     963 $prev
184             or $next
185             or redo;
186             } # until ( $prev || $next );
187              
188 24 100       117 return $TRUE
189             if $parent->isa( 'PPI::Structure::Condition' );
190              
191 20         141 return;
192             }
193              
194             {
195              
196             Readonly::Hash my %LEGAL_NEXT_OPER => hashify(
197             qw{ && || == != > >= < <= and or } );
198              
199             Readonly::Hash my %LEGAL_NEXT_STRUCT => hashify( qw{ ; } );
200              
201             sub _legal_after_size_check {
202 40     40   373 my ( $next ) = @_;
203              
204 40 100       150 $next
205             or return $TRUE;
206              
207             $next->isa( 'PPI::Token::Operator' )
208 28 100       104 and return $LEGAL_NEXT_OPER{ $next->content() };
209              
210             $next->isa( 'PPI::Token::Structure' )
211 6 50       25 and return $LEGAL_NEXT_STRUCT{ $next->content() };
212              
213 0         0 return;
214             }
215             }
216              
217             {
218              
219             Readonly::Hash my %LEGAL_PREV_OPER => hashify(
220             qw{ && || ! == != > >= < <= and or not } );
221              
222             Readonly::Hash my %LEGAL_PREV_WORD => hashify(
223             qw{ if unless } );
224              
225             sub _legal_before_size_check {
226 50     50   101 my ( $prev ) = @_;
227              
228 50 100       155 $prev
229             or return $TRUE;
230              
231             $prev->isa( 'PPI::Token::Operator' )
232 38 100       150 and return $LEGAL_PREV_OPER{ $prev->content() };
233              
234             $prev->isa( 'PPI::Token::Word' )
235 7 50       44 and return $LEGAL_PREV_WORD{ $prev->content() };
236              
237 0         0 return;
238             }
239              
240             }
241              
242             sub _is_postfix_foreach {
243 0     0   0 my ($magic) = @_;
244              
245 0         0 my $sibling = $magic;
246 0         0 while ( $sibling = $sibling->snext_sibling ) {
247 0 0 0     0 return $TRUE
248             if
249             $sibling->isa('PPI::Token::Word')
250             and $sibling =~ m< \A for (?:each)? \z >xms;
251             }
252 0         0 return;
253             }
254              
255             sub _is_cast_of_array {
256 19     19   59 my ($magic) = @_;
257              
258 19         53 my $prev = $magic->sprevious_sibling;
259              
260 19 50 66     418 return $TRUE
      33        
261             if ( $prev && $prev->content() eq $AT )
262             and $prev->isa('PPI::Token::Cast');
263 19         106 return;
264             }
265              
266             # This subroutine recognizes (e.g.) $$_[0]. This is a use of $_ (equivalent to
267             # $_->[0]), not @_.
268              
269             sub _is_cast_of_scalar {
270 19     19   49 my ($magic) = @_;
271              
272 19         47 my $prev = $magic->sprevious_sibling;
273 19         358 my $next = $magic->snext_sibling;
274              
275 19   0     370 return $DOLLAR_ARG eq $magic->content() &&
276             $prev && $prev->isa('PPI::Token::Cast') &&
277             $DOLLAR eq $prev->content() &&
278             $next && $next->isa('PPI::Structure::Subscript');
279             }
280              
281             # A literal @_ is allowed as the argument for a delegation.
282             # An example of the idiom we are looking for is $self->SUPER::foo(@_).
283             # The argument list of (@_) is required; no other use of @_ is allowed.
284              
285             sub _is_delegation {
286 19     19   47 my ($self, $magic) = @_;
287              
288 19 100       62 $AT_ARG eq $magic->content() or return; # Not a literal '@_'.
289 12 50       66 my $parent = $magic->parent() # Don't know what to do with
290             or return; # orphans.
291 12 50       101 $parent->isa( 'PPI::Statement::Expression' )
292             or return; # Parent must be expression.
293 12 100       42 1 == $parent->schildren() # '@_' must stand alone in
294             or return; # its expression.
295 10 50       149 $parent = $parent->parent() # Still don't know what to do
296             or return; # with orphans.
297 10 50       72 $parent->isa ( 'PPI::Structure::List' )
298             or return; # Parent must be a list.
299 10 50       85 1 == $parent->schildren() # '@_' must stand alone in
300             or return; # the argument list.
301 10 50       129 my $subroutine_name = $parent->sprevious_sibling()
302             or return; # Missing sub name.
303 10 100 66     327 if ( $subroutine_name->isa( 'PPI::Token::Word' ) ) {
    100          
304 6 100       18 $self->{_allow_delegation_to}{$subroutine_name}
305             and return 1;
306 5 100       31 my ($subroutine_namespace) = $subroutine_name =~ m/ \A ( .* ::) \w+ \z /smx
307             or return;
308 4         61 return $self->{_allow_delegation_to}{$subroutine_namespace};
309             } elsif ( $self->{_allow_closures} &&
310             _is_dereference_operator( $subroutine_name ) ) {
311 2         15 my $prev_sib = $subroutine_name;
312             { # Single-iteration loop
313 2 50       4 $prev_sib = $prev_sib->sprevious_sibling()
  3         16  
314             or return;
315 3 100       89 ( $prev_sib->isa( 'PPI::Structure::Subscript' ||
316             _is_dereference_operator( $prev_sib ) ) )
317             and redo;
318             }
319 2         14 return $prev_sib->isa( 'PPI::Token::Symbol' );
320             }
321 2         7 return;
322             }
323              
324             sub _is_dereference_operator {
325 2     2   6 my ( $elem ) = @_;
326 2 50       8 $elem
327             or return;
328 2 50       10 $elem->isa( 'PPI::Token::Operator' )
329             or return;
330 2         9 return $DEREFERENCE eq $elem->content();
331             }
332              
333              
334             sub _get_arg_symbols {
335 129     129   256 my ($statement) = @_;
336              
337 129 100       209 return grep {$AT_ARG eq $_->symbol} @{$statement->find(\&_magic_finder) || []};
  77         1115  
  129         428  
338             }
339              
340             sub _magic_finder {
341             # Find all @_ and $_[\d+] not inside of nested subs
342 1691     1691   17608 my (undef, $elem) = @_;
343 1691 100       4931 return $TRUE if $elem->isa('PPI::Token::Magic'); # match
344              
345 1614 100       4241 if ($elem->isa('PPI::Structure::Block')) {
346             # don't descend into a nested named sub
347 21 100       77 return if $elem->statement->isa('PPI::Statement::Sub');
348              
349             # don't descend into a nested anon sub, either.
350 20 100       366 return if _is_anon_sub( $elem );
351              
352             }
353              
354 1608         3279 return $FALSE; # no match, descend
355             }
356              
357             # Detecting anonymous subs is hard, partly because PPI's parse of them, at
358             # least as of 1.220, appears to be a bit dodgy.
359             sub _is_anon_sub {
360 20     20   42 my ( $elem ) = @_;
361              
362             # If we have no previous element, we can not be an anonymous sub.
363 20 50       83 my $prev = $elem->sprevious_sibling()
364             or return $FALSE;
365              
366             # The simple case.
367 20 100 100     698 return $TRUE if $prev->isa( 'PPI::Token::Word' )
368             and 'sub' eq $prev->content();
369              
370             # Skip possible subroutine attributes. These appear as words (the names)
371             # or lists (the arguments, if any), or actual attributes (depending on how
372             # PPI handles them). A colon is required before the first, and is optional
373             # in between.
374 19   66     214 while ( $prev->isa( 'PPI::Token::Word' )
      100        
      66        
      100        
375             or $prev->isa( 'PPI::Structure::List' )
376             or $prev->isa( 'PPI::Token::Attribute' )
377             or $prev->isa( 'PPI::Token::Operator' )
378             and q<:> eq $prev->content() ) {
379              
380             # Grab the previous significant sib. If there is none, we can not
381             # be an anonymous sub with attributes.
382 4 100       71 return $FALSE if not $prev = $prev->sprevious_sibling();
383             }
384              
385             # PPI 1.220 may parse the 'sub :' erroneously as a label. If we find that,
386             # it means our block is the body of an anonymous subroutine.
387 18 100 66     157 return $TRUE if $prev->isa( 'PPI::Token::Label' )
388             and $prev->content() =~ m/ \A sub \s* : \z /smx;
389              
390             # At this point we may have a prototype. Skip that too, but there needs to
391             # be something before it.
392 17 50 66     75 return $FALSE if $prev->isa( 'PPI::Token::Prototype' )
393             and not $prev = $prev->sprevious_sibling();
394              
395             # Finally, we can find out if we're a sub
396 17 100 66     150 return $TRUE if $prev->isa( 'PPI::Token::Word' )
397             and 'sub' eq $prev->content();
398              
399             # We are out of options. At this point we can not possibly be an anon sub.
400 14         41 return $FALSE;
401             }
402              
403              
404             1;
405              
406             __END__
407              
408             #-----------------------------------------------------------------------------
409              
410             =pod
411              
412             =for stopwords Params::Validate
413              
414             =head1 NAME
415              
416             Perl::Critic::Policy::Subroutines::RequireArgUnpacking - Always unpack C<@_> first.
417              
418             =head1 AFFILIATION
419              
420             This Policy is part of the core L<Perl::Critic|Perl::Critic>
421             distribution.
422              
423              
424             =head1 DESCRIPTION
425              
426             Subroutines that use C<@_> directly instead of unpacking the arguments
427             to local variables first have two major problems. First, they are
428             very hard to read. If you're going to refer to your variables by
429             number instead of by name, you may as well be writing assembler code!
430             Second, C<@_> contains aliases to the original variables! If you
431             modify the contents of a C<@_> entry, then you are modifying the
432             variable outside of your subroutine. For example:
433              
434             sub print_local_var_plus_one {
435             my ($var) = @_;
436             print ++$var;
437             }
438             sub print_var_plus_one {
439             print ++$_[0];
440             }
441              
442             my $x = 2;
443             print_local_var_plus_one($x); # prints "3", $x is still 2
444             print_var_plus_one($x); # prints "3", $x is now 3 !
445             print $x; # prints "3"
446              
447             This is spooky action-at-a-distance and is very hard to debug if it's
448             not intentional and well-documented (like C<chop> or C<chomp>).
449              
450             An exception is made for the usual delegation idiom C<<
451             $object->SUPER::something( @_ ) >>. Only C<SUPER::> and C<NEXT::> are
452             recognized (though this is configurable) and the argument list for the
453             delegate must consist only of C<< ( @_ ) >>.
454              
455             =head1 CONFIGURATION
456              
457             This policy is lenient for subroutines which have C<N> or fewer
458             top-level statements, where C<N> defaults to ZERO. You can override
459             this to set it to a higher number with the
460             C<short_subroutine_statements> setting. This is very much not
461             recommended but perhaps you REALLY need high performance. To do this,
462             put entries in a F<.perlcriticrc> file like this:
463              
464             [Subroutines::RequireArgUnpacking]
465             short_subroutine_statements = 2
466              
467             By default this policy does not allow you to specify array subscripts
468             when you unpack arguments (i.e. by an array slice or by referencing
469             individual elements). Should you wish to permit this, you can do so
470             using the C<allow_subscripts> setting. This defaults to false. You can
471             set it true like this:
472              
473             [Subroutines::RequireArgUnpacking]
474             allow_subscripts = 1
475              
476             The delegation logic can be configured to allow delegation other than to
477             C<SUPER::> or C<NEXT::>. The configuration item is
478             C<allow_delegation_to>, and it takes a space-delimited list of allowed
479             delegates. If a given delegate ends in a double colon, anything in the
480             given namespace is allowed. If it does not, only that subroutine is
481             allowed. For example, to allow C<next::method> from C<Class::C3> and
482             _delegate from the current namespace in addition to SUPER and NEXT, the
483             following configuration could be used:
484              
485             [Subroutines::RequireArgUnpacking]
486             allow_delegation_to = next::method _delegate
487              
488             Argument validation tools such as L<Params::Validate|Params::Validate> generate a closure which is
489             used to unpack and validate the arguments of a subroutine. In order to
490             recognize closures as a valid way to unpack arguments you must enable them
491             explicitly:
492              
493             [Subroutines::RequireArgUnpacking]
494             allow_closures = 1
495              
496             =head1 CAVEATS
497              
498             PPI doesn't currently detect anonymous subroutines, so we don't check
499             those. This should just work when PPI gains that feature.
500              
501             We don't check for C<@ARG>, the alias for C<@_> from English.pm. That's
502             deprecated anyway.
503              
504             =head1 CREDITS
505              
506             Initial development of this policy was supported by a grant from the
507             Perl Foundation.
508              
509             =head1 AUTHOR
510              
511             Chris Dolan <cdolan@cpan.org>
512              
513             =head1 COPYRIGHT
514              
515             Copyright (c) 2007-2011 Chris Dolan. Many rights reserved.
516              
517             This program is free software; you can redistribute it and/or modify
518             it under the same terms as Perl itself. The full text of this license
519             can be found in the LICENSE file included with this module
520              
521             =cut
522              
523             # Local Variables:
524             # mode: cperl
525             # cperl-indent-level: 4
526             # fill-column: 78
527             # indent-tabs-mode: nil
528             # c-indentation-style: bsd
529             # End:
530             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :