File Coverage

blib/lib/App/PerlNitpick/Rule/RewriteWithAssignmentOperators.pm
Criterion Covered Total %
statement 45 45 100.0
branch 5 6 83.3
condition 12 27 44.4
subroutine 8 8 100.0
pod 0 2 0.0
total 70 88 79.5


line stmt bran cond sub pod time code
1             package App::PerlNitpick::Rule::RewriteWithAssignmentOperators;
2 1     1   360319 use Moose;
  1         466262  
  1         7  
3 1     1   7692 use PPI::Document;
  1         2  
  1         45  
4 1     1   8 use PPI::Token::Whitespace;
  1         2  
  1         33  
5              
6 1     1   5 no Moose;
  1         2  
  1         6  
7              
8 1         2 use constant IS_REWRITABLE => { map { $_ => 1 } (
  17         636  
9             '*', '/', '%', 'x', '+', '-', '.',
10             '//', '||',
11             '|', '&', '^',
12             '|.', '&.', '^.',
13             '<<', '>>'
14 1     1   304 ) };
  1         3  
15              
16             sub is_rewritable {
17 8     8 0 137 my ($op) = @_;
18 8         60 return IS_REWRITABLE->{$op};
19             }
20              
21             sub _trim_whitespace {
22 5     5   12 my ($elem) = @_;
23              
24 5         43 my $e = $elem->next_sibling;
25 5         121 while (! $e->significant) {
26 2         33 $e->remove;
27 2         70 $e = $elem->next_sibling;
28             }
29             }
30              
31             sub rewrite {
32 8     8 0 24347 my ($self, $document) = @_;
33              
34             my @found = grep {
35             # Find a statement that looks like $x = $x + $y;
36 8         185 my $c0 = $_->schild(0); # $x
37 8         100 my $c1 = $_->schild(1); # =
38 8         105 my $c2 = $_->schild(2); # $x
39 8         117 my $c3 = $_->schild(3); # +
40 8         136 my $c4 = $_->schild(4); # $y
41 8         151 my $c5 = $_->schild(5); # ;
42              
43 8 100 33     209 ($c1->isa('PPI::Token::Operator') && $c1->content eq '=') &&
      33        
      33        
      66        
      33        
      33        
      33        
      66        
      66        
44             ($c5->isa('PPI::Token::Structure') && $c5->content eq ';') &&
45             ($c3->isa('PPI::Token::Operator') && is_rewritable($c3->content)) &&
46             ($c0->isa('PPI::Token::Symbol') && $c0->raw_type eq '$' &&
47             $c2->isa('PPI::Token::Symbol') && $c2->raw_type eq '$' &&
48             $c0->content eq $c2->content)
49             } grep {
50 9         3252 $_->schildren == 6
51 8 50       18 } @{ $document->find('PPI::Statement') ||[] };
  8         32  
52              
53 8 100       189 return $document unless @found;
54              
55 5         11 for my $statement (@found) {
56 5         13 my @child = $statement->schildren;
57              
58 5         99 my $assigment_operator = PPI::Token::Operator->new($child[3]->content . $child[1]->content);
59              
60 5         67 $child[3]->remove;
61              
62 5         234 _trim_whitespace($child[2]);
63 5         39 $child[2]->remove;
64              
65 5         172 $child[2]->remove;
66 5         47 $child[1]->insert_after($assigment_operator);
67 5         205 $child[1]->remove;
68             }
69              
70 5         190 return $document;
71             }
72              
73             1;
74              
75             __END__
76              
77             =head1 DESCRIPTION
78              
79             This rule rewrites those assignments that alter a single varible with itself.
80             For example, this one:
81              
82             $x = $x + 2;
83              
84             Is rewritten with the C<+=> assignment operator, as:
85              
86             $x += 2;
87              
88             =cut