File Coverage

blib/lib/Perl/Critic/Policy/CodeLayout/RequireSpaceAroundBinaryOperators.pm
Criterion Covered Total %
statement 51 52 98.0
branch 13 14 92.8
condition 5 6 83.3
subroutine 17 18 94.4
pod 5 6 83.3
total 91 96 94.7


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::CodeLayout::RequireSpaceAroundBinaryOperators;
2 2     2   2693 use strict;
  2         23  
  2         63  
3 2     2   13 use warnings;
  2         4  
  2         57  
4 2     2   11 use parent qw[ Perl::Critic::Policy ];
  2         4  
  2         17  
5 2     2   140 use Perl::Critic::Utils qw[ :severities :data_conversion :booleans ];
  2         4  
  2         105  
6 2     2   407 use List::MoreUtils qw[ all any ];
  2         5  
  2         21  
7              
8 2         242 use constant BINARY_OPERATORS => qw(
9             ** + -
10             =~ !~ * / % x
11             << >> lt gt le ge cmp ~~
12             == != <=> . .. ...
13             & | ^ && || //
14             **= += -= .= *= /=
15             %= x= &= |= ^= <<= >>= &&=
16             ||= //= < > <= >= => ->
17             and or xor eq ne
18 2     2   1664 ); # comma specifically excluded, even though it's technically a binary operator
  2         6  
19 2         140 use constant OPERAND_CLASSES => qw(
20             PPI::Token::HereDoc
21             PPI::Token::Number
22             PPI::Token::Quote
23             PPI::Token::QuoteLike
24             PPI::Token::Regexp
25             PPI::Token::Symbol
26             PPI::Structure::List
27 2     2   15 );
  2         18  
28 2     2   15 use constant PBP_PAGE => 14;
  2         5  
  2         1056  
29              
30 5     5 1 65 sub default_severity { return $SEVERITY_LOW }
31 0     0 1 0 sub default_themes { return qw[ cosmetic pbp ] }
32 8     8 1 33307 sub applies_to { return 'PPI::Token::Operator' }
33              
34             sub supported_parameters {
35             return (
36             {
37 8     8 0 31155 name => 'exclude',
38             description => 'Exempt operators.',
39             behavior => 'enumeration',
40             enumeration_values => [BINARY_OPERATORS],
41             enumeration_allow_multiple_values => 1,
42             default_string => '** ->',
43             },
44             );
45             }
46              
47             sub initialize_if_enabled {
48 8     8 1 31745 my ($self, $config) = @_;
49              
50             $self->{_ops_to_check} = {
51 8         30 map { $_ => 1 } grep { not $self->{_exclude}{$_} } BINARY_OPERATORS
  432         851  
  448         883  
52             };
53              
54 8         57 return $TRUE;
55             }
56              
57             sub violates {
58 38     38 1 1513 my ($self, $elem, $doc) = @_;
59 38         436 my $op = $elem->content();
60 38 100       201 return if not $self->{_ops_to_check}{$op};
61              
62 16 100 100     87 if ($op eq '+' or $op eq '-') { # try to detect unary operators
63 8         33 my $next_sig_sib = $elem->snext_sibling();
64 8         217 my $prev_sig_sib = $elem->sprevious_sibling();
65 8 100   16   190 return if any { not _is_operand($_) } $next_sig_sib, $prev_sig_sib;
  16         51  
66             }
67              
68 14         89 my $next_sib = $elem->next_sibling();
69 14         433 my $prev_sib = $elem->previous_sibling();
70              
71             # Treat ,=> as a single operator
72 14 100 66     379 $prev_sib = $prev_sib->previous_sibling()
73             if $elem eq '=>' and $prev_sib eq ',';
74              
75 14 50   24   587 if (not all { ref and $_->isa('PPI::Token::Whitespace') } $next_sib, $prev_sib) {
  24 100       123  
76 5         28 return $self->violation("Binary $op operator used without surrounding whitespace",
77             PBP_PAGE, $elem);
78             }
79              
80 9         38 return;
81             }
82              
83             sub _is_operand {
84 16     16   34 my ($elem) = @_;
85 16 100       51 return if not ref $elem;
86 15     61   100 return any { $elem->isa($_) } OPERAND_CLASSES;
  61         270  
87             }
88              
89             1;
90             __END__
91             =pod
92              
93             =head1 NAME
94              
95             Perl::Critic::Policy::CodeLayout::RequireSpaceAroundBinaryOperators - put spaces around operators
96              
97             =head1 AFFILIATION
98              
99             This policy as a part of the L<Perl::Critic::PolicyBundle::SNEZ> distribution.
100              
101             =head1 DESCRIPTION
102              
103             Squashing operators and operands together produces less readable code.
104             Put spaces around binary operators.
105              
106             =head1 CONFIGURATION
107              
108             Operators can be exempt from this rule with the B<exclude> parameter:
109              
110             [Perl::Critic::Policy::CodeLayout::RequireSpaceAroundBinaryOperators]
111             exclude = ** -> x
112              
113             Note that B<**> and B<< -> >> are excluded by default.
114              
115             =head1 COPYRIGHT
116              
117             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
118              
119             =cut