From e9cf334a4b98ecfceec93b27985d0c8320467feb Mon Sep 17 00:00:00 2001 From: Steve Hancock Date: Wed, 18 Mar 2020 07:10:52 -0700 Subject: [PATCH] fix git#22, keep sub signature on a single line --- CHANGES.md | 4 ++ dev-bin/build.pl | 4 +- lib/Perl/Tidy/Formatter.pm | 86 +++++++++++++++++++++++++++++++++ t/snippets/expect/signature.def | 21 ++++++++ t/snippets/packing_list.txt | 5 +- t/snippets/signature.in | 21 ++++++++ t/snippets17.t | 53 ++++++++++++++++++++ 7 files changed, 190 insertions(+), 4 deletions(-) create mode 100644 t/snippets/expect/signature.def create mode 100644 t/snippets/signature.in diff --git a/CHANGES.md b/CHANGES.md index cfe41afd..edab3077 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,10 @@ ## 2020 01 10.01 + - Fix for git#22, Preserve function signature on a single line. An + unwanted line break was being introduced when a closing signature paren + followed a closing do brace. + - Fix RT#132059, the -dac parameter was not working and caused an error exit - When -utf8 is used, any error output is encoded as utf8 diff --git a/dev-bin/build.pl b/dev-bin/build.pl index 483ca8d0..4d31bfd6 100755 --- a/dev-bin/build.pl +++ b/dev-bin/build.pl @@ -49,7 +49,7 @@ my $rstatus = {}; foreach my $step ( @{$rsteps} ) { $rstatus->{$step} = 'TBD' } my $rcode = { - 'A' => \&autopilot, + ## 'A' => \&autopilot, # can be confusing, deactivated 'CHK' => sub { openurl("local-docs/Release-Checklist.md") unless $rstatus->{CHK} eq 'OK'; @@ -73,12 +73,12 @@ $fh_log->close(); sub main { while (1) { +##A - run All Steps... print <{'CHK'} v - check/update Version Number status: $rstatus->{'V'} tidy - run tidyall (tidy & critic) status: $rstatus->{'TIDY'} diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm index 38e94a04..c5dadcef 100644 --- a/lib/Perl/Tidy/Formatter.pm +++ b/lib/Perl/Tidy/Formatter.pm @@ -3843,6 +3843,8 @@ sub weld_containers { $self->weld_cuddled_blocks(); + $self->weld_signature_parens(); + return; } @@ -3858,6 +3860,90 @@ sub cumulative_length_after_K { return $rLL->[$KK]->[_CUMULATIVE_LENGTH_]; } +sub weld_signature_parens { + my $self = shift; + + # This routine fixes a problem in which an unwanted line break can + # be inserted between a closing block brace and a closing sub signature + # paren. This is a fix for issue git#22. + + # For example, in the following snippet: + # sub foo ( $self, $$opts = do { ... } ) { $something=1 } + # we do not want a break after the closing do brace + + # Method: Look through the file for closing sub signature parens which + # follow closing braces, and weld any such parens to those braces so that + # they do not get separated. + + # We want to do the following steps: + # 1. look for an opening sub brace, + # 2. look back one nonblank character for a closing paren [the signature] + # 3. if we find one, look back one more character for any closing brace, + # 4. and if we find one, then 'weld' that closing brace to that closing + # paren. + + # Note that some good test cases are in 'signatures.t' in a perl + # distribution + + # TODO: Improve efficiency by creating a list of K values of opening sub + # braces in advance, and just loop through them rather than all containers. + + my $rLL = $self->{rLL}; + return unless ( defined($rLL) && @{$rLL} ); + + # Loop over all container items in the file + my $KNEXT = 0; + my $KK = 0; + my $token = ""; + my $type_sequence = ""; + while ( defined($KNEXT) ) { + my $KLAST = $KK; + my $token_last = $token; + my $type_sequence_last = $type_sequence; + + $KK = $KNEXT; + $KNEXT = $rLL->[$KNEXT]->[_KNEXT_SEQ_ITEM_]; + my $rtoken_vars = $rLL->[$KK]; + $type_sequence = $rtoken_vars->[_TYPE_SEQUENCE_]; + $token = $rtoken_vars->[_TOKEN_]; + my $block_type = $rtoken_vars->[_BLOCK_TYPE_]; + + # 1. look for an opening sub brace... + # 2. following a closing paren (with possible blank between)... + if ( + $is_opening_token{$token} + && $KLAST + && $KK - $KLAST <= 2 + && $token_last eq ')' + && ( $block_type =~ /$SUB_PATTERN/ + || $block_type =~ /$ASUB_PATTERN/ ) + ) + { + + # any intervening char must be a blank + if ( $KK - $KLAST == 2 ) { + if ( $rLL->[ $KK - 1 ]->[_TYPE_] ne 'b' ) { + next; + } + } + + # 3. following a closing block brace of any kind... + my $Kp = $self->K_previous_nonblank($KLAST); + if ($Kp) { + my $block_type_p = $rLL->[$Kp]->[_BLOCK_TYPE_]; + if ($block_type_p) { + + # 4. Found it; set the weld flag for this brace. + # It will be checked in sub output_line_to_go + my $type_sequence_p = $rLL->[$Kp]->[_TYPE_SEQUENCE_]; + $weld_len_right_closing{$type_sequence_p} = 1; + } + } + } + } + return; +} + sub weld_cuddled_blocks { my $self = shift; diff --git a/t/snippets/expect/signature.def b/t/snippets/expect/signature.def new file mode 100644 index 00000000..de0dc882 --- /dev/null +++ b/t/snippets/expect/signature.def @@ -0,0 +1,21 @@ +# git22: Preserve function signature on a single line +# This behavior is controlled by 'sub weld_signature_parens' + +sub foo ( $x, $y = "abcd" ) { + $x . $y; +} + +# do not break after closing do brace +sub foo ( $x, $y = do { {} }, $z = 42, $w = do { "abcd" } ) { + $x . $y . $z; +} + +# This signature should get put back on one line +sub t022 ( $p = do { $z += 10; 222 }, $a = do { $z++; 333 } ) { + "$p/$a"; +} + +# anonymous sub with signature +my $subref = sub ( $cat, $id = do { state $auto_id = 0; $auto_id++ } ) { + ...; +}; diff --git a/t/snippets/packing_list.txt b/t/snippets/packing_list.txt index 4ac53628..47ac806e 100644 --- a/t/snippets/packing_list.txt +++ b/t/snippets/packing_list.txt @@ -155,6 +155,9 @@ ../snippets16.t rt130394.rt130394 ../snippets16.t git18.def ../snippets16.t here2.def +../snippets17.t rt132059.def +../snippets17.t rt132059.rt132059 +../snippets17.t signature.def ../snippets2.t angle.def ../snippets2.t arrows1.def ../snippets2.t arrows2.def @@ -315,5 +318,3 @@ ../snippets9.t rt98902.def ../snippets9.t rt98902.rt98902 ../snippets9.t rt99961.def -../snippets17.t rt132059.def -../snippets17.t rt132059.rt132059 diff --git a/t/snippets/signature.in b/t/snippets/signature.in new file mode 100644 index 00000000..def25b50 --- /dev/null +++ b/t/snippets/signature.in @@ -0,0 +1,21 @@ +# git22: Preserve function signature on a single line +# This behavior is controlled by 'sub weld_signature_parens' + +sub foo($x, $y="abcd") { + $x.$y; +} + +# do not break after closing do brace +sub foo($x, $y=do{{}}, $z=42, $w=do{"abcd"}) { + $x.$y.$z; +} + +# This signature should get put back on one line +sub t022 ( + $p = do { $z += 10; 222 }, $a = do { $z++; 333 } +) { "$p/$a" } + +# anonymous sub with signature +my $subref = sub ( $cat, $id = do { state $auto_id = 0; $auto_id++ } ) { + ...; +}; diff --git a/t/snippets17.t b/t/snippets17.t index 0a6c1ec6..61a73748 100644 --- a/t/snippets17.t +++ b/t/snippets17.t @@ -3,6 +3,7 @@ # Contents: #1 rt132059.def #2 rt132059.rt132059 +#3 signature.def # To locate test #13 you can search for its name or the string '#13' @@ -43,6 +44,30 @@ bonjour! =cut $i++; +---------- + + 'signature' => <<'----------', +# git22: Preserve function signature on a single line +# This behavior is controlled by 'sub weld_signature_parens' + +sub foo($x, $y="abcd") { + $x.$y; +} + +# do not break after closing do brace +sub foo($x, $y=do{{}}, $z=42, $w=do{"abcd"}) { + $x.$y.$z; +} + +# This signature should get put back on one line +sub t022 ( + $p = do { $z += 10; 222 }, $a = do { $z++; 333 } +) { "$p/$a" } + +# anonymous sub with signature +my $subref = sub ( $cat, $id = do { state $auto_id = 0; $auto_id++ } ) { + ...; +}; ---------- }; @@ -86,6 +111,34 @@ sub f { $i++; #2........... }, + + 'signature.def' => { + source => "signature", + params => "def", + expect => <<'#3...........', +# git22: Preserve function signature on a single line +# This behavior is controlled by 'sub weld_signature_parens' + +sub foo ( $x, $y = "abcd" ) { + $x . $y; +} + +# do not break after closing do brace +sub foo ( $x, $y = do { {} }, $z = 42, $w = do { "abcd" } ) { + $x . $y . $z; +} + +# This signature should get put back on one line +sub t022 ( $p = do { $z += 10; 222 }, $a = do { $z++; 333 } ) { + "$p/$a"; +} + +# anonymous sub with signature +my $subref = sub ( $cat, $id = do { state $auto_id = 0; $auto_id++ } ) { + ...; +}; +#3........... + }, }; my $ntests = 0 + keys %{$rtests}; -- 2.39.5