From ca53d0a3176a402fa30bac6691652b8b5d2cad50 Mon Sep 17 00:00:00 2001 From: Steve Hancock Date: Fri, 18 Sep 2020 18:04:10 -0700 Subject: [PATCH] Simplified coding of -ibhb and related parameters --- CHANGES.md | 3 +- bin/perltidy | 29 ++++---- docs/BugLog.html | 16 +++++ docs/ChangeLog.html | 3 +- docs/perltidy.html | 19 ++--- lib/Perl/Tidy/Formatter.pm | 133 +++++++++++++++++++++-------------- t/snippets/expect/bbhb.bbhb2 | 5 +- t/snippets/packing_list.txt | 4 +- t/snippets22.t | 5 +- 9 files changed, 137 insertions(+), 80 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5ca9d946..88ee52ef 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,7 +7,8 @@ - Added parameters -bbhb=n (--break-before-hash-brace=n), -bbsb=n (--break-before-square-bracket=n), and -bbp=n (--break-before-paren=n) suggested in git #38. These provide control over the - opening container token of a multiple-line list. + opening container token of a multiple-line list. Related new parameters -ihb=n, -isb=n, -ip=n + control indentation of these tokens. - Numerous issues have been found during automated testing and fixed. Many involve references to uninitialized variables when perltidy is given random text. A complete list is given in diff --git a/bin/perltidy b/bin/perltidy index a0e34d29..8ce05e3a 100755 --- a/bin/perltidy +++ b/bin/perltidy @@ -2143,7 +2143,7 @@ before the opening brace according to the value given to the integer B: -bbhb=0 never break [default] -bbhb=1 stable: break if the input script had a break - -bbhb=2 break if list is 'complex', meaning it contains other broken lists + -bbhb=2 break if list is 'complex' (see note below) -bbhb=3 always break For example, @@ -2157,20 +2157,25 @@ For example, four => 'IV', }; -There are a couple of points to note about this flag: +There are several points to note about this flag: =over 4 =item * +This parameter only applies to opening hash braces which are preceded by an '=' +or '=>'. + +=item * + This parameter only applies if the contents of the container looks like a list. The contents need to contain some commas or '=>'s at the next interior level to be considered a list. =item * -This parameter only applies if there is a blank space before the opening brace -in the default formatting. +For the B option, a list is considered 'complex' if it is part of a nested list +structure which spans multiple lines in the input file. =item * @@ -2191,8 +2196,8 @@ Similar flags for controlling parens and square brackets are given in the subseq =item B<-ihb=n>, B<--indent-hash-brace=n> -This flag is a companion to B<-bbhb> for controlling the indentation of an opening hash brace. -The indentation is as follows: +This flag is a companion to B<-bbhb=n> for controlling the indentation of an opening hash brace +which is placed on a new line by that parameter. The indentation is as follows: -ihb=0 one continuation level [default] -ihb=1 outdent by one continuation level @@ -2224,13 +2229,13 @@ This flag is similar to the flag described above, except it applies to square br -bbsb=0 never break [default] -bbsb=1 stable: break if the input script had a break - -bbsb=2 break if list is 'complex', meaning it contains other broken lists + -bbsb=2 break if list is 'complex' (part of nested list structure) -bbsb=3 always break =item B<-isb=n>, B<--indent-square-bracket=n> -This flag is a companion to B<-bbsb> for controlling the indentation of an opening square bracket. -The indentation is as follows: +This flag is a companion to B<-bbsb=n> for controlling the indentation of an opening square bracket +which is placed on a new line by that parameter. The indentation is as follows: -isb=0 one continuation level [default] -isb=1 outdent by one continuation level @@ -2242,13 +2247,13 @@ This flag is similar to B<-bbhb=n>, described above, except it applies to parens -bbp=0 never break [default] -bbp=1 stable: break if the input script had a break - -bbp=2 break if list is 'complex', meaning it contains other broken lists + -bpb=2 break if list is 'complex' (part of nested list structure) -bbp=3 always break =item B<-ip=n>, B<--indent-paren=n> -This flag is a companion to B<-bbp> for controlling the indentation of an opening paren. -The indentation is as follows: +This flag is a companion to B<-bbp=n> for controlling the indentation of an opening paren +which is placed on a new line by that parameter. The indentation is as follows: -ip=0 one continuation level [default] -ip=1 outdent by one continuation level diff --git a/docs/BugLog.html b/docs/BugLog.html index 56a91fd6..c3652f3b 100644 --- a/docs/BugLog.html +++ b/docs/BugLog.html @@ -21,6 +21,22 @@
+
fix incorrect parsing of certain deprecated empty here-docs
+
+ +

The following snippet was being incorrecly parsed:

+ +
 print <<
+ # Hello World 13!
+ 
+   ;
+ print "DONE\n";
+ +

This is a deprecated here-doc without a specified target but currently still a valid program. It would have been correctly parsed if the semicolon followed the '<<' operator rather than the here-doc.

+ +

This was found in random testing and fixed 16 Sep 2020. A warning message about deprecated here-doc targets was added.

+ +
make the arrow a vertical alignment token, git #39
diff --git a/docs/ChangeLog.html b/docs/ChangeLog.html index d6d37d33..04ab4789 100644 --- a/docs/ChangeLog.html +++ b/docs/ChangeLog.html @@ -7,7 +7,8 @@ - Added parameters -bbhb=n (--break-before-hash-brace=n), -bbsb=n (--break-before-square-bracket=n), and -bbp=n (--break-before-paren=n) suggested in git #38. These provide control over the - opening container token of a multiple-line list. + opening container token of a multiple-line list. Related new parameters -ihb=n, -isb=n, -ip=n + control indentation of these tokens. - Numerous issues have been found during automated testing and fixed. Many involve references to uninitialized variables when perltidy is given random text. A complete list is given in diff --git a/docs/perltidy.html b/docs/perltidy.html index 806eba17..63e00369 100644 --- a/docs/perltidy.html +++ b/docs/perltidy.html @@ -1692,7 +1692,7 @@
  -bbhb=0 never break [default]
   -bbhb=1 stable: break if the input script had a break
-  -bbhb=2 break if list is 'complex', meaning it contains other broken lists
+  -bbhb=2 break if list is 'complex' (see note below)
   -bbhb=3 always break

For example,

@@ -1706,14 +1706,17 @@ four => 'IV', }; -

There are a couple of points to note about this flag:

+

There are several points to note about this flag:

    +
  • This parameter only applies to opening hash braces which are preceded by an '=' or '=>'.

    + +
  • This parameter only applies if the contents of the container looks like a list. The contents need to contain some commas or '=>'s at the next interior level to be considered a list.

  • -
  • This parameter only applies if there is a blank space before the opening brace in the default formatting.

    +
  • For the n=2 option, a list is considered 'complex' if it is part of a nested list structure which spans multiple lines in the input file.

  • If multiple opening tokens have been 'welded' together with the -wn parameter, then this parameter has no effect.

    @@ -1731,7 +1734,7 @@
    -ihb=n, --indent-hash-brace=n
    -

    This flag is a companion to -bbhb for controlling the indentation of an opening hash brace. The indentation is as follows:

    +

    This flag is a companion to -bbhb=n for controlling the indentation of an opening hash brace which is placed on a new line by that parameter. The indentation is as follows:

      -ihb=0 one continuation level [default]
       -ihb=1 outdent by one continuation level
    @@ -1765,14 +1768,14 @@
     
     
      -bbsb=0 never break [default]
       -bbsb=1 stable: break if the input script had a break
    -  -bbsb=2 break if list is 'complex', meaning it contains other broken lists
    +  -bbsb=2 break if list is 'complex' (part of nested list structure)
       -bbsb=3 always break
    -isb=n, --indent-square-bracket=n
    -

    This flag is a companion to -bbsb for controlling the indentation of an opening square bracket. The indentation is as follows:

    +

    This flag is a companion to -bbsb=n for controlling the indentation of an opening square bracket which is placed on a new line by that parameter. The indentation is as follows:

      -isb=0 one continuation level [default]
       -isb=1 outdent by one continuation level
    @@ -1786,14 +1789,14 @@
     
     
      -bbp=0 never break [default]
       -bbp=1 stable: break if the input script had a break
    -  -bbp=2 break if list is 'complex', meaning it contains other broken lists
    +  -bpb=2 break if list is 'complex' (part of nested list structure)
       -bbp=3 always break
    -ip=n, --indent-paren=n
    -

    This flag is a companion to -bbp for controlling the indentation of an opening paren. The indentation is as follows:

    +

    This flag is a companion to -bbp=n for controlling the indentation of an opening paren which is placed on a new line by that parameter. The indentation is as follows:

      -ip=0 one continuation level [default]
       -ip=1 outdent by one continuation level
    diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm
    index 12f3ad14..f7789610 100644
    --- a/lib/Perl/Tidy/Formatter.pm
    +++ b/lib/Perl/Tidy/Formatter.pm
    @@ -73,6 +73,7 @@ my (
         %is_closing_type,
         %is_opening_token,
         %is_closing_token,
    +    %is_equal_or_fat_comma,
     
         # Initialized in check_options. These are constants and could
         # just as well be initialized in a BEGIN block.
    @@ -106,7 +107,7 @@ my (
         %want_break_before,
     
         %break_before_container_types,
    -    %container_indentation_options, 
    +    %container_indentation_options,
     
         %space_after_keyword,
     
    @@ -402,6 +403,9 @@ BEGIN {
         @q = qw< } ) ] >;
         @is_closing_token{@q} = (1) x scalar(@q);
     
    +    @q = qw( = => );
    +    @is_equal_or_fat_comma{@q} = (1) x scalar(@q);
    +
     }
     
     {    ## begin closure to count instanes
    @@ -4592,7 +4596,7 @@ sub adjust_indentation_levels {
         # Adjust indentation for list containers
         $self->adjust_container_indentation();
     
    -    # Set adjusted levels for the whitespace cycle option.  
    +    # Set adjusted levels for the whitespace cycle option.
         $self->whitespace_cycle_adjustment();
     
         # Adjust continuation indentation if -bli is set
    @@ -4798,26 +4802,45 @@ sub adjust_container_indentation {
         }
     
         # Loop over all opening container tokens
    -    my $K_opening_container = $self->[_K_opening_container_];
    +    my $K_opening_container  = $self->[_K_opening_container_];
    +    my $ris_broken_container = $self->[_ris_broken_container_];
         foreach my $seqno ( keys %{$K_opening_container} ) {
    -        my $KK          = $K_opening_container->{$seqno};
    -        my $rtoken_vars = $rLL->[$KK];
    -        my $block_type  = $rtoken_vars->[_BLOCK_TYPE_];
    +        my $KK = $K_opening_container->{$seqno};
     
             # this routine is not for code block braces
    +        my $block_type = $rLL->[$KK]->[_BLOCK_TYPE_];
             next if ($block_type);
     
    -        my $token = $rtoken_vars->[_TOKEN_];
    -        my $flag  = $container_indentation_options{$token};
    +        # These flags only apply if the corresponding -bb* flags
    +        # have been set to non-default values
    +        my $rtoken_vars = $rLL->[$KK];
    +        my $token       = $rtoken_vars->[_TOKEN_];
    +        my $flag        = $container_indentation_options{$token};
             next unless ($flag);
     
    +        # Require previous nonblank to be certain types (= and =>)
    +        # Note similar coding in sub insert_breaks_before...
    +        my $Kprev = $KK - 1;
    +        next if ( $Kprev < 0 );
    +        my $prev_type = $rLL->[$Kprev]->[_TYPE_];
    +        if ( $prev_type eq 'b' ) {
    +            $Kprev--;
    +            next if ( $Kprev < 0 );
    +            $prev_type = $rLL->[$Kprev]->[_TYPE_];
    +        }
    +        next unless ( $is_equal_or_fat_comma{$prev_type} );
    +
             # This is only for list containers
             next unless $self->is_list($seqno);
     
    +        # and only for broken lists
    +        next unless $ris_broken_container->{$seqno};
    +
             # NOTE: We are adjusting indentation of the opening container. The
             # closing container will normally follow the indentation of the opening
             # container automatically, so this is not currently done.
             my $ci = $rLL->[$KK]->[_CI_LEVEL_];
    +        next unless ($ci);
     
             # option 1: outdent
             if ( $flag == 1 ) {
    @@ -6263,24 +6286,23 @@ EOM
         %container_indentation_options = ();
         for ( $rOpts->{'indent-hash-brace'} ) {
             my $tok = '{';
    -        if ( defined($_) && $_>0 && $break_before_container_types{$tok} ) {
    -            $container_indentation_options{$tok} = $_; 
    +        if ( defined($_) && $_ > 0 && $break_before_container_types{$tok} ) {
    +            $container_indentation_options{$tok} = $_;
             }
         }
         for ( $rOpts->{'indent-square-bracket'} ) {
             my $tok = '[';
    -        if ( defined($_) && $_>0 && $break_before_container_types{$tok} ) {
    -            $container_indentation_options{$tok} = $_; 
    +        if ( defined($_) && $_ > 0 && $break_before_container_types{$tok} ) {
    +            $container_indentation_options{$tok} = $_;
             }
         }
         for ( $rOpts->{'indent-paren'} ) {
             my $tok = '(';
    -        if ( defined($_) && $_>0 && $break_before_container_types{$tok} ) {
    -            $container_indentation_options{$tok} = $_; 
    +        if ( defined($_) && $_ > 0 && $break_before_container_types{$tok} ) {
    +            $container_indentation_options{$tok} = $_;
             }
         }
     
    -
         # Define here tokens which may follow the closing brace of a do statement
         # on the same line, as in:
         #   } while ( $something);
    @@ -17931,16 +17953,28 @@ sub break_equals {
     
     sub is_list {
     
    -    # Try to decide if the immediate contents of a container is a list.
    +    # Return true if the immediate contents of a container appears to be a
    +    # list.
     
         my ( $self, $seqno ) = @_;
    -    my $rLL                  = $self->[_rLL_];
    -    my $rtype_count_by_seqno = $self->[_rtype_count_by_seqno_];
    +    return unless defined($seqno);
    +
    +    my $K_opening_container = $self->[_K_opening_container_];
    +    my $K_opening           = $K_opening_container->{$seqno};
    +    return unless ( defined($K_opening) );
    +
    +    my $rLL        = $self->[_rLL_];
    +    my $block_type = $rLL->[$K_opening]->[_BLOCK_TYPE_];
    +    return if ($block_type);
    +
    +    my $token = $rLL->[$K_opening]->[_TOKEN_];
    +    return if ( $token eq ':' );
     
         # We will require at least 2 commas or 1 fat comma in the
         # immediate lower level.
    -    my $fat_comma_count = $rtype_count_by_seqno->{$seqno}->{'=>'};
    -    my $comma_count     = $rtype_count_by_seqno->{$seqno}->{','};
    +    my $rtype_count_by_seqno = $self->[_rtype_count_by_seqno_];
    +    my $fat_comma_count      = $rtype_count_by_seqno->{$seqno}->{'=>'};
    +    my $comma_count          = $rtype_count_by_seqno->{$seqno}->{','};
         my $is_list = ( $fat_comma_count || $comma_count && $comma_count > 1 );
         return $is_list;
     }
    @@ -17957,6 +17991,7 @@ sub insert_breaks_before_list_opening_containers {
         my $rLL                   = $self->[_rLL_];
         my $ris_broken_container  = $self->[_ris_broken_container_];
         my $rhas_broken_container = $self->[_rhas_broken_container_];
    +    my $rparent_of_seqno      = $self->[_rparent_of_seqno_];
     
         # scan the ends of all lines
         my @insert_list;
    @@ -17970,7 +18005,7 @@ sub insert_breaks_before_list_opening_containers {
             my $iend     = $ir;
             my $type_end = $rLL->[$Kr]->[_TYPE_];
     
    -        # backup before a side comment
    +        # Backup before any side comment
             if ( $type_end eq '#' ) {
                 $Kend = $self->K_previous_nonblank($Kr);
                 next unless defined($Kend);
    @@ -17978,46 +18013,36 @@ sub insert_breaks_before_list_opening_containers {
                 $iend     = $ir + ( $Kend - $Kr );
             }
     
    -        # This is only for line-ending tokens with a preceding blank
    -        # on the same line.
             next unless ( $Kl < $Kend - 1 );
     
    -        # And only for some kind of container token
             my $seqno = $rLL->[$Kend]->[_TYPE_SEQUENCE_];
             next unless ( defined($seqno) );
     
    -        # And only for selected types of container tokens
    +	# Only for types of container tokens with a non-default break option
             my $token_end    = $rLL->[$Kend]->[_TOKEN_];
             my $break_option = $break_before_container_types{$token_end};
             next unless ($break_option);
     
    -        # This is not for code block braces
    -        my $block_type = $rLL->[$Kend]->[_BLOCK_TYPE_];
    -        next if ($block_type);
    -
    -        # Require a space before the line ending token
    -        next unless ( $rLL->[ $Kend - 1 ]->[_TYPE_] eq 'b' );
    +        # Require previous nonblank to be certain types (= and =>)
    +        # Note similar coding in sub adjust_container_indentation
    +        my $Kprev     = $Kend - 1;
    +        my $prev_type = $rLL->[$Kprev]->[_TYPE_];
    +        if ( $prev_type eq 'b' ) {
    +            $Kprev--;
    +            next if ( $Kprev <= $Kl );
    +            $prev_type = $rLL->[$Kprev]->[_TYPE_];
    +        }
    +        next unless ( $is_equal_or_fat_comma{$prev_type} );
     
    +        # This must be a list (this will exclude all code blocks)
             next unless $self->is_list($seqno);
     
    -        # Do not break a weld
    +        # Never break a weld
             next if ( $self->weld_len_left( $seqno, $token_end ) );
     
    -        # Parens cannot break after certain keywords
    -        if ( $token_end eq '(' ) {
    -            my $iend_m2 = $iend - 2;
    -            if ( $iend_m2 >= $il ) {
    -                if ( $types_to_go[$iend_m2] eq 'k'
    -                    && $is_if_elsif_else_unless_while_until_for_foreach{
    -                        $tokens_to_go[$iend_m2] } )
    -                {
    -                    next;
    -                }
    -            }
    -        }
    +        # Final decision is based on selected option:
     
    -        # Final decision is based on selected option
    -        # 1 = stable
    +        # Option 1 = stable, try to follow input
             my $ok_to_break;
             if ( $break_option == 1 ) {
                 if ( $ir - 2 > $il ) {
    @@ -18025,32 +18050,36 @@ sub insert_breaks_before_list_opening_containers {
                 }
             }
     
    -        # 2 = only if complex list
    +        # Option 2 = only if complex list, meaning:
    +        #  - this list contains a broken container, or
    +        #  - this list is contained in a broken list
             elsif ( $break_option == 2 ) {
                 $ok_to_break = $rhas_broken_container->{$seqno};
    +            if ( !$ok_to_break ) {
    +                my $parent = $rparent_of_seqno->{$seqno};
    +                $ok_to_break = $self->is_list($parent);
    +            }
             }
     
    -        # 3 = always break
    +        # Option 3 = always break
             elsif ( $break_option == 3 ) {
                 $ok_to_break = 1;
             }
     
    -        # Shouldn't happen! Bad flag, make same as 3
    +        # Shouldn't happen! Bad flag, but make behavior same as 3
             else {
                 $ok_to_break = 1;
             }
     
             next unless ($ok_to_break);
     
    -        # This meets the criteria, so install a break
    +        # This meets the criteria, so install a break before the opening token.
             my $Kbreak = $self->K_previous_nonblank($Kend);
             my $ibreak = $Kbreak - $Kl + $il;
             next if ( $ibreak < $il );
             next if ( $nobreak_to_go[$ibreak] );
             push @insert_list, $ibreak;
     
    -        # FIXME: at this point we could inform any child containers that they
    -        # are part of a complex container.
         }
     
         # insert any new break points
    diff --git a/t/snippets/expect/bbhb.bbhb2 b/t/snippets/expect/bbhb.bbhb2
    index 670c04d3..a39f536a 100644
    --- a/t/snippets/expect/bbhb.bbhb2
    +++ b/t/snippets/expect/bbhb.bbhb2
    @@ -1,8 +1,9 @@
     my %temp =
       (
         supsup => 123,
    -    nested => {
    +    nested =>
    +      {
             asdf => 456,
             yarg => 'yarp',
    -    },
    +      },
       );
    diff --git a/t/snippets/packing_list.txt b/t/snippets/packing_list.txt
    index 93e1f572..4b5dd44c 100644
    --- a/t/snippets/packing_list.txt
    +++ b/t/snippets/packing_list.txt
    @@ -274,6 +274,8 @@
     ../snippets22.t	bbhb.bbhb2
     ../snippets22.t	bbhb.bbhb3
     ../snippets22.t	bbhb.def
    +../snippets22.t	bbhb.bbhb4
    +../snippets22.t	bbhb.bbhb5
     ../snippets3.t	ce_wn1.ce_wn
     ../snippets3.t	ce_wn1.def
     ../snippets3.t	colin.colin
    @@ -414,5 +416,3 @@
     ../snippets9.t	rt98902.def
     ../snippets9.t	rt98902.rt98902
     ../snippets9.t	rt99961.def
    -../snippets22.t	bbhb.bbhb4
    -../snippets22.t	bbhb.bbhb5
    diff --git a/t/snippets22.t b/t/snippets22.t
    index 4ae6b702..104fe846 100644
    --- a/t/snippets22.t
    +++ b/t/snippets22.t
    @@ -83,10 +83,11 @@ END_OF_SELECT
     my %temp =
       (
         supsup => 123,
    -    nested => {
    +    nested =>
    +      {
             asdf => 456,
             yarg => 'yarp',
    -    },
    +      },
       );
     #2...........
             },
    -- 
    2.39.5