From cfa815b7b698aa97cda7e0f5ae52fee2e2b31342 Mon Sep 17 00:00:00 2001 From: Steve Hancock Date: Thu, 15 Dec 2022 06:18:58 -0800 Subject: [PATCH] issue c166, avoid applying -sfp if it might cause problems --- bin/perltidy | 2 +- lib/Perl/Tidy/Formatter.pm | 51 +++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/bin/perltidy b/bin/perltidy index 71ef6c33..4060188d 100755 --- a/bin/perltidy +++ b/bin/perltidy @@ -1532,7 +1532,7 @@ B<-sfp> or B<--space-function-paren> You will probably also want to use the flag B<-skp> (previous item) too. -The reason this is not recommended is that spacing a function paren can make a +The parameter is not recommended because spacing a function paren can make a program vulnerable to parsing problems by Perl. For example, the following two-line program will run as written but will have a syntax error if reformatted with -sfp: diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm index 2e4abaed..8df1c1ef 100644 --- a/lib/Perl/Tidy/Formatter.pm +++ b/lib/Perl/Tidy/Formatter.pm @@ -262,6 +262,7 @@ my ( %is_die_confess_croak_warn, %is_my_our_local, %is_soft_keep_break_type, + %is_indirect_object_taker, @all_operators, @@ -752,6 +753,10 @@ BEGIN { @q = qw# -> ? : && || + - / * #; @is_soft_keep_break_type{@q} = (1) x scalar(@q); + # these functions allow an identifier in the indirect object slot + @q = qw( print printf sort exec system say); + @is_indirect_object_taker{@q} = (1) x scalar(@q); + } { ## begin closure to count instances @@ -3171,7 +3176,11 @@ sub set_whitespace_flags { ) ) { - $ws = $rOpts_space_function_paren ? WS_YES : WS_NO; + $ws = + $rOpts_space_function_paren + ? $self->ws_space_function_paren( $j, $rtokh_last_last ) + : WS_NO; + set_container_ws_by_keyword( $last_token, $seqno ); $ris_function_call_paren->{$seqno} = 1; } @@ -3405,6 +3414,46 @@ sub ws_in_container { } ## end sub ws_in_container +sub ws_space_function_paren { + + my ( $self, $j, $rtokh_last_last ) = @_; + + # Called if --space-function-paren is set to see if it might cause + # a problem. The manual warns the user about potential problems with + # this flag. Here we just try to catch one common problem. + + # Given: + # $j = index of '(' after function name + # Return: + # WS_NO if no space + # WS_YES otherwise + + # This was added to fix for issue c166. Ignore -sfp at a possible indirect + # object location. For example, do not convert this: + # print header() ... + # to this: + # print header () ... + # because in this latter form, header may be taken to be a file handle + # instead of a function call. + + # Start with the normal value for -sfp: + my $ws = WS_YES; + + # now check to be sure we don't cause a problem: + my $type_ll = $rtokh_last_last->[_TYPE_]; + my $tok_ll = $rtokh_last_last->[_TOKEN_]; + + # NOTE: this is just a minimal check. For example, we might also check + # for something like this: + # print ( header ( .. + if ( $type_ll eq 'k' && $is_indirect_object_taker{$tok_ll} ) { + $ws = WS_NO; + } + + return $ws; + +} ## end sub ws_space_function_paren + } ## end closure set_whitespace_flags sub dump_want_left_space { -- 2.39.5