File Coverage

blib/lib/Perl/Critic/Policy/Subroutines/ProhibitAmpersandSigils.pm
Criterion Covered Total %
statement 26 36 72.2
branch 4 16 25.0
condition 1 24 4.1
subroutine 11 11 100.0
pod 4 5 80.0
total 46 92 50.0


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils;
2              
3 40     40   24257 use 5.010001;
  40         138  
4 40     40   170 use strict;
  40         66  
  40         732  
5 40     40   132 use warnings;
  40         63  
  40         1409  
6              
7 40     40   148 use Readonly;
  40         63  
  40         2102  
8              
9 40     40   161 use Perl::Critic::Utils qw{ :severities hashify };
  40         62  
  40         1970  
10 40     40   4888 use parent 'Perl::Critic::Policy';
  40         72  
  40         317  
11              
12             our $VERSION = '1.156';
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 90     90 0 601 sub supported_parameters { return () }
28 75     75 1 236 sub default_severity { return $SEVERITY_LOW }
29 86     86 1 244 sub default_themes { return qw(core pbp maintenance) }
30 31     31 1 67 sub applies_to { return 'PPI::Token::Symbol' }
31              
32             #-----------------------------------------------------------------------------
33              
34             sub violates {
35 173     173 1 250 my ( $self, $elem, undef ) = @_;
36              
37 173         380 my $previous = $elem->sprevious_sibling();
38 173 100       3667 if ( $previous ) {
39             #Sigil is allowed if taking a reference, e.g. "\&my_sub"
40 131 50 33     443 return if $previous->isa('PPI::Token::Cast') && $previous eq q{\\};
41             }
42              
43 173 50       328 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 0 0 0       if (not $previous or
      0        
48             $previous->isa( 'PPI::Token::Operator' ) and
49             $IS_COMMA{ $previous->content() } ) {
50 0           my $up = $elem;
51              
52             PARENT:
53 0   0       while (
      0        
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 0 0         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 0 0 0       $up->isa('PPI::Structure::List')
      0        
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 0 0         if ($word->isa('PPI::Token::Word')) {
73 0           $previous = $word;
74             }
75 0           last PARENT;
76             }
77             }
78             }
79 0 0 0       return if $previous and $EXEMPTIONS{$previous};
80              
81 0           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 :