]> git.donarmstrong.com Git - perltidy.git/commitdiff
fix instability b1491
authorSteve Hancock <perltidy@users.sourceforge.net>
Wed, 16 Oct 2024 23:52:58 +0000 (16:52 -0700)
committerSteve Hancock <perltidy@users.sourceforge.net>
Wed, 16 Oct 2024 23:52:58 +0000 (16:52 -0700)
dev-bin/run_convergence_tests.pl.data
dev-bin/run_convergence_tests.pl.expect
lib/Perl/Tidy/Formatter.pm

index ab362386e95351f832b8888f230903e48d764671..2a6dc5afe44266dbc2a6a5b210a9d2f82d22a901 100644 (file)
@@ -12323,6 +12323,24 @@ $e_str->bind ( '<return>' => sub {$e_hnr->tabfocus if $e_hnr->can ( 'tabfocus' )
 --delete-trailing-commas
 --block-brace-tightness=2
 
+==> b1491.in <==
+@ISA =
+       qw( Stack )
+       ; # inherit from Stack
+@ISA =
+       qw(
+    Stack )
+       ; # inherit from Stack
+
+==> b1491.par <==
+--maximum-line-length=18
+--continuation-indentation=7
+--paren-vertical-tightness-closing=3
+--paren-tightness=0
+--qw-as-function
+--add-trailing-commas
+--want-trailing-commas=1
+
 ==> b156.in <==
 # State 1
 {
index 6ed49f26bc27e2986b2f99daf2a2a109f04d4043..1aadf94d4102b2d28614cb4b836522d03b3776c7 100644 (file)
@@ -8340,6 +8340,16 @@ $e_str->bind (
 $e_str->bind (
 '<return>' => sub {$e_hnr->tabfocus if $e_hnr->can ( 'tabfocus' );} );
 
+==> b1491 <==
+@ISA =
+       qw(
+    Stack )
+       ; # inherit from Stack
+@ISA =
+       qw(
+    Stack )
+       ; # inherit from Stack
+
 ==> b156 <==
 # State 1
 {
index 93cd6d5c48a9edc107bc47b6f7757fb2d0aff67d..7c4a242539de969c92a9c00ce24e9d7a22667763 100644 (file)
@@ -6667,6 +6667,7 @@ EOM
 
     # variables for the -qwaf option
     my $in_qw_seqno;
+    my $in_qw_comma_count;
     my $last_new_seqno;
     my %new_seqno_from_old_seqno;
     my $last_ending_in_quote;
@@ -6683,6 +6684,7 @@ EOM
         %saw_closing_seqno = ();
 
         $in_qw_seqno              = 0;
+        $in_qw_comma_count        = 0;    # b1491
         %new_seqno_from_old_seqno = ();
         $last_ending_in_quote     = 0;
         $added_seqno_count        = 0;
@@ -7002,7 +7004,8 @@ EOM
             # Do not use -qwaf under high stress (b1482,b1483,b1484,b1485,1486)
             # Note: so far all known cases of stress instability have had -naws
             # set, so this is included for now. It may eventually need to be
-            # removed.
+            # removed. NOTE: The update for b1491 also fixes cases b1482-6 in a
+            # more general way, so this test can probably be removed.
             if ( !$rOpts_add_whitespace && $level_words >= $high_stress_level )
             {
                 return;
@@ -7066,7 +7069,7 @@ EOM
         if (
                @words
             && $closing
-            && substr( $words[-1], -1, 1 ) eq '\\'
+            && substr( $words[-1], -1, 1 ) eq BACKSLASH
             && (   $tightness{')'} == 2
                 || $tightness{')'} == 1 && @words == 1 )
           )
@@ -7121,7 +7124,8 @@ EOM
 
         # All words must be followed by a comma except for an intact
         # structure with a single word, like 'qw(hello)'
-        my $commas_needed = !( $opening && $closing && @words == 1 );
+        my $commas_needed =
+          !( ( $opening || !$in_qw_comma_count ) && $closing && @words == 1 );
 
         # Make and push each word as a type 'Q' quote followed by a phantom
         # comma. The phantom comma is type ',' and is processed
@@ -7144,11 +7148,15 @@ EOM
                 $rtoken_word->[_LEVEL_] = $level_words;
                 push @{$rLL}, $rtoken_word;
 
-                # Add a trailing comma unless this is a single
-                # item. For a single item we want just one token in the
-                # container so that the single-item spacing rule will apply as
-                # expected.  There is no danger that a real trailing comma will
-                # be added since no other commas will be in the container.
+                # Add a comma if needed.  NOTE on trailing commas:
+                # - For multiple words: Trailing commas must be added.
+                #   Otherwise, -atc might put a comma in a qw list.
+                # - For single words: Trailing commas are not required, and
+                #   are best avoided. This is because:
+                #   - atc will not add commas to a list which has no commas
+                #   - This will make the single-item spacing rule work as
+                #   expected.
+                #   - This will reduce the chance of instability (b1491)
                 if ($commas_needed) {
                     my $rtoken_comma =
                       copy_token_as_type( $rtoken_q, ',', EMPTY_STRING );
@@ -7162,6 +7170,24 @@ EOM
         # make and push closing sequenced item ')'
         if ($closing) {
 
+            # OPTIONAL: remove a previous comma if it is the only one. This can
+            # happen if this closing paren starts a new line and there was just
+            # one word in the qw list. The reason for doing this would be
+            # to avoid possible instability, but none is currently known. b1491.
+            # This has been tested but is currently inactive because it has not
+            # been found to be necessary.
+            if (   0
+                && !@words
+                && $in_qw_comma_count == 1
+                && $rLL->[-1]->[_TYPE_] eq ',' )
+            {
+
+                # It is simpler to convert it to a blank; otherwise it would
+                # be necessary to change the range [Kfirst,Klast] of the
+                # previous line and the current line.
+                $rLL->[-1]->[_TYPE_] = 'b';
+            }
+
             # follow input spacing before ')'
             if ($has_closing_space) {
                 my $rtoken_space = copy_token_as_type( $rtoken_q, 'b', SPACE );
@@ -7181,9 +7207,14 @@ EOM
             push @{$rLL}, $rtoken_closing;
 
             # all done with this qw list
-            $in_qw_seqno = 0;
+            $in_qw_seqno       = 0;
+            $in_qw_comma_count = 0;
+        }
+        else {
+            $in_qw_comma_count += $comma_count;
         }
 
+        # The '_ending_in_quote' flag for this line is no longer needed
         if ($is_continued) { $line_of_tokens->{_ending_in_quote} = 0 }
 
         return;