]> git.donarmstrong.com Git - perltidy.git/commitdiff
update -duv to work better with v5.36 experimental for_list
authorSteve Hancock <perltidy@users.sourceforge.net>
Sat, 23 Dec 2023 16:14:37 +0000 (08:14 -0800)
committerSteve Hancock <perltidy@users.sourceforge.net>
Sat, 23 Dec 2023 16:14:37 +0000 (08:14 -0800)
bin/perltidy
lib/Perl/Tidy/Formatter.pm

index b8778fbff91c5bbf76aba0351706f8fe1b242d1b..b04dccc689b0fdb271b6464c6cbbbb4be8db5f6b 100755 (executable)
@@ -5531,16 +5531,19 @@ meaning:
     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>
 
@@ -5552,17 +5555,19 @@ confusing.
 =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.
 
index 507c146ade8e3a4d1d813dd8d9657fe9c9308dbd..a578c7b6285b9dabf3e444fc7203625a7a391a02 100644 (file)
@@ -8853,7 +8853,7 @@ sub scan_variable_usage {
                         my $as_iterator =
                           $is_my_state{$my_keyword}
                           ? EMPTY_STRING
-                          : ' as_iterator';
+                          : ' as iterator';
                         $note   = "reused$as_iterator - see line $first_line";
                         $letter = 'r';
                     }
@@ -9011,68 +9011,94 @@ sub scan_variable_usage {
         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);
     };
 
@@ -34088,3 +34114,4 @@ sub wrapup {
 
 } ## end package Perl::Tidy::Formatter
 1;
+