]> git.donarmstrong.com Git - perltidy.git/commitdiff
fix irregular -ce indentation seen in rt #144979
authorSteve Hancock <perltidy@users.sourceforge.net>
Fri, 4 Nov 2022 00:08:33 +0000 (17:08 -0700)
committerSteve Hancock <perltidy@users.sourceforge.net>
Fri, 4 Nov 2022 00:08:33 +0000 (17:08 -0700)
12 files changed:
CHANGES.md
lib/Perl/Tidy/Formatter.pm
t/snippets/expect/git09.git09
t/snippets/expect/git10.git10
t/snippets/expect/rt144979.def [new file with mode: 0644]
t/snippets/expect/rt144979.rt144979 [new file with mode: 0644]
t/snippets/packing_list.txt
t/snippets/rt144979.in [new file with mode: 0644]
t/snippets/rt144979.par [new file with mode: 0644]
t/snippets15.t
t/snippets16.t
t/snippets27.t

index 13b3c31d3dacfe15abdc9269916f9795e932c45d..75adf91ae8a6302adc9bef3b80814f4e2d6f394c 100644 (file)
@@ -6,6 +6,9 @@
       Several minor issues have been fixed, and some new parameters have been
       added, as follows:
 
+    - Fixed rare problem with irregular indentation involving --cuddled-else,
+      usually also with the combination -xci and -lp.  Reported in rt #144979.
+
     - Add option --weld-fat-comma (-wfc) for issue git #108. When -wfc
       is set, along with -wn, perltidy is allowed to weld an opening paren
       to an inner opening container when they are separated by a hash key
index d32e44f76cb8aaa88204bd8d86642517373c4586..919e8c1188d3894541b577e37e9a9eb2b1dfc48b 100644 (file)
@@ -458,6 +458,8 @@ BEGIN {
         _rparent_of_seqno_          => $i++,
         _rchildren_of_seqno_        => $i++,
         _ris_list_by_seqno_         => $i++,
+        _ris_cuddled_closing_brace_ => $i++,
+        _ris_cuddled_opening_brace_ => $i++,
         _rbreak_container_          => $i++,
         _rshort_nested_             => $i++,
         _length_function_           => $i++,
@@ -877,6 +879,8 @@ sub new {
     $self->[_rparent_of_seqno_]          = {};
     $self->[_rchildren_of_seqno_]        = {};
     $self->[_ris_list_by_seqno_]         = {};
+    $self->[_ris_cuddled_closing_brace_] = {};
+    $self->[_ris_cuddled_opening_brace_] = {};
 
     $self->[_rbreak_container_] = {};                 # prevent one-line blocks
     $self->[_rshort_nested_]    = {};                 # blocks not forced open
@@ -9100,10 +9104,12 @@ sub weld_cuddled_blocks {
 
     my $rLL = $self->[_rLL_];
     return unless ( defined($rLL) && @{$rLL} );
-    my $rbreak_container = $self->[_rbreak_container_];
 
-    my $K_opening_container = $self->[_K_opening_container_];
-    my $K_closing_container = $self->[_K_closing_container_];
+    my $rbreak_container          = $self->[_rbreak_container_];
+    my $ris_cuddled_closing_brace = $self->[_ris_cuddled_closing_brace_];
+    my $ris_cuddled_opening_brace = $self->[_ris_cuddled_opening_brace_];
+    my $K_opening_container       = $self->[_K_opening_container_];
+    my $K_closing_container       = $self->[_K_closing_container_];
 
     my $is_broken_block = sub {
 
@@ -9206,6 +9212,14 @@ sub weld_cuddled_blocks {
                     # so that the cuddled line is balanced.
                     $rbreak_container->{$opening_seqno} = 1
                       if ($CBO);
+
+                    # Remember which braces are cuddled.
+                    # The closing brace is used to set adjusted indentations.
+                    # The opening brace is not yet used but might eventually
+                    # be needed in setting adjusted indentation.
+                    $ris_cuddled_closing_brace->{$closing_seqno} = 1;
+                    $ris_cuddled_opening_brace->{$opening_seqno} = 1;
+
                 }
 
             }
@@ -25199,7 +25213,14 @@ sub get_seqno {
                         $terminal_type = $types_to_go[ $iend - 2 ];
                     }
                 }
-                if ( $terminal_type eq '{' ) {
+
+                # Patch for rt144979, part 2. Coordinated with part 1.
+                # Skip cuddled braces.
+                my $seqno_beg = $type_sequence_to_go[$ibeg];
+                my $is_cuddled_closing_brace = $seqno_beg
+                  && $self->[_ris_cuddled_closing_brace_]->{$seqno_beg};
+
+                if ( $terminal_type eq '{' && !$is_cuddled_closing_brace ) {
                     my $Kbeg = $K_to_go[$ibeg];
                     $ci_levels_to_go[$ibeg] = 0;
                 }
@@ -27082,6 +27103,13 @@ sub make_paren_name {
               = $self->get_opening_indentation( $ibeg_weld_fix, $ri_first,
                 $ri_last, $rindentation_list, $seqno_qw_closing );
 
+            # Patch for rt144979, part 1. Coordinated with part 2.
+            # Do not undo ci for a cuddled closing brace control; it
+            # needs to be treated exactly the same ci as an isolated
+            # closing brace.
+            my $is_cuddled_closing_brace = $seqno_beg
+              && $self->[_ris_cuddled_closing_brace_]->{$seqno_beg};
+
             # First set the default behavior:
             if (
 
@@ -27089,14 +27117,15 @@ sub make_paren_name {
                 # of the form:   ");  };  ];  )->xxx;"
                 $is_semicolon_terminated
 
-                # and 'cuddled parens' of the form:   ")->pack("
-                # Bug fix for RT #123749]: the types here were
-                # incorrectly '(' and ')'.  Corrected to be '{' and '}'
+                # and 'cuddled parens' of the form:   ")->pack(". Bug fix for RT
+                # #123749]: the TYPES here were incorrectly ')' and '('.  The
+                # corrected TYPES are '}' and '{'. But skip a cuddled block.
                 || (
                        $terminal_type eq '{'
                     && $type_beg eq '}'
                     && ( $nesting_depth_to_go[$iend] + 1 ==
                         $nesting_depth_to_go[$ibeg] )
+                    && !$is_cuddled_closing_brace
                 )
 
                 # remove continuation indentation for any line like
@@ -27108,6 +27137,9 @@ sub make_paren_name {
 
                     && (   $types_to_go[$iend] eq '{'
                         || $levels_to_go[$iend] < $level_beg )
+
+                    # but not if a cuddled block
+                    && !$is_cuddled_closing_brace
                 )
 
                 # and when the next line is at a lower indentation level...
@@ -27370,7 +27402,6 @@ sub make_paren_name {
 
         );
     }
-
 } ## end closure get_final_indentation
 
 sub get_opening_indentation {
index 12813d7b79a5cada97f04bacb46b584c8fb96c9a..c45824c0158c2779f2ce9d60758b1fb9acc90f2d 100644 (file)
@@ -1,8 +1,8 @@
 # no one-line block for first map with -ce -cbl=map,sort,grep
 @sorted = map {
     $_->[0]
-} sort {
+  } sort {
     $a->[1] <=> $b->[1] or $a->[0] cmp $b->[0]
-} map {
+  } map {
     [ $_, length($_) ]
-} @unsorted;
+  } @unsorted;
index 6fc2108f90976236066bcd0de665335c794eb14a..ee8f7ecc95fe8f29cae44891254ad88c3fff1bc9 100644 (file)
@@ -1,8 +1,8 @@
 # perltidy -wn -ce -cbl=sort,map,grep
 @sorted = map {
     $_->[0]
-} sort {
+  } sort {
     $a->[1] <=> $b->[1] or $a->[0] cmp $b->[0]
-} map {
+  } map {
     [ $_, length($_) ]
-} @unsorted;
+  } @unsorted;
diff --git a/t/snippets/expect/rt144979.def b/t/snippets/expect/rt144979.def
new file mode 100644 (file)
index 0000000..47b7492
--- /dev/null
@@ -0,0 +1,42 @@
+# part 1
+GetOptions(
+    "format|f=s" => sub {
+        my ( $n, $v ) = @_;
+        if ( ( my $k = $formats{$v} ) ) {
+            $format = $k;
+        }
+        else {
+            die("--format must be 'system' or 'user'\n");
+        }
+        return;
+    },
+);
+
+# part 2
+{
+    {
+        {
+            my $desc =
+              $access
+              ? "for -$op under use filetest 'access' $desc_tail"
+              : "for -$op $desc_tail";
+            {
+                local $SIG{__WARN__} = sub {
+                    my $w = shift;
+                    if ( $w =~ /^File::stat ignores VMS ACLs/ ) {
+                        ++$vwarn;
+                    }
+                    elsif ( $w =~ /^File::stat ignores use filetest 'access'/ )
+                    {
+                        ++$awarn;
+                    }
+                    else {
+                        $warnings .= $w;
+                    }
+                };
+                $rv = eval "$access; -$op \$stat";
+            }
+        }
+    }
+}
+
diff --git a/t/snippets/expect/rt144979.rt144979 b/t/snippets/expect/rt144979.rt144979
new file mode 100644 (file)
index 0000000..017e97b
--- /dev/null
@@ -0,0 +1,40 @@
+# part 1
+GetOptions(
+      "format|f=s" => sub {
+          my ( $n, $v ) = @_;
+          if ( ( my $k = $formats{$v} ) ) {
+              $format = $k;
+          } else {
+              die("--format must be 'system' or 'user'\n");
+          }
+          return;
+      },
+);
+
+# part 2
+{
+    {
+        {
+            my $desc =
+              $access
+              ? "for -$op under use filetest 'access' $desc_tail"
+              : "for -$op $desc_tail";
+            {
+                local $SIG{__WARN__} = sub {
+                    my $w = shift;
+                    if ( $w =~ /^File::stat ignores VMS ACLs/ ) {
+                        ++$vwarn;
+                    } elsif (
+                             $w =~ /^File::stat ignores use filetest 'access'/ )
+                    {
+                        ++$awarn;
+                    } else {
+                        $warnings .= $w;
+                    }
+                };
+                $rv = eval "$access; -$op \$stat";
+            }
+        }
+    }
+}
+
index 034b903a9b392b6daf702beb9978c6063cc15d47..6ca99208bad237b71aeb98419675baae918fd383 100644 (file)
 ../snippets27.t        dwic.def
 ../snippets27.t        dwic.dwic
 ../snippets27.t        wtc.wtc7
+../snippets27.t        rt144979.def
+../snippets27.t        rt144979.rt144979
 ../snippets3.t ce_wn1.ce_wn
 ../snippets3.t ce_wn1.def
 ../snippets3.t colin.colin
diff --git a/t/snippets/rt144979.in b/t/snippets/rt144979.in
new file mode 100644 (file)
index 0000000..69a3d0d
--- /dev/null
@@ -0,0 +1,38 @@
+# part 1
+GetOptions(
+      "format|f=s" => sub {
+          my ( $n, $v ) = @_;
+          if ( ( my $k = $formats{$v} ) ) {
+              $format = $k;
+      } else {
+              die("--format must be 'system' or 'user'\n");
+          }
+          return;
+      },
+);
+
+# part 2
+{{{
+            my $desc =
+              $access
+              ? "for -$op under use filetest 'access' $desc_tail"
+              : "for -$op $desc_tail";
+            {
+                local $SIG{__WARN__} = sub {
+                    my $w = shift;
+                    if ($w =~ /^File::stat ignores VMS ACLs/)
+                    {
+                        ++$vwarn;
+                      } elsif (
+                              $w =~ /^File::stat ignores use filetest 'access'/)
+                    {
+                        ++$awarn;
+                    } else
+                    {
+                        $warnings .= $w;
+                    }
+                };
+                $rv = eval "$access; -$op \$stat";
+            }
+}}}
+
diff --git a/t/snippets/rt144979.par b/t/snippets/rt144979.par
new file mode 100644 (file)
index 0000000..c12c979
--- /dev/null
@@ -0,0 +1 @@
+-xci -ce -lp
index f79abe8dbf34506e1b4cae6962bc68ab2620520c..b51c0c5fc7f3e85d78378c8d9c6b5cb631ae17f4 100644 (file)
@@ -407,11 +407,11 @@ elsif ( $i > $depth )  { $_ = 0; }
 # no one-line block for first map with -ce -cbl=map,sort,grep
 @sorted = map {
     $_->[0]
-} sort {
+  } sort {
     $a->[1] <=> $b->[1] or $a->[0] cmp $b->[0]
-} map {
+  } map {
     [ $_, length($_) ]
-} @unsorted;
+  } @unsorted;
 #14...........
         },
 
index 7322a8b5cbb886c6efca7b7ca4662b208205eda9..9e8f75c05b7afb3564a602ac2db0a2a271339f12 100644 (file)
@@ -236,11 +236,11 @@ my %Structure = $Self->PackageParse( String => $Package );
 # perltidy -wn -ce -cbl=sort,map,grep
 @sorted = map {
     $_->[0]
-} sort {
+  } sort {
     $a->[1] <=> $b->[1] or $a->[0] cmp $b->[0]
-} map {
+  } map {
     [ $_, length($_) ]
-} @unsorted;
+  } @unsorted;
 #5...........
         },
 
index 420358911ae7591873067f5058d0b0c14f43df00..beb1ef51e03ebb035e2fa1972e927bfb4a485599 100644 (file)
@@ -10,6 +10,8 @@
 #7 dwic.def
 #8 dwic.dwic
 #9 wtc.wtc7
+#10 rt144979.def
+#11 rt144979.rt144979
 
 # To locate test #13 you can search for its name or the string '#13'
 
@@ -27,15 +29,16 @@ BEGIN {
     # BEGIN SECTION 1: Parameter combinations #
     ###########################################
     $rparams = {
-        'def'  => "",
-        'dwic' => "-wn -dwic",
-        'wtc1' => "-wtc=0 -dtc",
-        'wtc2' => "-wtc=1 -atc",
-        'wtc3' => "-wtc=m -atc",
-        'wtc4' => "-wtc=m -atc -dtc",
-        'wtc5' => "-wtc=b -atc -dtc -vtc=2",
-        'wtc6' => "-wtc=i -atc -dtc -vtc=2",
-        'wtc7' => "-wtc=h -atc -dtc -vtc=2",
+        'def'      => "",
+        'dwic'     => "-wn -dwic",
+        'rt144979' => "-xci -ce -lp",
+        'wtc1'     => "-wtc=0 -dtc",
+        'wtc2'     => "-wtc=1 -atc",
+        'wtc3'     => "-wtc=m -atc",
+        'wtc4'     => "-wtc=m -atc -dtc",
+        'wtc5'     => "-wtc=b -atc -dtc -vtc=2",
+        'wtc6'     => "-wtc=i -atc -dtc -vtc=2",
+        'wtc7'     => "-wtc=h -atc -dtc -vtc=2",
     };
 
     ############################
@@ -52,6 +55,47 @@ BEGIN {
             PL_sys_intern
         ) ],
     );
+----------
+
+        'rt144979' => <<'----------',
+# part 1
+GetOptions(
+      "format|f=s" => sub {
+          my ( $n, $v ) = @_;
+          if ( ( my $k = $formats{$v} ) ) {
+              $format = $k;
+      } else {
+              die("--format must be 'system' or 'user'\n");
+          }
+          return;
+      },
+); 
+
+# part 2
+{{{
+            my $desc =
+              $access
+              ? "for -$op under use filetest 'access' $desc_tail"
+              : "for -$op $desc_tail";
+            {
+                local $SIG{__WARN__} = sub {
+                    my $w = shift;
+                    if ($w =~ /^File::stat ignores VMS ACLs/)
+                    {
+                        ++$vwarn;
+                      } elsif (
+                              $w =~ /^File::stat ignores use filetest 'access'/)
+                    {
+                        ++$awarn;
+                    } else
+                    {
+                        $warnings .= $w;
+                    }
+                };
+                $rv = eval "$access; -$op \$stat";
+            }
+}}}
+
 ----------
 
         'wtc' => <<'----------',
@@ -505,6 +549,102 @@ my $no_index_1_1 =
 
 #9...........
         },
+
+        'rt144979.def' => {
+            source => "rt144979",
+            params => "def",
+            expect => <<'#10...........',
+# part 1
+GetOptions(
+    "format|f=s" => sub {
+        my ( $n, $v ) = @_;
+        if ( ( my $k = $formats{$v} ) ) {
+            $format = $k;
+        }
+        else {
+            die("--format must be 'system' or 'user'\n");
+        }
+        return;
+    },
+);
+
+# part 2
+{
+    {
+        {
+            my $desc =
+              $access
+              ? "for -$op under use filetest 'access' $desc_tail"
+              : "for -$op $desc_tail";
+            {
+                local $SIG{__WARN__} = sub {
+                    my $w = shift;
+                    if ( $w =~ /^File::stat ignores VMS ACLs/ ) {
+                        ++$vwarn;
+                    }
+                    elsif ( $w =~ /^File::stat ignores use filetest 'access'/ )
+                    {
+                        ++$awarn;
+                    }
+                    else {
+                        $warnings .= $w;
+                    }
+                };
+                $rv = eval "$access; -$op \$stat";
+            }
+        }
+    }
+}
+
+#10...........
+        },
+
+        'rt144979.rt144979' => {
+            source => "rt144979",
+            params => "rt144979",
+            expect => <<'#11...........',
+# part 1
+GetOptions(
+      "format|f=s" => sub {
+          my ( $n, $v ) = @_;
+          if ( ( my $k = $formats{$v} ) ) {
+              $format = $k;
+          } else {
+              die("--format must be 'system' or 'user'\n");
+          }
+          return;
+      },
+);
+
+# part 2
+{
+    {
+        {
+            my $desc =
+              $access
+              ? "for -$op under use filetest 'access' $desc_tail"
+              : "for -$op $desc_tail";
+            {
+                local $SIG{__WARN__} = sub {
+                    my $w = shift;
+                    if ( $w =~ /^File::stat ignores VMS ACLs/ ) {
+                        ++$vwarn;
+                    } elsif (
+                             $w =~ /^File::stat ignores use filetest 'access'/ )
+                    {
+                        ++$awarn;
+                    } else {
+                        $warnings .= $w;
+                    }
+                };
+                $rv = eval "$access; -$op \$stat";
+            }
+        }
+    }
+}
+
+#11...........
+        },
     };
 
     my $ntests = 0 + keys %{$rtests};