]> git.donarmstrong.com Git - perltidy.git/commitdiff
rewrote 'send_lines_to_vertical_aligner'; no globals
authorSteve Hancock <perltidy@users.sourceforge.net>
Wed, 1 Jan 2020 18:53:46 +0000 (10:53 -0800)
committerSteve Hancock <perltidy@users.sourceforge.net>
Wed, 1 Jan 2020 18:53:46 +0000 (10:53 -0800)
lib/Perl/Tidy/Formatter.pm
lib/Perl/Tidy/Tokenizer.pm
t/snippets/expect/rt125012.rt125012
t/snippets/packing_list.txt
t/snippets8.t

index b967aed57980350b0c934481c3317760eca85cb9..f0f33c0518ec817c092c36531c90417f15b6c8f0 100644 (file)
@@ -1570,6 +1570,12 @@ sub break_lines {
                 next;
             }
 
+            # Handle block comment to be deleted
+            elsif ( $CODE_type eq 'DEL' ) {
+                $self->flush();
+                next;
+            }
+
             # Handle all other lines of code
             $self->print_line_of_tokens($line_of_tokens);
         }
@@ -7195,8 +7201,6 @@ EOM
         ######################################
         if ($is_comment) {
 
-            if ( $rOpts->{'delete-block-comments'} ) { return }
-
             if ( $rOpts->{'tee-block-comments'} ) {
                 $file_writer_object->tee_on();
             }
@@ -8055,16 +8059,49 @@ sub output_line_to_go {
             $self->delete_one_line_semicolons( $ri_first, $ri_last );
         }
 
-        # The line breaks for this batch of code have been finalized;
-        my $rlines_i;
+        # The line breaks for this batch of code have been finalized. Now we
+        # can to package the results for further processing.  We will switch
+        # from the local '_to_go' buffer arrays (i-index) back to the global
+        # token arrays (K-index) at this point.
+        my $rlines_K;
+        my $index_error;
         for ( my $n = 0 ; $n < @{$ri_first} ; $n++ ) {
-            push @{$rlines_i}, [ $ri_first->[$n], $ri_last->[$n] ];
+            my $ibeg = $ri_first->[$n];
+            my $Kbeg = $K_to_go[$ibeg];
+            my $iend = $ri_last->[$n];
+            my $Kend = $K_to_go[$iend];
+            if ( $iend - $ibeg != $Kend - $Kbeg ) {
+                $index_error = $n unless defined($index_error);
+            }
+            push @{$rlines_K},
+              [ $Kbeg, $Kend, $forced_breakpoint_to_go[$iend] ];
+        }
+
+        # Check correctness of the mapping between the i and K token indexes
+        if ( defined($index_error) ) {
+
+            # Temporary debug code - should never get here
+            for ( my $n = 0 ; $n < @{$ri_first} ; $n++ ) {
+                my $ibeg  = $ri_first->[$n];
+                my $Kbeg  = $K_to_go[$ibeg];
+                my $iend  = $ri_last->[$n];
+                my $Kend  = $K_to_go[$iend];
+                my $idiff = $iend - $ibeg;
+                my $Kdiff = $Kend - $Kbeg;
+                print STDERR <<EOM;
+line $n, irange $ibeg-$iend = $idiff, Krange $Kbeg-$Kend = $Kdiff;
+EOM
+            }
+            Fault("Index error at line $index_error; i and K ranges differ");
         }
-        my $rcall_hash = {
-            rlines_i   => $rlines_i,
+
+        my $rbatch_hash = {
+            rlines_K   => $rlines_K,
             do_not_pad => $do_not_pad,
+            ibeg0      => $ri_first->[0],
         };
-        $self->send_lines_to_vertical_aligner($rcall_hash);
+
+        $self->send_lines_to_vertical_aligner($rbatch_hash);
 
         # Insert any requested blank lines after an opening brace.  We have to
         # skip back before any side comment to find the terminal token
@@ -9886,32 +9923,53 @@ sub previous_nonblank_token {
 
 sub send_lines_to_vertical_aligner {
 
-    my ( $self, $rcall_hash ) = @_;
+    my ( $self, $rbatch_hash ) = @_;
+
+   # This routine receives a batch of code for which the final line breaks
+   # have been defined. Here we prepare the lines for passing to the vertical
+   # aligner.  We do the following tasks:
+   # - mark certain vertical alignment tokens tokens, such as '=', in each line.
+   # - make minor indentation adjustments
+   # - insert extra blank spaces to help display certain logical constructions
 
-    my $do_not_pad = $rcall_hash->{do_not_pad};
-    my $rlines_i   = $rcall_hash->{rlines_i};
-    if ( !@{$rlines_i} ) {
-        Fault("Error in send_lines_to_vertical_aligner: no lines");
+    my $rlines_K = $rbatch_hash->{rlines_K};
+    if ( !@{$rlines_K} ) {
+        Fault("Unexpected call with no lines");
         return;
     }
+    my $n_last_line = @{$rlines_K} - 1;
+    my $do_not_pad  = $rbatch_hash->{do_not_pad};
+
+    my $rLL    = $self->{rLL};
+    my $Klimit = $self->{Klimit};
+
+    my ( $Kbeg_next, $Kend_next ) = @{ $rlines_K->[0] };
+    my $type_beg_next  = $rLL->[$Kbeg_next]->[_TYPE_];
+    my $token_beg_next = $rLL->[$Kbeg_next]->[_TOKEN_];
+    my $type_end_next  = $rLL->[$Kend_next]->[_TYPE_];
+
+    # Construct indexes to the global_to_go arrays so that called routines can
+    # still access those arrays. This might eventually be removed
+    # when all called routines have been converted to access token values
+    # in the rLL array instead.
+    my $ibeg0 = $rbatch_hash->{ibeg0};
+    my $Kbeg0 = $Kbeg_next;
     my ( $ri_first, $ri_last );
-    foreach my $rline ( @{$rlines_i} ) {
-        my ( $ibeg, $iend ) = @{$rline};
+    foreach my $rline ( @{$rlines_K} ) {
+        my ( $Kbeg, $Kend ) = @{$rline};
+        my $ibeg = $ibeg0 + $Kbeg - $Kbeg0;
+        my $iend = $ibeg0 + $Kend - $Kbeg0;
         push @{$ri_first}, $ibeg;
         push @{$ri_last},  $iend;
     }
+    #####################################################################
 
     my $valign_batch_number = $self->increment_valign_batch_count();
 
     my ( $cscw_block_comment, $closing_side_comment );
-    if ( $rOpts->{'closing-side-comments'} && $max_index_to_go >= 0 ) {
+    if ( $rOpts->{'closing-side-comments'} ) {
         ( $closing_side_comment, $cscw_block_comment ) =
           $self->add_closing_side_comment();
-
-        # Add or update any closing side comment
-        if ( $types_to_go[$max_index_to_go] eq '#' ) {
-            $ri_last->[-1] = $max_index_to_go;
-        }
     }
 
     my $rindentation_list = [0];    # ref to indentations for each line
@@ -9922,16 +9980,11 @@ sub send_lines_to_vertical_aligner {
     my $ralignment_type_to_go =
       $self->set_vertical_alignment_markers( $ri_first, $ri_last );
 
-    # flush if necessary to avoid unwanted alignment
-    my $must_flush = 0;
-    if ( @{$ri_first} > 1 ) {
-
-        # flush before a long if statement
-        if ( $types_to_go[0] eq 'k' && $tokens_to_go[0] =~ /^(if|unless)$/ ) {
-            $must_flush = 1;
-        }
-    }
-    if ($must_flush) {
+    # flush before a long if statement to avoid unwanted alignment
+    if (   $n_last_line > 0
+        && $type_beg_next eq 'k'
+        && $token_beg_next =~ /^(if|unless)$/ )
+    {
         Perl::Tidy::VerticalAligner::flush();
     }
 
@@ -9940,11 +9993,53 @@ sub send_lines_to_vertical_aligner {
     $self->set_logical_padding( $ri_first, $ri_last );
 
     # loop to prepare each line for shipment
-    my $n_last_line = @{$ri_first} - 1;
     my $in_comma_list;
+    my ( $Kbeg, $type_beg, $token_beg );
+    my ( $Kend, $type_end );
     for my $n ( 0 .. $n_last_line ) {
-        my $ibeg = $ri_first->[$n];
-        my $iend = $ri_last->[$n];
+
+        my $ibeg              = $ri_first->[$n];
+        my $iend              = $ri_last->[$n];
+        my $rline             = $rlines_K->[$n];
+        my $forced_breakpoint = $rline->[2];
+
+        # we may need to look at variables on three consecutive lines ...
+
+        # Some vars on line [n-1], if any:
+        my $Kbeg_last      = $Kbeg;
+        my $type_beg_last  = $type_beg;
+        my $token_beg_last = $token_beg;
+        my $Kend_last      = $Kend;
+        my $type_end_last  = $type_end;
+
+        # Some vars on line [n]:
+        $Kbeg      = $Kbeg_next;
+        $type_beg  = $type_beg_next;
+        $token_beg = $token_beg_next;
+        $Kend      = $Kend_next;
+        $type_end  = $type_end_next;
+
+        # We use two slightly different definitions of level jump at the end
+        # of line:
+        #  $ljump is the level jump needed by 'sub set_adjusted_indentation'
+        #  $level_jump is the level jump needed by the vertical aligner.
+        my $ljump = 0;    # level jump at end of line
+
+        # Get some vars on line [n+1], if any:
+        if ( $n < $n_last_line ) {
+            ( $Kbeg_next, $Kend_next ) =
+              @{ $rlines_K->[ $n + 1 ] };
+            $type_beg_next  = $rLL->[$Kbeg_next]->[_TYPE_];
+            $token_beg_next = $rLL->[$Kbeg_next]->[_TOKEN_];
+            $type_end_next  = $rLL->[$Kend_next]->[_TYPE_];
+            $ljump = $rLL->[$Kbeg_next]->[_LEVEL_] - $rLL->[$Kend]->[_LEVEL_];
+        }
+
+        # level jump at end of line for the vertical aligner:
+        my $level_jump =
+          $Kend >= $Klimit
+          ? 0
+          : $rLL->[ $Kend + 1 ]->[_SLEVEL_] - $rLL->[$Kbeg]->[_SLEVEL_];
 
         $self->delete_needless_alignments( $ibeg, $iend,
             $ralignment_type_to_go );
@@ -9953,14 +10048,6 @@ sub send_lines_to_vertical_aligner {
           $self->make_alignment_patterns( $ibeg, $iend,
             $ralignment_type_to_go );
 
-        # Set flag to show how much level changes between this line
-        # and the next line, if we have it.
-        my $ljump = 0;
-        if ( $n < $n_last_line ) {
-            my $ibegp = $ri_first->[ $n + 1 ];
-            $ljump = $levels_to_go[$ibegp] - $levels_to_go[$iend];
-        }
-
         my ( $indentation, $lev, $level_end, $terminal_type,
             $is_semicolon_terminated, $is_outdented_line )
           = $self->set_adjusted_indentation( $ibeg, $iend, $rfields, $rpatterns,
@@ -9970,11 +10057,11 @@ sub send_lines_to_vertical_aligner {
         my $outdent_long_lines = (
 
             # which are long quotes, if allowed
-            ( $types_to_go[$ibeg] eq 'Q' && $rOpts->{'outdent-long-quotes'} )
+            ( $type_beg eq 'Q' && $rOpts->{'outdent-long-quotes'} )
 
             # which are long block comments, if allowed
               || (
-                   $types_to_go[$ibeg] eq '#'
+                   $type_beg eq '#'
                 && $rOpts->{'outdent-long-comments'}
 
                 # but not if this is a static block comment
@@ -9982,9 +10069,6 @@ sub send_lines_to_vertical_aligner {
               )
         );
 
-        my $level_jump =
-          $nesting_depth_to_go[ $iend + 1 ] - $nesting_depth_to_go[$ibeg];
-
         my $rvertical_tightness_flags =
           $self->set_vertical_tightness_flags( $n, $n_last_line, $ibeg, $iend,
             $ri_first, $ri_last );
@@ -10008,50 +10092,54 @@ sub send_lines_to_vertical_aligner {
         # );
         #
         my $is_terminal_ternary = 0;
-        if (   $tokens_to_go[$ibeg] eq ':'
-            || $n > 0 && $tokens_to_go[ $ri_last->[ $n - 1 ] ] eq ':' )
-        {
-            my $last_leading_type = ":";
-            if ( $n > 0 ) {
-                my $iprev = $ri_first->[ $n - 1 ];
-                $last_leading_type = $types_to_go[$iprev];
-            }
+
+        if ( $type_beg eq ':' || $n > 0 && $type_end_last eq ':' ) {
+            my $last_leading_type = $n > 0 ? $type_beg_last : ':';
             if (   $terminal_type ne ';'
                 && $n_last_line > $n
                 && $level_end == $lev )
             {
-                my $inext = $ri_first->[ $n + 1 ];
-                $level_end     = $levels_to_go[$inext];
-                $terminal_type = $types_to_go[$inext];
+                $level_end     = $rLL->[$Kbeg_next]->[_LEVEL_];
+                $terminal_type = $rLL->[$Kbeg_next]->[_TYPE_];
             }
+            if (
+                $last_leading_type eq ':'
+                && (   ( $terminal_type eq ';' && $level_end <= $lev )
+                    || ( $terminal_type ne ':' && $level_end < $lev ) )
+              )
+            {
 
-            $is_terminal_ternary = $last_leading_type eq ':'
-              && ( ( $terminal_type eq ';' && $level_end <= $lev )
-                || ( $terminal_type ne ':' && $level_end < $lev ) )
+                # the terminal term must not contain any ternary terms, as in
+                # my $ECHO = (
+                #       $Is_MSWin32 ? ".\\echo$$"
+                #     : $Is_MacOS   ? ":echo$$"
+                #     : ( $Is_NetWare ? "echo$$" : "./echo$$" )
+                # );
+                $is_terminal_ternary = 1;
 
-              # the terminal term must not contain any ternary terms, as in
-              # my $ECHO = (
-              #       $Is_MSWin32 ? ".\\echo$$"
-              #     : $Is_MacOS   ? ":echo$$"
-              #     : ( $Is_NetWare ? "echo$$" : "./echo$$" )
-              # );
-              && !grep { /^[\?\:]$/ } @types_to_go[ $ibeg + 1 .. $iend ];
+                my $KP = $rLL->[$Kbeg]->[_KNEXT_SEQ_ITEM_];
+                while ( defined($KP) && $KP <= $Kend ) {
+                    my $type_KP = $rLL->[$KP]->[_TYPE_];
+                    if ( $type_KP eq '?' || $type_KP eq ':' ) {
+                        $is_terminal_ternary = 0;
+                        last;
+                    }
+                    $KP = $rLL->[$KP]->[_KNEXT_SEQ_ITEM_];
+                }
+            }
         }
 
-        # add any closing side comment to the last line
+        # add any new closing side comment to the last line
         if ( $closing_side_comment && $n == $n_last_line && @{$rfields} ) {
             $rfields->[-1] .= " $closing_side_comment";
         }
 
         # send this new line down the pipe
-        my $forced_breakpoint = $forced_breakpoint_to_go[$iend];
-
         my $rvalign_hash = {};
-        $rvalign_hash->{level}       = $lev;
-        $rvalign_hash->{level_end}   = $level_end;
-        $rvalign_hash->{indentation} = $indentation;
-        $rvalign_hash->{is_forced_break} =
-          $forced_breakpoint_to_go[$iend] || $in_comma_list;
+        $rvalign_hash->{level}           = $lev;
+        $rvalign_hash->{level_end}       = $level_end;
+        $rvalign_hash->{indentation}     = $indentation;
+        $rvalign_hash->{is_forced_break} = $forced_breakpoint || $in_comma_list;
         $rvalign_hash->{outdent_long_lines}        = $outdent_long_lines;
         $rvalign_hash->{is_terminal_ternary}       = $is_terminal_ternary;
         $rvalign_hash->{is_terminal_statement}     = $is_semicolon_terminated;
@@ -10064,8 +10152,7 @@ sub send_lines_to_vertical_aligner {
         Perl::Tidy::VerticalAligner::valign_input( $rvalign_hash, $rfields,
             $rtokens, $rpatterns );
 
-        $in_comma_list =
-          $tokens_to_go[$iend] eq ',' && $forced_breakpoint_to_go[$iend];
+        $in_comma_list = $type_end eq ',' && $forced_breakpoint;
 
         # flush an outdented line to avoid any unwanted vertical alignment
         Perl::Tidy::VerticalAligner::flush() if ($is_outdented_line);
@@ -10084,16 +10171,16 @@ sub send_lines_to_vertical_aligner {
         $last_output_short_opening_token
 
           # line ends in opening token
-          = $types_to_go[$iend] =~ /^[\{\(\[L]$/
+          = $type_end =~ /^[\{\(\[L]$/
 
           # and either
           && (
             # line has either single opening token
-            $iend == $ibeg
+            $Kend == $Kbeg
 
             # or is a single token followed by opening token.
             # Note that sub identifiers have blanks like 'sub doit'
-            || ( $iend - $ibeg <= 2 && $tokens_to_go[$ibeg] !~ /\s+/ )
+            || ( $Kend - $Kbeg <= 2 && $token_beg !~ /\s+/ )
           )
 
           # and limit total to 10 character widths
index edc07aa9a2406cc49173e0acfe70cf563b6b6434..73d6cd3bbb66731cafa4677f00654e3d9a5d0b2e 100644 (file)
@@ -2056,16 +2056,21 @@ sub prepare_for_a_new_file {
                 $is_pattern = 0;
             }
 
-           # patch for RT#131288, user constant function without prototype
-           # last type is 'U' followed by ?. 
-            elsif (   $last_nonblank_type =~ /^[FUY]$/ ) {
+            # patch for RT#131288, user constant function without prototype
+            # last type is 'U' followed by ?.
+            elsif ( $last_nonblank_type =~ /^[FUY]$/ ) {
                 $is_pattern = 0;
-           }
+            }
             elsif ( $expecting == UNKNOWN ) {
 
-               # FIXME: Can a bare ? still be a pattern delimiter in modern
-               # versions of Perl? Need to research this and decide what
-               # to do.
+                # In older versions of Perl, a bare ? can be a pattern
+                # delimiter.  Sometime after Perl 5.10 this seems to have
+                # been dropped, but we have to support it in order to format
+                # older programs.  For example, the following line worked
+                # at one time:
+                #      ?(.*)? && (print $1,"\n");
+                # In current versions it would have to be written with slashes:
+                #      /(.*)/ && (print $1,"\n");
                 my $msg;
                 ( $is_pattern, $msg ) =
                   guess_if_pattern_or_conditional( $i, $rtokens, $rtoken_map,
@@ -6428,7 +6433,7 @@ sub scan_identifier_do {
                 $statement_type = $tok;
             }
             elsif ($next_nonblank_token) {      # EOF technically ok
-               $subname = "" unless defined($subname);
+                $subname = "" unless defined($subname);
                 warning(
 "expecting ':' or ';' or '{' after definition or declaration of sub '$subname' but saw '$next_nonblank_token'\n"
                 );
index 8b64a694d564734147f50aff8bd50faa618211d6..057aa87ef12dad713efcaed272bf7494cdcad046 100644 (file)
@@ -1,2 +1,4 @@
-++$_ for values%_;
-system qq{};
+++$_ for
+  values%_;
+system
+  qq{};
index 5f4afdc0c726b2c2dde717efc74bfc5892649837..690938da86396068904d9901b1edb7883768496f 100644 (file)
 ../snippets16.t        rt131115.rt131115
 ../snippets16.t        ndsm1.def
 ../snippets16.t        ndsm1.ndsm
+../snippets16.t        rt131288.def
 ../snippets2.t angle.def
 ../snippets2.t arrows1.def
 ../snippets2.t arrows2.def
 ../snippets9.t rt98902.def
 ../snippets9.t rt98902.rt98902
 ../snippets9.t rt99961.def
-../snippets16.t        rt131288.def
index 77c50a2fcd876b74829585a0832df9b15fb3acb7..a8789d51b02a6844774a23b2807a4a4bc1962839 100644 (file)
@@ -282,8 +282,10 @@ system
             source => "rt125012",
             params => "rt125012",
             expect => <<'#7...........',
-++$_ for values%_;
-system qq{};
+++$_ for
+  values%_;
+system
+  qq{};
 #7...........
         },