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   24193 use 5.010001;
  40         138  
4 40     40   173 use strict;
  40         106  
  40         777  
5 40     40   136 use warnings;
  40         70  
  40         1502  
6 40     40   153 use Readonly;
  40         102  
  40         2068  
7 40     40   205 use version ();
  40         63  
  40         873  
8              
9 40     40   136 use Perl::Critic::Utils qw( :severities );
  40         96  
  40         2242  
10 40     40   4243 use parent 'Perl::Critic::Policy';
  40         174  
  40         193  
11              
12             our $VERSION = '1.156';
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 90     90 0 546 sub supported_parameters { return () }
24 75     75 1 239 sub default_severity { return $SEVERITY_HIGHEST }
25 92     92 1 275 sub default_themes { return qw(core pbp bugs certrec ) }
26 37     37 1 65 sub applies_to { return 'PPI::Statement::Compound' }
27              
28             #-----------------------------------------------------------------------------
29              
30             sub prepare_to_scan_document {
31 37     37 1 89 my ( undef, $document ) = @_;
32             # perl5004delta says that is when lexical iterators were introduced,
33             # so ... (RT 67760)
34 37         131 my $version = $document->highest_explicit_perl_version();
35 37   33     138 return ! $version || $version >= $MINIMUM_PERL_VERSION;
36             }
37              
38             #-----------------------------------------------------------------------------
39              
40             sub violates {
41 11     11 1 22 my ( $self, $elem, undef ) = @_;
42              
43             # First child will be 'for' or 'foreach' keyword
44 11 100       35 return if $elem->type() ne 'foreach';
45              
46 6         322 my $first_child = $elem->schild(0);
47 6 50       68 return if not $first_child;
48 6 50       27 my $start = $first_child->isa('PPI::Token::Label') ? 1 : 0;
49              
50 6         19 my $potential_scope = $elem->schild($start + 1);
51 6 50       71 return if not $potential_scope;
52 6 50       30 return if $potential_scope->isa('PPI::Structure::List');
53              
54 6 50       21 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 :