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   27071 use 5.010001;
  40         175  
4 40     40   240 use strict;
  40         88  
  40         865  
5 40     40   204 use warnings;
  40         92  
  40         1269  
6              
7 40     40   218 use Readonly;
  40         133  
  40         2048  
8              
9 40     40   286 use Perl::Critic::Utils qw{ :severities hashify };
  40         127  
  40         2155  
10 40     40   5466 use parent 'Perl::Critic::Policy';
  40         113  
  40         217  
11              
12             our $VERSION = '1.150';
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 89     89 0 1662 sub supported_parameters { return () }
28 74     74 1 316 sub default_severity { return $SEVERITY_LOW }
29 86     86 1 353 sub default_themes { return qw(core pbp maintenance) }
30 30     30 1 84 sub applies_to { return 'PPI::Token::Symbol' }
31              
32             #-----------------------------------------------------------------------------
33              
34             sub violates {
35 172     172 1 384 my ( $self, $elem, undef ) = @_;
36              
37 172         362 my $previous = $elem->sprevious_sibling();
38 172 100       3457 if ( $previous ) {
39             #Sigil is allowed if taking a reference, e.g. "\&my_sub"
40 130 50 33     494 return if $previous->isa('PPI::Token::Cast') && $previous eq q{\\};
41             }
42              
43 172 50       348 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 :