File Coverage

blib/lib/Perl/Critic/Policy/Variables/ProhibitUnusedVariables.pm
Criterion Covered Total %
statement 74 74 100.0
branch 22 28 78.5
condition n/a
subroutine 17 17 100.0
pod 4 5 80.0
total 117 124 94.3


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Variables::ProhibitUnusedVariables;
2              
3 40     40   27606 use 5.010001;
  40         191  
4 40     40   253 use strict;
  40         108  
  40         820  
5 40     40   214 use warnings;
  40         120  
  40         1056  
6              
7 40     40   232 use Readonly;
  40         119  
  40         1899  
8 40     40   321 use List::SomeUtils qw( any );
  40         117  
  40         1652  
9              
10 40     40   282 use PPI::Token::Symbol;
  40         147  
  40         1409  
11 40     40   25804 use PPIx::QuoteLike;
  40         6571399  
  40         1960  
12              
13 40     40   480 use Perl::Critic::Utils qw< :characters :severities >;
  40         115  
  40         3034  
14 40     40   13751 use parent 'Perl::Critic::Policy';
  40         139  
  40         394  
15              
16             our $VERSION = '1.146';
17              
18             #-----------------------------------------------------------------------------
19              
20             Readonly::Scalar my $EXPL =>
21             q<Unused variables clutter code and make it harder to read>;
22              
23             #-----------------------------------------------------------------------------
24              
25 107     107 0 1745 sub supported_parameters { return () }
26 78     78 1 404 sub default_severity { return $SEVERITY_MEDIUM }
27 74     74 1 428 sub default_themes { return qw< core maintenance certrec > }
28 48     48 1 175 sub applies_to { return qw< PPI::Document > }
29              
30             #-----------------------------------------------------------------------------
31              
32             sub violates {
33 48     48 1 169 my ( $self, $elem, $document ) = @_;
34              
35 48         119 my %symbol_usage;
36 48         213 _get_symbol_usage( \%symbol_usage, $document );
37 48         234 _get_regexp_symbol_usage( \%symbol_usage, $document );
38 48 100       187 return if not %symbol_usage;
39              
40 46         148 my $declarations = $document->find('PPI::Statement::Variable');
41 46 100       181 return if not $declarations;
42              
43 44         90 my @violations;
44              
45             DECLARATION:
46 44         95 foreach my $declaration ( @{$declarations} ) {
  44         135  
47 105 100       1513 next DECLARATION if 'my' ne $declaration->type();
48              
49 76         2964 my @children = $declaration->schildren();
50 76 100   231   1643 next DECLARATION if any { $_->content() eq q<=> } @children;
  231         850  
51              
52             VARIABLE:
53 9         88 foreach my $variable ( $declaration->variables() ) {
54 11         526 my $count = $symbol_usage{ $variable };
55 11 50       41 next VARIABLE if not $count; # BUG!
56 11 100       49 next VARIABLE if $count > 1;
57              
58 4         23 push
59             @violations,
60             $self->violation(
61             qq<"$variable" is declared but not used.>,
62             $EXPL,
63             $declaration,
64             );
65             }
66             }
67              
68 44         821 return @violations;
69             }
70              
71             sub _get_symbol_usage {
72 51     51   139 my ( $symbol_usage, $document ) = @_;
73              
74 51         172 my $symbols = $document->find('PPI::Token::Symbol');
75 51 100       1629 return if not $symbols;
76              
77 49         133 foreach my $symbol ( @{$symbols} ) {
  49         140  
78 208         8133 $symbol_usage->{ $symbol->symbol() }++;
79             }
80              
81 49         3164 foreach my $class ( qw{
82             PPI::Token::Quote::Double
83             PPI::Token::Quote::Interpolate
84             PPI::Token::QuoteLike::Backtick
85             PPI::Token::QuoteLike::Command
86             PPI::Token::QuoteLike::Readline
87             PPI::Token::HereDoc
88             } ) {
89 294         6754 foreach my $double_quotish (
90 294 100       718 @{ $document->find( $class ) || [] }
91             ) {
92 3 50       33 my $str = PPIx::QuoteLike->new( $double_quotish )
93             or next;
94 3         8712 foreach my $var ( $str->variables() ) {
95 2         8928 $symbol_usage->{ $var }++;
96             }
97             }
98             }
99              
100 49         1462 return;
101             }
102              
103             sub _get_regexp_symbol_usage {
104 48     48   156 my ( $symbol_usage, $document ) = @_;
105              
106 48         149 foreach my $class ( qw{
107             PPI::Token::Regexp::Match
108             PPI::Token::Regexp::Substitute
109             PPI::Token::QuoteLike::Regexp
110             } ) {
111              
112 144 100       311 foreach my $regex ( @{ $document->find( $class ) || [] } ) {
  144         344  
113              
114 3 50       18 my $ppix = $document->ppix_regexp_from_element( $regex ) or next;
115 3 50       33312 $ppix->failures() and next;
116              
117 3         23 foreach my $code ( @{
118 3 50       12 $ppix->find( 'PPIx::Regexp::Token::Code' ) || [] } ) {
119 3 50       1226 my $subdoc = $code->ppi() or next;
120 3         38 _get_symbol_usage( $symbol_usage, $subdoc );
121             }
122              
123             }
124              
125             }
126              
127 48         121 return;
128             }
129              
130             #-----------------------------------------------------------------------------
131              
132             1;
133              
134             __END__
135              
136             #-----------------------------------------------------------------------------
137              
138             =pod
139              
140             =head1 NAME
141              
142             Perl::Critic::Policy::Variables::ProhibitUnusedVariables - Don't ask for storage you don't need.
143              
144              
145             =head1 AFFILIATION
146              
147             This Policy is part of the core L<Perl::Critic|Perl::Critic>
148             distribution.
149              
150              
151             =head1 DESCRIPTION
152              
153             Unused variables clutter code and require the reader to do mental
154             bookkeeping to figure out if the variable is actually used or not.
155              
156             At present, this Policy is very limited in order to ensure that there
157             aren't any false positives. Hopefully, this will become more
158             sophisticated soon.
159              
160             Right now, this only looks for simply declared, uninitialized lexical
161             variables.
162              
163             my $x; # not ok, assuming no other appearances.
164             my @y = (); # ok, not handled yet.
165             our $z; # ok, global.
166             local $w; # ok, global.
167              
168             This module is very dumb: it does no scoping detection, i.e. if the
169             same variable name is used in two different locations, even if they
170             aren't the same variable, this Policy won't complain.
171              
172             Have to start somewhere.
173              
174              
175             =head1 CONFIGURATION
176              
177             This Policy is not configurable except for the standard options.
178              
179              
180             =head1 AUTHOR
181              
182             Elliot Shank C<< <perl@galumph.com> >>
183              
184              
185             =head1 COPYRIGHT
186              
187             Copyright (c) 2008-2021 Elliot Shank.
188              
189             This program is free software; you can redistribute it and/or modify
190             it under the same terms as Perl itself. The full text of this license
191             can be found in the LICENSE file included with this module.
192              
193             =cut
194              
195             # Local Variables:
196             # mode: cperl
197             # cperl-indent-level: 4
198             # fill-column: 78
199             # indent-tabs-mode: nil
200             # c-indentation-style: bsd
201             # End:
202             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :