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   29416 use 5.010001;
  40         189  
4 40     40   234 use strict;
  40         91  
  40         827  
5 40     40   206 use warnings;
  40         89  
  40         988  
6              
7 40     40   248 use Carp;
  40         97  
  40         2433  
8 40     40   298 use English qw(-no_match_vars);
  40         105  
  40         264  
9 40     40   14954 use Readonly;
  40         111  
  40         1771  
10              
11 40     40   274 use File::Spec;
  40         110  
  40         1493  
12              
13 40         2122 use Perl::Critic::Utils qw<
14             :booleans :characters :classification hashify :severities words_from_string
15 40     40   271 >;
  40         99  
16 40     40   22157 use parent 'Perl::Critic::Policy';
  40         123  
  40         245  
17              
18             our $VERSION = '1.146';
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 3235 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 478 sub default_severity { return $SEVERITY_HIGH }
67 86     86 1 429 sub default_themes { return qw( core pbp maintenance ) }
68 56     56 1 226 sub applies_to { return 'PPI::Statement::Sub' }
69              
70             #-----------------------------------------------------------------------------
71              
72             sub violates {
73 46     46 1 162 my ( $self, $elem, undef ) = @_;
74              
75             # forward declaration?
76 46 100       249 return if not $elem->block;
77              
78 45         1260 my @statements = $elem->block->schildren;
79              
80             # empty sub?
81 45 100       2071 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       182 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         105 my $state = 'unpacking'; # still in unpacking paragraph
94 43         110 for my $statement (@statements) {
95              
96 129         343 my @magic = _get_arg_symbols($statement);
97              
98 129         5525 my $saw_unpack = $FALSE;
99              
100             MAGIC:
101 129         282 for my $magic (@magic) {
102             # allow conditional checks on the size of @_
103 74 100       243 next MAGIC if _is_size_check($magic);
104              
105 30 100       178 if ('unpacking' eq $state) {
106 22 100       80 if ($self->_is_unpack($magic)) {
107 11         255 $saw_unpack = $TRUE;
108 11         41 next MAGIC;
109             }
110             }
111              
112             # allow @$_[] construct in "... for ();"
113             # Check for "print @$_[] for ()" construct (rt39601)
114             next MAGIC
115 19 50 33     73 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       64 if _is_cast_of_scalar( $magic );
121              
122             # allow delegation of the form "$self->SUPER::foo( @_ );"
123             next MAGIC
124 19 100       251 if $self->_is_delegation( $magic );
125              
126             # If we make it this far, it is a violation
127 13         163 return $self->violation( $DESC, $EXPL, $elem );
128             }
129 116 100       644 if (not $saw_unpack) {
130 105         279 $state = 'post_unpacking';
131             }
132             }
133 30         132 return; # OK
134             }
135              
136             sub _is_unpack {
137 22     22   60 my ($self, $magic) = @_;
138              
139 22         62 my $prev = $magic->sprevious_sibling();
140 22         541 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     551 if ( $next and $next->isa('PPI::Structure::Subscript') ) {
145 10 100       48 $self->{_allow_subscripts} or return;
146 4         15 $next = $next->snext_sibling;
147             }
148              
149 16 50 100     198 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         18 return;
159             }
160              
161             sub _is_size_check {
162 74     74   160 my ($magic) = @_;
163              
164             # No size check on $_[0]. RT #34009.
165 74 100       220 $AT eq $magic->raw_type or return;
166              
167 64         580 my $prev = $magic->sprevious_sibling;
168 64         1717 my $next = $magic->snext_sibling;
169              
170 64 100 100     1450 if ( $prev || $next ) {
171              
172 50 100 66     119 return $TRUE
173             if _legal_before_size_check( $prev )
174             and _legal_after_size_check( $next );
175             }
176              
177 24         273 my $parent = $magic;
178             {
179 24 50       43 $parent = $parent->parent()
  40         149  
180             or return;
181 40         294 $prev = $parent->sprevious_sibling();
182 40         995 $next = $parent->snext_sibling();
183 40 100 100     962 $prev
184             or $next
185             or redo;
186             } # until ( $prev || $next );
187              
188 24 100       157 return $TRUE
189             if $parent->isa( 'PPI::Structure::Condition' );
190              
191 20         152 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   413 my ( $next ) = @_;
203              
204 40 100       164 $next
205             or return $TRUE;
206              
207             $next->isa( 'PPI::Token::Operator' )
208 28 100       108 and return $LEGAL_NEXT_OPER{ $next->content() };
209              
210             $next->isa( 'PPI::Token::Structure' )
211 6 50       26 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   112 my ( $prev ) = @_;
227              
228 50 100       148 $prev
229             or return $TRUE;
230              
231             $prev->isa( 'PPI::Token::Operator' )
232 38 100       162 and return $LEGAL_PREV_OPER{ $prev->content() };
233              
234             $prev->isa( 'PPI::Token::Word' )
235 7 50       34 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   48 my ($magic) = @_;
257              
258 19         70 my $prev = $magic->sprevious_sibling;
259              
260 19 50 66     422 return $TRUE
      33        
261             if ( $prev && $prev->content() eq $AT )
262             and $prev->isa('PPI::Token::Cast');
263 19         112 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   52 my ($magic) = @_;
271              
272 19         67 my $prev = $magic->sprevious_sibling;
273 19         360 my $next = $magic->snext_sibling;
274              
275 19   0     362 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   69 my ($self, $magic) = @_;
287              
288 19 100       57 $AT_ARG eq $magic->content() or return; # Not a literal '@_'.
289 12 50       75 my $parent = $magic->parent() # Don't know what to do with
290             or return; # orphans.
291 12 50       107 $parent->isa( 'PPI::Statement::Expression' )
292             or return; # Parent must be expression.
293 12 100       51 1 == $parent->schildren() # '@_' must stand alone in
294             or return; # its expression.
295 10 50       155 $parent = $parent->parent() # Still don't know what to do
296             or return; # with orphans.
297 10 50       73 $parent->isa ( 'PPI::Structure::List' )
298             or return; # Parent must be a list.
299 10 50       92 1 == $parent->schildren() # '@_' must stand alone in
300             or return; # the argument list.
301 10 50       139 my $subroutine_name = $parent->sprevious_sibling()
302             or return; # Missing sub name.
303 10 100 66     357 if ( $subroutine_name->isa( 'PPI::Token::Word' ) ) {
    100          
304 6 100       21 $self->{_allow_delegation_to}{$subroutine_name}
305             and return 1;
306 5 100       38 my ($subroutine_namespace) = $subroutine_name =~ m/ \A ( .* ::) \w+ \z /smx
307             or return;
308 4         64 return $self->{_allow_delegation_to}{$subroutine_namespace};
309             } elsif ( $self->{_allow_closures} &&
310             _is_dereference_operator( $subroutine_name ) ) {
311 2         14 my $prev_sib = $subroutine_name;
312             { # Single-iteration loop
313 2 50       5 $prev_sib = $prev_sib->sprevious_sibling()
  3         35  
314             or return;
315 3 100       95 ( $prev_sib->isa( 'PPI::Structure::Subscript' ||
316             _is_dereference_operator( $prev_sib ) ) )
317             and redo;
318             }
319 2         13 return $prev_sib->isa( 'PPI::Token::Symbol' );
320             }
321 2         7 return;
322             }
323              
324             sub _is_dereference_operator {
325 2     2   9 my ( $elem ) = @_;
326 2 50       9 $elem
327             or return;
328 2 50       9 $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   287 my ($statement) = @_;
336              
337 129 100       208 return grep {$AT_ARG eq $_->symbol} @{$statement->find(\&_magic_finder) || []};
  77         1096  
  129         468  
338             }
339              
340             sub _magic_finder {
341             # Find all @_ and $_[\d+] not inside of nested subs
342 1691     1691   17934 my (undef, $elem) = @_;
343 1691 100       5029 return $TRUE if $elem->isa('PPI::Token::Magic'); # match
344              
345 1614 100       4537 if ($elem->isa('PPI::Structure::Block')) {
346             # don't descend into a nested named sub
347 21 100       78 return if $elem->statement->isa('PPI::Statement::Sub');
348              
349             # don't descend into a nested anon sub, either.
350 20 100       417 return if _is_anon_sub( $elem );
351              
352             }
353              
354 1608         3202 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   45 my ( $elem ) = @_;
361              
362             # If we have no previous element, we can not be an anonymous sub.
363 20 50       64 my $prev = $elem->sprevious_sibling()
364             or return $FALSE;
365              
366             # The simple case.
367 20 100 100     671 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     229 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       112 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     166 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     76 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         43 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 :