]> git.donarmstrong.com Git - perltidy.git/commitdiff
Fixed problem where -bbpi could cause blinking states
authorSteve Hancock <perltidy@users.sourceforge.net>
Wed, 27 Jan 2021 15:27:33 +0000 (07:27 -0800)
committerSteve Hancock <perltidy@users.sourceforge.net>
Wed, 27 Jan 2021 15:27:33 +0000 (07:27 -0800)
lib/Perl/Tidy/Formatter.pm
local-docs/BugLog.pod

index fd7162016148ccb7967bd86fa4b11161a38282bd..26a5fab82afa6c464cf065c8d11665919a45afc3 100644 (file)
@@ -5661,8 +5661,7 @@ sub respace_tokens {
         $self->[_K_first_seq_item_] = $KNEXT;
     }
 
-    # find and remember lists by sequence number
-    # TODO: eventually this should hold a name for the list
+    # Find and remember lists by sequence number
     my $ris_list_by_seqno = {};
     foreach my $seqno ( keys %{$K_opening_container} ) {
         my $K_opening  = $K_opening_container->{$seqno};
@@ -5670,17 +5669,15 @@ sub respace_tokens {
         next if ($block_type);
         my $rtype_count = $rtype_count_by_seqno->{$seqno};
         next unless ($rtype_count);
-        ##my $fat_comma_count = $rtype_count->{'=>'};
         my $comma_count     = $rtype_count->{','};
         my $semicolon_count = $rtype_count->{';'};
 
-       # We will define a list to be a container with one or more commas and
-       # no semicolons.  Previously we allowed either a comma or fat comma,
-        # but requiring a comma gives a guarantee later routines that there 
+        # We will define a list to be a container with one or more commas and
+        # no semicolons.  Previously we allowed either a comma or fat comma,
+        # but requiring a comma gives a guarantee later routines that there
         # is a good line break point within the list.  This is useful because
-        # we are mainly concerned with formatting and vertically aligning 
+        # we are mainly concerned with formatting and vertically aligning
         # multiple-line lists here.
-        ##if ( ( $fat_comma_count || $comma_count ) && !$semicolon_count ) {
         if ( $comma_count && !$semicolon_count ) {
             $ris_list_by_seqno->{$seqno} = $seqno;
         }
@@ -7571,13 +7568,16 @@ sub adjust_container_indentation {
 
     # Loop over all opening container tokens
     my $K_opening_container  = $self->[_K_opening_container_];
+    my $K_closing_container  = $self->[_K_closing_container_];
     my $ris_broken_container = $self->[_ris_broken_container_];
     foreach my $seqno ( keys %{$K_opening_container} ) {
-        my $KK = $K_opening_container->{$seqno};
 
-        # this routine is not for code block braces
-        my $block_type = $rLL->[$KK]->[_BLOCK_TYPE_];
-        next if ($block_type);
+        # This is only for list containers
+        next unless $self->is_list_by_seqno($seqno);
+
+        my $KK        = $K_opening_container->{$seqno};
+        my $K_closing = $K_closing_container->{$seqno};
+        next unless defined($K_closing);
 
         # These flags only apply if the corresponding -bb* flags
         # have been set to non-default values
@@ -7598,21 +7598,63 @@ sub adjust_container_indentation {
         }
         next unless ( $is_equal_or_fat_comma{$prev_type} );
 
-        # This is only for list containers
-        next unless $self->is_list_by_seqno($seqno);
+        # NOTE: We are adjusting indentation of the opening container. The
+        # closing container will normally follow the indentation of the opening
+        # container automatically, so this is not currently done.
+        my $ci = $rLL->[$KK]->[_CI_LEVEL_];
+        next unless ($ci);
 
         # and only for broken lists.
         # Require container to span 3 or more line to avoid blinkers,
         # so line difference must be 2 or more.
         next
-          if ( $ris_broken_container->{$seqno}
-            && $ris_broken_container->{$seqno} <= 1 );
+          if (!$ris_broken_container->{$seqno}
+            || $ris_broken_container->{$seqno} <= 1 );
+
+        # To avoid blinkers, we only want to change ci if this container
+        # will definitely be broken.  We are doing this before the final
+        # decision is made, so we have to use whatever information we can.
+        # In most cases it wouldn't make any difference if we added the ci
+        # or not, but there are some edge cases where adding the ci can
+        # cause blinking states, so we need to try to only add ci if the
+        # container will really be broken.  One of the following
+        # conditions will be taken as sufficient:
+        #  (1) the container is permanently broken by blank lines,
+        #      side comments, here docs, pod, ..
+        #  (2) contains multiple fat commas or
+        #  (3) that this container token starts a new line, or
+        #  (4) container is too long for one line
+
+        # (1) TBD: is permanently broken container: not yet implemented.
+
+        # (2) or the opening paren, bracket, or brace starts a new line
+        my $opening_container_starts_line =
+          $rLL->[$KK]->[_LINE_INDEX_] > $rLL->[$Kprev]->[_LINE_INDEX_];
+        if ( !$opening_container_starts_line ) { #<<<
+
+        # (3) or it contains multiple fat commas
+        my $rtype_count     = $self->[_rtype_count_by_seqno_]->{$seqno};
+        my $fat_comma_count = $rtype_count->{'=>'};
+        if ( !$fat_comma_count || $fat_comma_count < 2 ) { #<<<
+
+        # (4) or the net container length exceeds maximum line length
+        my $starting_indent = 0;
+        if ( !$rOpts_variable_maximum_line_length ) {
+            my $level = $rLL->[$KK]->[_LEVEL_];
+            $starting_indent = $rOpts_indent_columns * $level +
+              $ci * $rOpts_continuation_indentation;
+        }
+        my $length = $self->cumulative_length_before_K($K_closing) -
+          $self->cumulative_length_before_K($KK);
+        my $excess_length =
+          $starting_indent + $length - $rOpts_maximum_line_length;
 
-        # NOTE: We are adjusting indentation of the opening container. The
-        # closing container will normally follow the indentation of the opening
-        # container automatically, so this is not currently done.
-        my $ci = $rLL->[$KK]->[_CI_LEVEL_];
-        next unless ($ci);
+        next if ( $excess_length <= 0 );
+
+        } ## end (3) fat comma test
+        } ## end (2) opening container token starts new line
+
+        # OK to change ci...
 
         # option 1: outdent
         if ( $flag == 1 ) {
index 674a194a0c86d6659dc2dd87d6c6dcdfce47f24c..f0744a7b034c2e13f694ca939e246ee2643542a0 100644 (file)
@@ -2,6 +2,24 @@
 
 =over 4
 
+=item B<Avoid blinking states associated with -bbpi and similar flags>
+
+Random testing with extreme parameter values revealed blinking states
+associated with the -bbpi and related flags.  The problem was that
+continuation indentation was sometimes being added according to the flag
+but the lists were not actually being broken.  After this was fixed
+the following cases ran correctly: 
+
+b024 b035 b036 b040 b042 b047 b049 b050 b051 b052 b053 b054 b057 b062 b063 b073
+b074 b076 b080 b083 b085 b086 b087 b088 b102 b103 b104 b106 b107 b108 b115 b118
+b121 b123 b125 b127 b132 b137 b139 b140 b141 b143 b144 b148 b159 b175 b177 b180
+b181 b188 b189 b200 b201 b202 b204 b207 b212 b213 b214 b226 b227 b228 b229 b230
+b232 b239 b240 b241 b243 b248 b250 b255 b277 b286 b287 b290 b293 b298 b301 b306
+b308 b328 b351 b353 b357 b378 b380 b390 b391 b393 b394 b399 b400 b401 b406 b413
+b415 b416 b430 b431 b442 b447 b463 b470 b491 b495
+
+27 Jan 2021.
+
 =item B<Revise coding for the --freeze-whitespace option>
 
 Random testing produced some blinking states which were traced to an incorrect