File Coverage

blib/lib/Perl/Critic/Policy/BuiltinFunctions/ProhibitReverseSortBlock.pm
Criterion Covered Total %
statement 42 42 100.0
branch 16 16 100.0
condition 6 6 100.0
subroutine 11 11 100.0
pod 4 5 80.0
total 79 80 98.7


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::BuiltinFunctions::ProhibitReverseSortBlock;
2              
3 40     40   26668 use 5.010001;
  40         201  
4 40     40   263 use strict;
  40         122  
  40         826  
5 40     40   233 use warnings;
  40         115  
  40         1040  
6 40     40   282 use Readonly;
  40         132  
  40         2223  
7              
8 40     40   345 use Perl::Critic::Utils qw{ :severities :classification };
  40         132  
  40         2158  
9 40     40   14261 use parent 'Perl::Critic::Policy';
  40         131  
  40         277  
10              
11             our $VERSION = '1.146';
12              
13             #-----------------------------------------------------------------------------
14              
15             Readonly::Scalar my $DESC => q{Forbid $b before $a in sort blocks}; ## no critic (InterpolationOfMetachars)
16             Readonly::Scalar my $EXPL => [ 152 ];
17              
18             #-----------------------------------------------------------------------------
19              
20 92     92 0 1682 sub supported_parameters { return () }
21 77     77 1 360 sub default_severity { return $SEVERITY_LOWEST }
22 84     84 1 370 sub default_themes { return qw(core pbp cosmetic) }
23 33     33 1 143 sub applies_to { return 'PPI::Token::Word' }
24              
25             #-----------------------------------------------------------------------------
26              
27             sub violates {
28 354     354 1 745 my ($self, $elem, $doc) = @_;
29              
30 354 100       723 return if $elem->content() ne 'sort';
31 18 100       99 return if ! is_function_call($elem);
32              
33 14         59 my $sib = $elem->snext_sibling();
34 14 100       281 return if !$sib;
35              
36 13         25 my $arg = $sib;
37 13 100       39 if ( $arg->isa('PPI::Structure::List') ) {
38 5         49 $arg = $arg->schild(0);
39             # Forward looking: PPI might change in v1.200 so schild(0) is a PPI::Statement::Expression
40 5 100 100     89 if ( $arg && $arg->isa('PPI::Statement::Expression') ) {
41 1         5 $arg = $arg->schild(0);
42             }
43             }
44 13 100 100     90 return if !$arg || !$arg->isa('PPI::Structure::Block');
45              
46             # If we get here, we found a sort with a block as the first arg
47              
48             # Look at each statement in the block separately.
49             # $a is +1, $b is -1, sum should always be >= 0.
50             # This may go badly if there are conditionals or loops or other
51             # sub-statements...
52 7         31 for my $statement ($arg->children) {
53 9         58 my @sort_vars = $statement =~ m/\$([ab])\b/gxms;
54 9         670 my $count = 0;
55 9         20 for my $sort_var (@sort_vars) {
56 13 100       31 if ($sort_var eq 'a') {
57 5         11 $count++;
58             } else {
59 8         14 $count--;
60 8 100       24 if ($count < 0) {
61             # Found too many C<$b>s too early
62 3         18 return $self->violation( $DESC, $EXPL, $elem );
63             }
64             }
65             }
66             }
67 4         17 return; #ok
68             }
69              
70             1;
71              
72             #-----------------------------------------------------------------------------
73              
74             __END__
75              
76             =pod
77              
78             =head1 NAME
79              
80             Perl::Critic::Policy::BuiltinFunctions::ProhibitReverseSortBlock - Forbid $b before $a in sort blocks.
81              
82              
83             =head1 AFFILIATION
84              
85             This Policy is part of the core L<Perl::Critic|Perl::Critic>
86             distribution.
87              
88              
89             =head1 DESCRIPTION
90              
91             Conway says that it is much clearer to use C<reverse> than to flip
92             C<$a> and C<$b> around in a C<sort> block. He also suggests that, in
93             newer perls, C<reverse> is specifically looked for and optimized, and
94             in the case of a simple reversed string C<sort>, using C<reverse> with
95             a C<sort> with no block is faster even in old perls.
96              
97             my @foo = sort { $b cmp $a } @bar; #not ok
98             my @foo = reverse sort @bar; #ok
99              
100             my @foo = sort { $b <=> $a } @bar; #not ok
101             my @foo = reverse sort { $a <=> $b } @bar; #ok
102              
103              
104             =head1 CONFIGURATION
105              
106             This Policy is not configurable except for the standard options.
107              
108              
109             =head1 AUTHOR
110              
111             Chris Dolan <cdolan@cpan.org>
112              
113              
114             =head1 COPYRIGHT
115              
116             Copyright (c) 2006-2011 Chris Dolan.
117              
118             This program is free software; you can redistribute it and/or modify
119             it under the same terms as Perl itself.
120              
121             =cut
122              
123             # Local Variables:
124             # mode: cperl
125             # cperl-indent-level: 4
126             # fill-column: 78
127             # indent-tabs-mode: nil
128             # c-indentation-style: bsd
129             # End:
130             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :