variable name - the name of the variable, preceded by a keyword
note - an optional note referring to another line
-The checks are for lexical variables introduced by the keywords B<my> and B<state>. The types of checks which are made are identified in the output with one
-of the letters, B<r>, B<s>, B<p>, and B<u> as follows:
+If there are a large number of issues it can be convenient to read the file
+into a spreadsheet. The checks are for lexical variables introduced by the
+keywords B<my> and B<state>. The types of checks which are made are identified
+in the output with one of the letters, B<r>, B<s>, B<p>, and B<u> as follows:
=over 4
=item B<r: reused variable name>
These are variables which are re-declared in the scope of a variable with the
-identical name. This can be confusing. This is similar to the B<Perl::Critic>
-policy B<Variables::ProhibitReusedNames>
+identical name. This can be confusing (perhaps not when the code is first
+written, but possibly later when an update is being made). Note that this is
+similar to the B<Perl::Critic> policy B<Variables::ProhibitReusedNames>.
=item B<s: sigil change but reused bareword>
=item B<p: package-crossing variables>
These are lexical variables which are declared in one package and still visible
-in subroutines of a different package in the same file. This check is limited
-to packages which are not enclosed in block braces in order skip some common
-use cases.
+in subroutines of a different package in the same file. This can be confusing.
+This check is limited to packages which are not enclosed in block braces in
+order skip some common use cases.
=item B<u: unused variables>
-These are variables which are declared but not used. There are many reasons for
-having unused variables. For example, they can occur in lists of values
-provided by another routine or data structure but which are not needed, or they
-might be defined for possible future program development, clarity or debugging.
-But sometimes they can occur due to being orphaned by a coding change, due to a
+These are variables which occur just one time in their scope in the program
+text. Calling them B<unused> is convenient but not really accurate. There
+are many reasons for having such variables. For example, they might occur in a
+list of values provided by another routine or data structure, and therefor must
+be listed, even though they might not be referenced again. Or they might be
+defined for possible future program development, clarity or debugging. But
+sometimes they can occur due to being orphaned by a coding change, due to a
misspelling, or by having an unintentional preceding C<my>. So it is worth
reviewing them, especially for new code.
my $as_iterator =
$is_my_state{$my_keyword}
? EMPTY_STRING
- : ' as_iterator';
+ : ' as iterator';
$note = "reused$as_iterator - see line $first_line";
$letter = 'r';
}
return unless ( $token_paren eq '(' );
# found a paren, but does it belong to this keyword?
- my $is_keyword_paren;
my $seqno_paren = $rLL->[$K_paren]->[_TYPE_SEQUENCE_];
# see if this opening paren immediately follows the keyword
my $K_n = $self->K_next_code($KK);
return unless $K_n;
- my $token_KK = $rLL->[$KK]->[_TOKEN_];
-
- # is it the next token?
- if ( $K_n == $K_paren ) {
- $is_keyword_paren = 1;
- }
- # if not, then look for pattern 'for my $var ('
- elsif ($is_for_foreach{$token_KK}
- && $rLL->[$K_n]->[_TYPE_] eq 'k'
- && $is_my_state{ $rLL->[$K_n]->[_TOKEN_] } )
- {
-
- # look for an identifier after the 'my'
- $K_n = $self->K_next_code($K_n);
- return unless $K_n;
- if ( $rLL->[$K_n]->[_TYPE_] eq 'i' ) {
-
- # followed by the same '('
- $K_n = $self->K_next_code($K_n);
- $is_keyword_paren = $K_n && $K_n == $K_paren;
- }
- }
+ # is it the next token? this is the common case
+ my $K_end_iterator;
+ my $saw_my;
+ my $token_KK = $rLL->[$KK]->[_TOKEN_];
+ if ( $K_n != $K_paren ) {
+
+ # look for 'for $var (', 'for my $var (', 'for my (', 'for $var ('
+ if ( $is_for_foreach{$token_KK} ) {
+ my $type_K_n = $rLL->[$K_n]->[_TYPE_];
+ my $token_K_n = $rLL->[$K_n]->[_TOKEN_];
+
+ # skip past a 'my'
+ if ( $type_K_n eq 'k' ) {
+ if ( $is_my_state{$token_K_n} ) {
+ $K_n = $self->K_next_code($K_n);
+ $saw_my = 1;
+ }
+ else { return }
+ }
- # look for iterator pattern 'for $var ('
- elsif ($is_for_foreach{$token_KK}
- && $rLL->[$K_n]->[_TYPE_] eq 'i' )
- {
- # followed by the same '('
- $K_n = $self->K_next_code($K_n);
- if ( $K_n && $K_n == $K_paren && $K_n > $K_end_my ) {
- $is_keyword_paren = 1;
+ # skip an identifier
+ if ( $K_n && $K_n != $K_paren && $rLL->[$K_n]->[_TYPE_] eq 'i' )
+ {
+ $K_n = $self->K_next_code($K_n);
- # Patch: force this iterator to be entered as new lexical
- $K_end_my = $K_paren;
- $my_keyword = $token_KK;
+ # force this iterator to be entered as new lexical
+ $K_end_iterator = $K_paren;
+ }
}
}
- else {
- # not the correct opening paren, give up
- }
- return unless ($is_keyword_paren);
+ # we must be at the paren
+ return unless ( $K_n && $K_n == $K_paren );
# now jump to the closing paren
$K_paren = $self->[_K_closing_container_]->{$seqno_paren};
# then look for the opening brace immediately after it
my $K_brace = $self->K_next_code($K_paren);
- return
- unless ( defined($K_brace) && $rLL->[$K_brace]->[_TOKEN_] eq '{' );
+ return unless ($K_brace);
+ # check for experimental 'for list': for my ( $a, $b) (@list) {
+ # ^
+ if ( $rLL->[$K_brace]->[_TOKEN_] eq '('
+ && !$K_end_iterator
+ && $is_for_foreach{$token_KK} )
+ {
+ if ( !$saw_my ) { $K_end_iterator = $K_brace }
+ my $seqno_test = $rLL->[$K_brace]->[_TYPE_SEQUENCE_];
+ my $K_test = $self->[_K_closing_container_]->{$seqno_test};
+ return unless $K_test;
+ $K_brace = $self->K_next_code($K_test);
+ return unless ($K_brace);
+ }
+
+ return unless ( $rLL->[$K_brace]->[_TOKEN_] eq '{' );
my $seqno_brace = $rLL->[$K_brace]->[_TYPE_SEQUENCE_];
- return unless ( $rblock_type_of_seqno->{$seqno_brace} );
+ return unless ($seqno_brace);
+ my $block_type = $rblock_type_of_seqno->{$seqno_brace};
+
+ # Verify that this is the correct brace
+ if ( $block_type ne $token_KK ) {
- # success
+ # If not, this is unexpected and should be investigated
+ # (the block type may have been mis-marked)
+ my $lno = $rLL->[$KK]->[_LINE_INDEX_] + 1;
+ DEVEL_MODE && Fault(<<EOM);
+at line $lno: found block type $block_type: expecting $token_KK - please check
+EOM
+ return;
+ }
+
+ # Found the brace. Mark an iterator as a new lexical variable in order
+ # to catch something like:
+ # my $i;
+ # foreach $i(...) { }
+ # where the iterator $i is not the same as the first $i,
+ # We should be beyond any existing $K_end_my, but check anyway:
+ if ( $K_end_iterator && $K_end_iterator > $K_end_my ) {
+ $K_end_my = $K_end_iterator;
+ $my_keyword = $token_KK;
+ }
return ($seqno_brace);
};
} ## end package Perl::Tidy::Formatter
1;
+