File Coverage

blib/lib/Perl/Critic/Policy/Community/DollarAB.pm
Criterion Covered Total %
statement 37 38 97.3
branch 8 8 100.0
condition 14 15 93.3
subroutine 11 12 91.6
pod 4 5 80.0
total 74 78 94.8


line stmt bran cond sub pod time code
1              
2             use strict;
3 1     1   336 use warnings;
  1         1  
  1         27  
4 1     1   4  
  1         2  
  1         22  
5             use Perl::Critic::Utils qw(:severities :classification :ppi);
6 1     1   5 use parent 'Perl::Critic::Policy';
  1         1  
  1         41  
7 1     1   270  
  1         2  
  1         4  
8             our $VERSION = 'v1.0.3';
9              
10             use constant DESC => 'Using $a or $b outside sort()';
11 1     1   55 use constant EXPL => '$a and $b are special package variables for use in sort() and related functions. Declaring them as lexicals like "my $a" may break sort(). Use different variable names.';
  1         2  
  1         44  
12 1     1   4  
  1         2  
  1         268  
13             (
14             {
15             name => 'extra_pair_functions',
16             description => 'Non-standard functions in which to allow $a and $b',
17 9     9 0 27629 behavior => 'string list',
18             },
19             )
20             }
21              
22              
23             my @sorters = qw(sort reduce pairgrep pairfirst pairmap pairwise);
24 4     4 1 52  
25 0     0 1 0 my ($self, $elem) = @_;
26 9     9 1 82481 return () unless $elem->symbol eq '$a' or $elem->symbol eq '$b';
27              
28             my %sorters_hash = map { ($_ => 1) } @sorters, keys %{$self->{_extra_pair_functions}};
29             my $found = $self->_find_sorter($elem, \%sorters_hash);
30            
31 37     37 1 1073 return $self->violation(DESC, EXPL, $elem) unless $found;
32 37 100 100     93 return ();
33             }
34 31         1544  
  194         338  
  31         71  
35 31         73 my ($self, $elem, $sorters) = @_;
36            
37 31 100       72 my $outer = $elem->parent;
38 27         78 $outer = $outer->parent until !$outer or $outer->isa('PPI::Structure::Block');
39             return '' unless $outer;
40            
41             # Find function or method call (assumes block/sub is first argument)
42 33     33   58 my $function = $outer->previous_token;
43             $function = $function->previous_token until !$function
44 33         72 or ($function->isa('PPI::Token::Word') and $function =~ m/([^:]+)\z/ and exists $sorters->{$1});
45 33   100     260 return $self->_find_sorter($outer) unless $function;
46 33 100       225 return $function;
47             }
48              
49 29         64 1;
50              
51 29   66     754 =head1 NAME
      100        
      100        
52 29 100       3293  
53 27         55 Perl::Critic::Policy::Community::DollarAB - Don't use $a or $b as variable
54             names outside sort
55              
56             =head1 DESCRIPTION
57              
58             The special variables C<$a> and C<$b> are reserved for C<sort()> and similar
59             functions which assign to them to iterate over pairs of values. These are
60             global variables, and declaring them as lexical variables with C<my> to use
61             them outside this context can break usage of these functions. Use different
62             names for your variables.
63              
64             my $a = 1; # not ok
65             my $abc = 1; # ok
66             sort { $a <=> $b } (3,2,1); # ok
67              
68             =head1 AFFILIATION
69              
70             This policy is part of L<Perl::Critic::Community>.
71              
72             =head1 CONFIGURATION
73              
74             This policy can be configured to allow C<$a> and C<$b> in additional functions,
75             by putting an entry in a C<.perlcriticrc> file like this:
76              
77             [Community::DollarAB]
78             extra_pair_functions = pairfoo pairbar
79              
80             =head1 AUTHOR
81              
82             Dan Book, C<dbook@cpan.org>
83              
84             =head1 COPYRIGHT AND LICENSE
85              
86             Copyright 2015, Dan Book.
87              
88             This library is free software; you may redistribute it and/or modify it under
89             the terms of the Artistic License version 2.0.
90              
91             =head1 SEE ALSO
92              
93             L<Perl::Critic>