File Coverage

blib/lib/Perl/Critic/Policy/Variables/RequireLexicalLoopIterators.pm
Criterion Covered Total %
statement 36 37 97.3
branch 7 12 58.3
condition 1 3 33.3
subroutine 13 13 100.0
pod 5 6 83.3
total 62 71 87.3


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Variables::RequireLexicalLoopIterators;
2              
3 40     40   35657 use 5.010001;
  40         204  
4 40     40   343 use strict;
  40         148  
  40         994  
5 40     40   304 use warnings;
  40         144  
  40         1156  
6 40     40   297 use Readonly;
  40         234  
  40         2154  
7 40     40   378 use version ();
  40         170  
  40         1033  
8              
9 40     40   364 use Perl::Critic::Utils qw( :severities );
  40         178  
  40         2239  
10 40     40   5353 use parent 'Perl::Critic::Policy';
  40         151  
  40         324  
11              
12             our $VERSION = '1.150';
13              
14             #-----------------------------------------------------------------------------
15              
16             Readonly::Scalar my $DESC => q{Loop iterator is not lexical};
17             Readonly::Scalar my $EXPL => [ 108 ];
18              
19             Readonly::Scalar my $MINIMUM_PERL_VERSION => version->new( 5.004 );
20              
21             #-----------------------------------------------------------------------------
22              
23 89     89 0 1596 sub supported_parameters { return () }
24 74     74 1 322 sub default_severity { return $SEVERITY_HIGHEST }
25 92     92 1 363 sub default_themes { return qw(core pbp bugs certrec ) }
26 36     36 1 98 sub applies_to { return 'PPI::Statement::Compound' }
27              
28             #-----------------------------------------------------------------------------
29              
30             sub prepare_to_scan_document {
31 36     36 1 93 my ( $self, $document ) = @_;
32             # perl5004delta says that is when lexical iterators were introduced,
33             # so ... (RT 67760)
34 36         128 my $version = $document->highest_explicit_perl_version();
35 36   33     145 return ! $version || $version >= $MINIMUM_PERL_VERSION;
36             }
37              
38             #-----------------------------------------------------------------------------
39              
40             sub violates {
41 11     11 1 28 my ( $self, $elem, undef ) = @_;
42              
43             # First child will be 'for' or 'foreach' keyword
44 11 100       47 return if $elem->type() ne 'foreach';
45              
46 6         311 my $first_child = $elem->schild(0);
47 6 50       68 return if not $first_child;
48 6 50       26 my $start = $first_child->isa('PPI::Token::Label') ? 1 : 0;
49              
50 6         25 my $potential_scope = $elem->schild($start + 1);
51 6 50       99 return if not $potential_scope;
52 6 50       44 return if $potential_scope->isa('PPI::Structure::List');
53              
54 6 50       22 return if $potential_scope eq 'my';
55              
56 0           return $self->violation( $DESC, $EXPL, $elem );
57             }
58              
59             #-----------------------------------------------------------------------------
60              
61             1;
62              
63             __END__
64              
65             #-----------------------------------------------------------------------------
66              
67             =pod
68              
69             =for stopwords foreach perlsyn
70              
71             =head1 NAME
72              
73             Perl::Critic::Policy::Variables::RequireLexicalLoopIterators - Write C<for my $element (@list) {...}> instead of C<for $element (@list) {...}>.
74              
75              
76             =head1 AFFILIATION
77              
78             This Policy is part of the core L<Perl::Critic|Perl::Critic>
79             distribution.
80              
81              
82             =head1 DESCRIPTION
83              
84             This policy asks you to use C<my>-style lexical loop iterator variables:
85              
86             foreach my $zed (...) {
87             ...
88             }
89              
90             Unless you use C<my>, C<for>/C<foreach> loops use a global variable with
91             its value C<local> to the block. In other words,
92              
93             foreach $zed (...) {
94             ...
95             }
96              
97             is more-or-less equivalent to
98              
99             {
100             local $zed
101             foreach $zed (...) {
102             ...
103             }
104             }
105              
106             This may not seem like a big deal until you see code like
107              
108             my $bicycle;
109             for $bicycle (@things_attached_to_the_bike_rack) {
110             if (
111             $bicycle->is_red()
112             and $bicycle->has_baseball_card_in_spokes()
113             and $bicycle->has_bent_kickstand()
114             ) {
115             $bicycle->remove_lock();
116              
117             last;
118             }
119             }
120              
121             if ( $bicycle and $bicycle->is_unlocked() ) {
122             ride_home($bicycle);
123             }
124              
125             which is not going to allow you to arrive in time for dinner with your
126             family because the C<$bicycle> outside the loop is not changed by the
127             loop. You may have unlocked your bicycle, but you can't remember which
128             one it was.
129              
130             Lexical loop variables were introduced in Perl 5.004. This policy does
131             not report violations on code which explicitly specifies an earlier
132             version of Perl (e.g. C<require 5.002;>).
133              
134              
135             =head1 CONFIGURATION
136              
137             This Policy is not configurable except for the standard options.
138              
139              
140             =head1 SEE ALSO
141              
142             L<"Foreach Loops" in perlsyn|perlsyn/Foreach Loops>
143              
144             L<"my() in Control Structures" in perl5004delta|perl5004delta/my() in control structures>
145              
146              
147             =head1 AUTHOR
148              
149             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
150              
151              
152             =head1 COPYRIGHT
153              
154             Copyright (c) 2005-2023 Imaginative Software Systems
155              
156             This program is free software; you can redistribute it and/or modify
157             it under the same terms as Perl itself. The full text of this license
158             can be found in the LICENSE file included with this module.
159              
160             =cut
161              
162             # Local Variables:
163             # mode: cperl
164             # cperl-indent-level: 4
165             # fill-column: 78
166             # indent-tabs-mode: nil
167             # c-indentation-style: bsd
168             # End:
169             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :