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   27018 use 5.010001;
  40         173  
4 40     40   243 use strict;
  40         93  
  40         872  
5 40     40   218 use warnings;
  40         116  
  40         1189  
6              
7 40     40   238 use Readonly;
  40         103  
  40         2268  
8              
9 40     40   287 use Perl::Critic::Utils qw{ :severities hashify };
  40         108  
  40         2237  
10 40     40   5840 use parent 'Perl::Critic::Policy';
  40         103  
  40         239  
11              
12             our $VERSION = '1.146';
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 1719 sub supported_parameters { return () }
28 81     81 1 404 sub default_severity { return $SEVERITY_LOW }
29 86     86 1 387 sub default_themes { return qw(core pbp maintenance) }
30 36     36 1 103 sub applies_to { return 'PPI::Token::Symbol' }
31              
32             #-----------------------------------------------------------------------------
33              
34             sub violates {
35 206     206 1 470 my ( $self, $elem, undef ) = @_;
36              
37 206         520 my $previous = $elem->sprevious_sibling();
38 206 100       4871 if ( $previous ) {
39             #Sigil is allowed if taking a reference, e.g. "\&my_sub"
40 146 100 100     631 return if $previous->isa('PPI::Token::Cast') && $previous eq q{\\};
41             }
42              
43 200 100       489 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     162 if (not $previous or
      100        
48             $previous->isa( 'PPI::Token::Operator' ) and
49             $IS_COMMA{ $previous->content() } ) {
50 12         35 my $up = $elem;
51              
52             PARENT:
53 12   100     55 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       392 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     286 $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       60 if ($word->isa('PPI::Token::Word')) {
73 2         6 $previous = $word;
74             }
75 8         20 last PARENT;
76             }
77             }
78             }
79 15 50 66     95 return if $previous and $EXEMPTIONS{$previous};
80              
81 7         30 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 :