From 6947fe98aac9b80ea200e2cab5de146b4fd17509 Mon Sep 17 00:00:00 2001 From: Steve Hancock Date: Tue, 25 May 2021 21:08:38 -0700 Subject: [PATCH] Fix several problems with -lp formatting --- lib/Perl/Tidy/Formatter.pm | 22 ++++---- lib/Perl/Tidy/VerticalAligner.pm | 49 +++++++++-------- local-docs/BugLog.pod | 93 ++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 30 deletions(-) diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm index d89afbf1..9108ba96 100644 --- a/lib/Perl/Tidy/Formatter.pm +++ b/lib/Perl/Tidy/Formatter.pm @@ -8194,10 +8194,8 @@ sub weld_nested_quotes { # Change the level of a closing qw token to be that of the outer # containing token. This will allow -lp indentation to function # correctly in the vertical aligner. - # Patch to fix c002: but not if it contains text and is not -lp. - if ( $rOpts_line_up_parentheses - || length( $rLL->[$Kinner_closing]->[_TOKEN_] ) == 1 ) - { + # Patch to fix c002: but not if it contains text + if ( length( $rLL->[$Kinner_closing]->[_TOKEN_] ) == 1 ) { $rLL->[$Kinner_closing]->[_LEVEL_] = $rLL->[$Kouter_closing]->[_LEVEL_]; } @@ -18912,7 +18910,6 @@ sub send_lines_to_vertical_aligner { $rvalign_hash->{list_seqno} = $list_seqno; $rvalign_hash->{outdent_long_lines} = $outdent_long_lines; $rvalign_hash->{is_terminal_ternary} = $is_terminal_ternary; - $rvalign_hash->{is_terminal_statement} = $is_semicolon_terminated; $rvalign_hash->{rvertical_tightness_flags} = $rvertical_tightness_flags; $rvalign_hash->{level_jump} = $level_jump; $rvalign_hash->{rfields} = $rfields; @@ -19364,8 +19361,18 @@ sub get_seqno { } # Loop over all lines of the batch ... + + # Workaround for problem c007, in which the combination -lp -xci + # can produce a "Program bug" message in unusual circumstances. + my $skip_SECTION_1 = $rOpts_line_up_parentheses + && $rOpts->{'extended-continuation-indentation'}; + foreach my $line ( 0 .. $max_line ) { + my $ibeg = $ri_first->[$line]; + my $iend = $ri_last->[$line]; + my $lev = $levels_to_go[$ibeg]; + #################################### # SECTION 1: Undo needless common CI #################################### @@ -19388,10 +19395,7 @@ sub get_seqno { # sort { $a <=> $b } # grep { $lookup->{$_} ne $default } keys %$lookup ); - my $ibeg = $ri_first->[$line]; - my $iend = $ri_last->[$line]; - my $lev = $levels_to_go[$ibeg]; - if ( $line > 0 ) { + if ( $line > 0 && !$skip_SECTION_1 ) { # if we have started a chain.. if ($line_1) { diff --git a/lib/Perl/Tidy/VerticalAligner.pm b/lib/Perl/Tidy/VerticalAligner.pm index 5090b39c..8eecfe8c 100644 --- a/lib/Perl/Tidy/VerticalAligner.pm +++ b/lib/Perl/Tidy/VerticalAligner.pm @@ -118,7 +118,6 @@ BEGIN { _zero_count_ => $i++, _last_leading_space_count_ => $i++, _comment_leading_space_count_ => $i++, - _extra_indent_ok_ => $i++, }; # Debug flag. This is a relic from the original program development @@ -191,7 +190,6 @@ sub new { $self->[_zero_count_] = 0; $self->[_comment_leading_space_count_] = 0; $self->[_last_leading_space_count_] = 0; - $self->[_extra_indent_ok_] = 0; # Memory of what has been processed $self->[_last_level_written_] = -1; @@ -400,7 +398,6 @@ sub valign_input { my $list_seqno = $rline_hash->{list_seqno}; my $outdent_long_lines = $rline_hash->{outdent_long_lines}; my $is_terminal_ternary = $rline_hash->{is_terminal_ternary}; - my $is_terminal_statement = $rline_hash->{is_terminal_statement}; my $rvertical_tightness_flags = $rline_hash->{rvertical_tightness_flags}; my $level_jump = $rline_hash->{level_jump}; my $rfields = $rline_hash->{rfields}; @@ -507,20 +504,7 @@ sub valign_input { # or if vertical alignment is turned off for debugging if ( $level != $group_level || $is_outdented || !$self->[_rOpts_valign_] ) { - # we are allowed to shift a group of lines to the right if its - # level is greater than the previous and next group - $self->[_extra_indent_ok_] = - ( $level < $group_level - && $self->[_last_level_written_] < $group_level ); - - $self->_flush_group_lines(); - - # If we know that this line will get flushed out by itself because - # of level changes, we can leave the extra_indent_ok flag set. - # That way, if we get an external flush call, we will still be - # able to do some -lp alignment if necessary. - $self->[_extra_indent_ok_] = - ( $is_terminal_statement && $level > $group_level ); + $self->_flush_group_lines( $level - $group_level ); $group_level = $level; $self->[_group_level_] = $group_level; @@ -729,7 +713,7 @@ EOM # Force break after jump to lower level if ( $level_jump < 0 ) { - $self->_flush_group_lines(); + $self->_flush_group_lines($level_jump); } # -------------------------------------------------------------------- @@ -1396,7 +1380,10 @@ sub _flush_group_lines { # This is the vertical aligner internal flush, which leaves the cache # intact - my ($self) = @_; + my ( $self, $level_jump ) = @_; + + # $level_jump = $next_level-$group_level, if known + # = undef if not known my $rgroup_lines = $self->[_rgroup_lines_]; return unless ( @{$rgroup_lines} ); @@ -1445,8 +1432,29 @@ sub _flush_group_lines { # STEP 5: For the -lp option, increase the indentation of lists # to the desired amount, but do not exceed the line length limit. + + # We are allowed to shift a group of lines to the right if: + # (1) its level is greater than the level of the previous group, and + # (2) its level is greater than the level of the next line to be written. + + my $extra_indent_ok; + if ( $group_level > $self->[_last_level_written_] ) { + + # Use the level jump to next line to come, if given + if ( defined($level_jump) ) { + $extra_indent_ok = $level_jump < 0; + } + + # Otherwise, assume the next line has the level of the end of last line. + # This fixes case c008. + else { + my $level_end = $rgroup_lines->[-1]->get_level_end(); + $extra_indent_ok = $group_level > $level_end; + } + } + my $extra_leading_spaces = - $self->[_extra_indent_ok_] + $extra_indent_ok ? get_extra_leading_spaces( $rgroup_lines, $rgroups ) : 0; @@ -5098,7 +5106,6 @@ sub get_output_line_number { $self->[_last_level_written_] = $level; $self->[_last_side_comment_length_] = $side_comment_length; - $self->[_extra_indent_ok_] = 0; return; } } diff --git a/local-docs/BugLog.pod b/local-docs/BugLog.pod index 1c2946b0..5ca2f9f7 100644 --- a/local-docs/BugLog.pod +++ b/local-docs/BugLog.pod @@ -2,6 +2,99 @@ =over 4 +=item B + +This update fixes several problems with -lp formatting which are all somewhat +related. + +ISSUE #1 (case c002): A problem involving -lp -wn and certain qw lists + +The last line of a welded qw list was being outdented even if it contained text +as well as the closing container token. This update fixes the problem and +simplifies the logic. + +A few examples (all use 'perltidy -wn -lp'): + + # OLD and NEW: OK, closing qw paren is on separate line + $roads->add_capacity_path( qw( CoolCity 10 ChocolateGulch 8 + PecanPeak 10 BlueberryWoods 6 + HotCity + ) ); + + # OLD: poor; outdented text not aligned with previous text + $roads->add_capacity_path( qw( CoolCity 10 ChocolateGulch 8 + PecanPeak 10 BlueberryWoods 6 + HotCity ) ); + + # NEW: + $roads->add_capacity_path( qw( CoolCity 10 ChocolateGulch 8 + PecanPeak 10 BlueberryWoods 6 + HotCity ) ); + + # OLD: + $roads->add_capacity_path( qw( ChocolateGulch 3 StrawberryFields 0 + StrawberryFields ) ); + + # NEW: + $roads->add_capacity_path( qw( ChocolateGulch 3 StrawberryFields 0 + StrawberryFields ) ); + + # OLD: + my $mon_name = ( qw(January February March April + May June July August + September October November December) )[$mon]; + + # NEW + my $mon_name = ( qw(January February March April + May June July August + September October November December) )[$mon]; + +ISSUE #2 (case c007): A rare program error could be triggered with -lp -xci + +In some very rare circumstances it was possible to trigger a "Program error" +message. The program still ran to completion. The conditions for this to occur +were that flags -lp -xci were set, and that there was a container of sort/map/grep +blocks, and there was a side comment on the closing paren. For example: + + # OLD: perltidy -lp -xci, gave an error message and extra indentation here + my %specified_opts = ( + ( + map { /^no-?(.*)$/i ? ($1 => 0) : ($_ => 1) } + map { /^--([\-_\w]+)$/ } @ARGV + ), # this comment caused an error with flags -lp -xci + ); + + # NEW: perltidy -lp -xci, no error + my %specified_opts = ( + ( + map { /^no-?(.*)$/i ? ( $1 => 0 ) : ( $_ => 1 ) } + map { /^--([\-_\w]+)$/ } @ARGV + ), # this comment caused an error with flags -lp -xci + ); + + +ISSUE #3 (case c008): In some unusual cases the -lp formatting style was not +being applied when it should have been. For example (text is shifted right): + + # NEW: perltidy -lp + $result = runperl( + switches => [ '-I.', "-w" ], + stderr => 1, + prog => <<'PROG' ); + SIG + PROG + + # NEW: perltidy -lp + $result = runperl( + switches => [ '-I.', "-w" ], + stderr => 1, + prog => <<'PROG' ); + SIG + PROG + + +25 May 2021. + =item B This is an update to the patch 19 Apr 2021, eeeaf09. It restricts that patch -- 2.39.5