File Coverage

blib/lib/Perl/Critic/Policy/Subroutines/ProhibitAmpersandSigils.pm
Criterion Covered Total %
statement 36 36 100.0
branch 15 16 93.7
condition 20 24 83.3
subroutine 11 11 100.0
pod 4 5 80.0
total 86 92 93.4


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils;
2              
3 40     40   26519 use 5.010001;
  40         166  
4 40     40   225 use strict;
  40         117  
  40         897  
5 40     40   231 use warnings;
  40         109  
  40         1012  
6              
7 40     40   225 use Readonly;
  40         95  
  40         2222  
8              
9 40     40   263 use Perl::Critic::Utils qw{ :severities hashify };
  40         100  
  40         2167  
10 40     40   5634 use parent 'Perl::Critic::Policy';
  40         116  
  40         232  
11              
12             our $VERSION = '1.148';
13              
14             #-----------------------------------------------------------------------------
15              
16             Readonly::Scalar my $DESC => q{Subroutine called with "&" sigil};
17             Readonly::Scalar my $EXPL => [ 175 ];
18              
19             Readonly::Hash my %EXEMPTIONS =>
20             hashify( qw< defined exists goto sort > );
21              
22             Readonly::Hash my %IS_COMMA =>
23             hashify( q{,}, q{=>} );
24              
25             #-----------------------------------------------------------------------------
26              
27 95     95 0 1710 sub supported_parameters { return () }
28 81     81 1 402 sub default_severity { return $SEVERITY_LOW }
29 86     86 1 371 sub default_themes { return qw(core pbp maintenance) }
30 36     36 1 127 sub applies_to { return 'PPI::Token::Symbol' }
31              
32             #-----------------------------------------------------------------------------
33              
34             sub violates {
35 206     206 1 467 my ( $self, $elem, undef ) = @_;
36              
37 206         511 my $previous = $elem->sprevious_sibling();
38 206 100       5075 if ( $previous ) {
39             #Sigil is allowed if taking a reference, e.g. "\&my_sub"
40 146 100 100     736 return if $previous->isa('PPI::Token::Cast') && $previous eq q{\\};
41             }
42              
43 200 100       495 return if ( $elem !~ m{\A [&] }xms ); # ok
44              
45             # look up past parens to get say the "defined" in "defined(&foo)" or
46             # "defined((&foo))" etc
47 18 100 66     169 if (not $previous or
      100        
48             $previous->isa( 'PPI::Token::Operator' ) and
49             $IS_COMMA{ $previous->content() } ) {
50 12         36 my $up = $elem;
51              
52             PARENT:
53 12   100     46 while (
      66        
54             ($up = $up->parent)
55             and (
56             $up->isa('PPI::Statement::Expression')
57             or $up->isa('PPI::Structure::List')
58             or $up->isa('PPI::Statement')
59             )
60             ) {
61 18 100       383 if (my $word = $up->sprevious_sibling) {
62             # Since backslashes distribute over lists (per perlref), if
63             # we have a list and the previous is a backslash, we're cool.
64             return if
65 11 100 100     337 $up->isa('PPI::Structure::List')
      66        
66             && $word->isa('PPI::Token::Cast')
67             && $word->content() eq q{\\};
68              
69             # For a word set $previous to have it checked against %EXEMPTIONS
70             # below. For a non-word it's a violation, leave $previous false
71             # to get there.
72 8 100       62 if ($word->isa('PPI::Token::Word')) {
73 2         4 $previous = $word;
74             }
75 8         21 last PARENT;
76             }
77             }
78             }
79 15 50 66     109 return if $previous and $EXEMPTIONS{$previous};
80              
81 7         47 return $self->violation( $DESC, $EXPL, $elem );
82             }
83              
84             1;
85              
86             __END__
87              
88             #-----------------------------------------------------------------------------
89              
90             =pod
91              
92             =head1 NAME
93              
94             Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils - Don't call functions with a leading ampersand sigil.
95              
96             =head1 AFFILIATION
97              
98             This Policy is part of the core L<Perl::Critic|Perl::Critic>
99             distribution.
100              
101              
102             =head1 DESCRIPTION
103              
104             Since Perl 5, the ampersand sigil is completely optional when invoking
105             subroutines. It also turns off checking of subroutine prototypes.
106             It's easily confused with the bitwise 'and' operator.
107              
108             @result = &some_function(); # not ok
109             @result = some_function(); # ok
110              
111              
112             =head1 CONFIGURATION
113              
114             This Policy is not configurable except for the standard options.
115              
116              
117             =head1 AUTHOR
118              
119             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
120              
121             =head1 COPYRIGHT
122              
123             Copyright (c) 2005-2011 Imaginative Software Systems. All rights reserved.
124              
125             This program is free software; you can redistribute it and/or modify
126             it under the same terms as Perl itself. The full text of this license
127             can be found in the LICENSE file included with this module.
128              
129             =cut
130              
131             # Local Variables:
132             # mode: cperl
133             # cperl-indent-level: 4
134             # fill-column: 78
135             # indent-tabs-mode: nil
136             # c-indentation-style: bsd
137             # End:
138             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :