From a69d4fa8135000315c785737bc02692652ab9c1a Mon Sep 17 00:00:00 2001 From: Steve Hancock Date: Sat, 16 Mar 2024 11:53:58 -0700 Subject: [PATCH] improve formatting of git #134 --- lib/Perl/Tidy/Formatter.pm | 113 +++++++++++++++++++++++++++++++++++ t/snippets/expect/git134.def | 15 +++++ t/snippets/git134.in | 15 +++++ t/snippets/packing_list.txt | 1 + t/snippets29.t | 41 +++++++++++++ 5 files changed, 185 insertions(+) create mode 100644 t/snippets/expect/git134.def create mode 100644 t/snippets/git134.in diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm index ebe3921f..b36b0fbd 100644 --- a/lib/Perl/Tidy/Formatter.pm +++ b/lib/Perl/Tidy/Formatter.pm @@ -31974,6 +31974,17 @@ sub get_seqno { ? $is_chain_operator{$tok_next} # and, or : $is_chain_operator{$type_next}; # + - * / : ? && || + # Fix for git134 + if ( !$has_leading_op_next + && $iend > $ibeg + 2 + && $types_to_go[ $ibeg + 1 ] eq 'b' + && $is_opening_type{ $types_to_go[$ibeg] } + && $nesting_depth_to_go[$iend] > $nesting_depth_to_go[$ibeg] ) + { + my $iend_next = $ri_last->[ $line + 1 ]; + $self->pad_broken_list( $ibeg, $iend, $ibeg_next, $iend_next ); + } + next unless ($has_leading_op_next); # next line must not be at lesser depth @@ -32382,6 +32393,108 @@ sub get_seqno { } ## end sub set_logical_padding } ## end closure set_logical_padding +sub pad_broken_list { + my ( $self, $ibeg, $iend, $ibeg_next, $iend_next ) = @_; + + # Given: + # $ibeg, $iend = index range of line to get padding + # $ibeg_next, $iend_next = index range of next line + + # This fixes a minor issue discussed in git134. In the example shown + # below, the is a broken list because of the q term, so line breaks + # are copied from the input. We want to insert padding at + # '[ $clientKey,' to align with the next line. + + # $q->do( + # q{ + # Something + # }, + # [ $clientKey, ## <-- pad spaces needed here + # $systemKey, + # ], + # ); + + # Notation for the line being padded: + # + # [ $clientKey, + # | | | + # | | ------- $iend + # | ------ $ibeg+2 + # ---- $ibeg + + # NOTES: + # - This particular list is broken because of the 'q' term in the list + # - It is extremely rare for this routine to be called for typical code + # (I found just two examples in my large collection of test scripts) + # - This routine is not called for the last line of a batch. This + # is not necessary because perltidy will generally put a break + # after the opening token in that case. + + # The basic logic is to pad the first blank space $ibeg+1 using the + # leading spaces that would have been given to token at $ibeg+2 if: + # - this line begins with an opening token which is + # - followed by additional tokens on the same line, + # - and is a list container, and + # - the line terminates in a comma whose parent is this container, + # - then pad using the indentation of the second token + + # So in other words, we are simulating doing a line break after the + # first token and then recombining with a -vt operation. That cannot + # actually happen for a broken list. + + # Next token must be blank for padding, and must be followed + # by at least one token and comma + return if ( $iend < $ibeg + 3 || $types_to_go[ $ibeg + 1 ] ne 'b' ); + + # This is only for lists + my $seqno = $type_sequence_to_go[$ibeg]; + return if ( !$seqno ); + my $is_list = $self->[_ris_list_by_seqno_]->{$seqno}; + return if ( !$is_list ); + + # First token on next line must be in same container + my $seqno_beg_next = $parent_seqno_to_go[$ibeg_next]; + return if ( !$seqno_beg_next || $seqno_beg_next != $seqno ); + + # This does not work well if the closing token is on the next line + return + if ( !defined( $mate_index_to_go[$ibeg] ) + || $mate_index_to_go[$ibeg] <= $iend_next ); + + # Line must end in a comma, with possible side comment + my $i_terminal = $iend; + if ( $types_to_go[$i_terminal] eq '#' ) { + $i_terminal -= 1; + if ( $types_to_go[$i_terminal] eq 'b' ) { + $i_terminal -= 1; + } + } + return if ( $i_terminal < $ibeg + 2 ); + return if ( $types_to_go[$i_terminal] ne ',' ); + + # add padding to make the second token have the same location + # as if it had been output separately and later joined with -vt + my $lsp = $leading_spaces_to_go[$ibeg]; + my $lsp_next = $leading_spaces_to_go[$ibeg_next]; + + # this is not for -lp style + return if ( ref($lsp) || ref($lsp_next) ); + + my $pad_spaces = + $lsp_next - + ( $lsp + $token_lengths_to_go[$ibeg] + + $token_lengths_to_go[ $ibeg + 1 ] ); + + return if ( $pad_spaces <= 0 ); + + # Do not pad if it will cause excess line length + my $excess = $self->excess_line_length( $ibeg, $iend ); + return if ( $excess + $pad_spaces > 0 ); + + $self->pad_token( $ibeg + 1, $pad_spaces ); + return; +} ## end sub pad_broken_list + sub pad_token { # insert $pad_spaces before token number $ipad diff --git a/t/snippets/expect/git134.def b/t/snippets/expect/git134.def new file mode 100644 index 00000000..6d62a119 --- /dev/null +++ b/t/snippets/expect/git134.def @@ -0,0 +1,15 @@ +# test padding at '[ $clientKey,' by sub pad_broken_list, see git #134 +sub foo { + my ( $self, $clientKey, $systemKey ) = @_; + + $q->do( + q{ + Something + }, + [ $clientKey, + $systemKey, + ], + ); + + return; +} diff --git a/t/snippets/git134.in b/t/snippets/git134.in new file mode 100644 index 00000000..6d62a119 --- /dev/null +++ b/t/snippets/git134.in @@ -0,0 +1,15 @@ +# test padding at '[ $clientKey,' by sub pad_broken_list, see git #134 +sub foo { + my ( $self, $clientKey, $systemKey ) = @_; + + $q->do( + q{ + Something + }, + [ $clientKey, + $systemKey, + ], + ); + + return; +} diff --git a/t/snippets/packing_list.txt b/t/snippets/packing_list.txt index 0d43932a..9ecf245a 100644 --- a/t/snippets/packing_list.txt +++ b/t/snippets/packing_list.txt @@ -551,3 +551,4 @@ ../snippets9.t rt98902.def ../snippets9.t rt98902.rt98902 ../snippets9.t rt99961.def +../snippets29.t git134.def diff --git a/t/snippets29.t b/t/snippets29.t index cfe5767b..930bf8d1 100644 --- a/t/snippets29.t +++ b/t/snippets29.t @@ -9,6 +9,7 @@ #6 dia.dia1 #7 dia.dia2 #8 dia.dia3 +#9 git134.def # To locate test #13 you can search for its name or the string '#13' @@ -71,6 +72,24 @@ my $val2 = $${$x}->[1]; 'git125' => <<'----------', sub Add ( $x, $y ); sub Sub( $x, $y ); +---------- + + 'git134' => <<'----------', +# test padding at '[ $clientKey,' by sub pad_broken_list, see git #134 +sub foo { + my ( $self, $clientKey, $systemKey ) = @_; + + $q->do( + q{ + Something + }, + [ $clientKey, + $systemKey, + ], + ); + + return; +} ---------- 'vsn' => <<'----------', @@ -247,6 +266,28 @@ my $val1 = ${$x}[1]; my $val2 = $${$x}->[1]; #8........... }, + + 'git134.def' => { + source => "git134", + params => "def", + expect => <<'#9...........', +# test padding at '[ $clientKey,' by sub pad_broken_list, see git #134 +sub foo { + my ( $self, $clientKey, $systemKey ) = @_; + + $q->do( + q{ + Something + }, + [ $clientKey, + $systemKey, + ], + ); + + return; +} +#9........... + }, }; my $ntests = 0 + keys %{$rtests}; -- 2.39.5