From ec7476a130559ca0b8c1431c7891f3ddca1e9ae9 Mon Sep 17 00:00:00 2001 From: Steve Hancock Date: Sat, 2 May 2020 16:36:56 -0700 Subject: [PATCH] tee options now work correctly with -io and -it=n --- lib/Perl/Tidy.pm | 75 ++++++++++++++++++------------ lib/Perl/Tidy/FileWriter.pm | 12 ----- lib/Perl/Tidy/Formatter.pm | 37 ++++++++------- lib/Perl/Tidy/LineSink.pm | 91 ++++++++----------------------------- 4 files changed, 86 insertions(+), 129 deletions(-) diff --git a/lib/Perl/Tidy.pm b/lib/Perl/Tidy.pm index bc2b1267..03f8345b 100644 --- a/lib/Perl/Tidy.pm +++ b/lib/Perl/Tidy.pm @@ -1153,9 +1153,19 @@ EOM } } - # the 'sink_object' knows how to write the output file + my $fh_tee; my $tee_file = $fileroot . $dot . "TEE"; if ($teefile_stream) { $tee_file = $teefile_stream } + if ( $rOpts->{'tee-pod'} + || $rOpts->{'tee-block-comments'} + || $rOpts->{'tee-side-comments'} ) + { + ( $fh_tee, my $tee_filename ) = + Perl::Tidy::streamhandle( $tee_file, 'w', $is_encoded_data ); + if ( !$fh_tee ) { + Warn("couldn't open TEE file $tee_file: $!\n"); + } + } my $line_separator = $rOpts->{'output-line-ending'}; if ( $rOpts->{'preserve-line-endings'} ) { @@ -1164,21 +1174,28 @@ EOM $line_separator = "\n" unless defined($line_separator); + # the 'sink_object' knows how to write the output file my ( $sink_object, $postfilter_buffer ); if ( $postfilter || $rOpts->{'assert-tidy'} || $rOpts->{'assert-untidy'} ) { - $sink_object = - Perl::Tidy::LineSink->new( \$postfilter_buffer, $tee_file, - $line_separator, $rOpts, $rpending_logfile_message, - $is_encoded_data ); + $sink_object = Perl::Tidy::LineSink->new( + output_file => \$postfilter_buffer, + line_separator => $line_separator, + rOpts => $rOpts, + rpending_logfile_message => $rpending_logfile_message, + is_encoded_data => $is_encoded_data, + ); } else { - $sink_object = - Perl::Tidy::LineSink->new( $output_file, $tee_file, - $line_separator, $rOpts, $rpending_logfile_message, - $is_encoded_data ); + $sink_object = Perl::Tidy::LineSink->new( + output_file => $output_file, + line_separator => $line_separator, + rOpts => $rOpts, + rpending_logfile_message => $rpending_logfile_message, + is_encoded_data => $is_encoded_data, + ); } #--------------------------------------------------------------- @@ -1225,39 +1242,37 @@ EOM my $sink_object_final = $sink_object; my $debugger_object_final = $debugger_object; my $logger_object_final = $logger_object; + my $fh_tee_final = $fh_tee; foreach my $iter ( 1 .. $max_iterations ) { # send output stream to temp buffers until last iteration my $sink_buffer; if ( $iter < $max_iterations ) { - $sink_object = - Perl::Tidy::LineSink->new( \$sink_buffer, $tee_file, - $line_separator, $rOpts, $rpending_logfile_message, - $is_encoded_data ); + $sink_object = Perl::Tidy::LineSink->new( + output_file => \$sink_buffer, + line_separator => $line_separator, + rOpts => $rOpts, + rpending_logfile_message => $rpending_logfile_message, + is_encoded_data => $is_encoded_data, + ); } else { $sink_object = $sink_object_final; } - # Save logger, debugger output only on pass 1 because: + # Save logger, debugger and tee output only on pass 1 because: # (1) line number references must be to the starting # source, not an intermediate result, and # (2) we need to know if there are errors so we can stop the # iterations early if necessary. + # (3) the tee option only works on first pass if comments are also + # being deleted. - # Programming note: ideally, we would also only save any .TEE file - # on iteration pass 1, but unfortunately the .TEE stream is - # combined in the sink object with the main output stream. The - # programming actually works as is, with the .TEE file being - # written and rewritten on each iteration. This even works if we - # are deleting comments or pod in the same run. But this - # complexity could cause future bugs so it would be best to - # eventually split the tee output into a completely separate stream - # to just save it on pass 1 and avoid this complexity. if ( $iter > 1 ) { $debugger_object = undef; $logger_object = undef; + $fh_tee = undef; } #------------------------------------------------------------ @@ -1284,6 +1299,7 @@ EOM diagnostics_object => $diagnostics_object, sink_object => $sink_object, length_function => $length_function, + fh_tee => $fh_tee, ); } else { @@ -1401,6 +1417,7 @@ EOM # for second and higher iterations $debugger_object = $debugger_object_final; $logger_object = $logger_object_final; + $fh_tee = $fh_tee_final; $logger_object->write_logfile_entry($convergence_log_message) if $convergence_log_message; @@ -1413,10 +1430,13 @@ EOM || $rOpts->{'assert-untidy'} ) { $sink_object->close_output_file(); - $sink_object = - Perl::Tidy::LineSink->new( $output_file, $tee_file, - $line_separator, $rOpts, $rpending_logfile_message, - $is_encoded_data ); + $sink_object = Perl::Tidy::LineSink->new( + output_file => $output_file, + line_separator => $line_separator, + rOpts => $rOpts, + rpending_logfile_message => $rpending_logfile_message, + is_encoded_data => $is_encoded_data, + ); my $buf = $postfilter @@ -4166,4 +4186,3 @@ sub do_syntax_check { } 1; - diff --git a/lib/Perl/Tidy/FileWriter.pm b/lib/Perl/Tidy/FileWriter.pm index 2c867909..943cefe5 100644 --- a/lib/Perl/Tidy/FileWriter.pm +++ b/lib/Perl/Tidy/FileWriter.pm @@ -43,18 +43,6 @@ sub new { }, $class; } -sub tee_on { - my $self = shift; - $self->{_line_sink_object}->tee_on(); - return; -} - -sub tee_off { - my $self = shift; - $self->{_line_sink_object}->tee_off(); - return; -} - sub get_output_line_number { my $self = shift; return $self->{_output_line_number}; diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm index fbcabfbe..dd6fed74 100644 --- a/lib/Perl/Tidy/Formatter.pm +++ b/lib/Perl/Tidy/Formatter.pm @@ -580,10 +580,12 @@ sub new { diagnostics_object => undef, logger_object => undef, length_function => sub { return length( $_[0] ) }, + fh_tee => undef, ); my %args = ( %defaults, @args ); my $length_function = $args{length_function}; + my $fh_tee = $args{fh_tee}; $logger_object = $args{logger_object}; $diagnostics_object = $args{diagnostics_object}; @@ -723,6 +725,7 @@ sub new { rvalid_self_keys => [], # for checking valign_batch_count => 0, length_function => $length_function, + fh_tee => $fh_tee, sink_object => $sink_object, logger_object => $logger_object, file_writer_object => $file_writer_object, @@ -1377,13 +1380,14 @@ EOM return $rhash_of_desires; } -sub break_lines { +sub process_all_lines { # Loop over old lines to set new line break points my $self = shift; my $rlines = $self->{rlines}; my $sink_object = $self->{sink_object}; + my $fh_tee = $self->{fh_tee}; my $rOpts_keep_old_blank_lines = $rOpts->{'keep-old-blank-lines'}; # Note for RT#118553, leave only one newline at the end of a file. @@ -1520,7 +1524,7 @@ sub break_lines { $self->want_blank_line(); } if ( $rOpts->{'tee-pod'} ) { - $sink_object->write_tee_line($input_line); + $fh_tee->print($input_line) if ($fh_tee); } } @@ -4725,10 +4729,10 @@ sub finish_formatting { # Eventually this call should just change the 'rlines' data according to the # new line breaks and then return so that we can do an internal iteration # before continuing with the next stages of formatting. - $self->break_lines(); + $self->process_all_lines(); ############################################################ - # A possible future decomposition of 'break_lines()' follows. + # A possible future decomposition of 'process_all_lines()' follows. # Benefits: # - allow perltidy to do an internal iteration which eliminates # many unnecessary steps, such as re-parsing and vertical alignment. @@ -7145,6 +7149,7 @@ sub copy_token_as_type { my $rbreak_container = $self->{rbreak_container}; my $rshort_nested = $self->{rshort_nested}; my $sink_object = $self->{sink_object}; + my $fh_tee = $self->{fh_tee}; my $rOpts_add_newlines = $rOpts->{'add-newlines'}; my $rOpts_break_at_old_comma_breakpoints = @@ -7207,7 +7212,7 @@ sub copy_token_as_type { if ($is_comment) { if ( $rOpts->{'tee-block-comments'} ) { - $sink_object->write_tee_line($input_line); + $fh_tee->print($input_line) if ($fh_tee); } if ( $rOpts->{'delete-block-comments'} ) { $self->flush(); @@ -7286,16 +7291,16 @@ sub copy_token_as_type { $self->flush(); my $line = $input_line; - # delete side comments if requested with -io, but - # we will not allow deleting of closing side comments with -io - # because the coding would be more complex - if ( $rOpts->{'delete-side-comments'} - && $rLL->[$K_last]->[_TYPE_] eq '#' ) - { - - $line = ""; - foreach my $KK ( $K_first .. $K_last - 1 ) { - $line .= $rLL->[$KK]->[_TOKEN_]; + # delete side comments if requested with -io + if ( $rLL->[$K_last]->[_TYPE_] eq '#' ) { + if ( $rOpts->{'delete-side-comments'} ) { + $line = ""; + foreach my $KK ( $K_first .. $K_last - 1 ) { + $line .= $rLL->[$KK]->[_TOKEN_]; + } + } + if ( $rOpts->{'tee-side-comments'} ) { + $fh_tee->print($input_line) if ($fh_tee); } } @@ -7769,7 +7774,7 @@ sub copy_token_as_type { my $type = $rLL->[$K_last]->[_TYPE_]; if ( $type eq '#' && $rOpts->{'tee-side-comments'} ) { - $sink_object->write_tee_line($input_line); + $fh_tee->print($input_line) if ($fh_tee); } # we have to flush .. diff --git a/lib/Perl/Tidy/LineSink.pm b/lib/Perl/Tidy/LineSink.pm index 5ae901c8..bdd899d7 100644 --- a/lib/Perl/Tidy/LineSink.pm +++ b/lib/Perl/Tidy/LineSink.pm @@ -12,11 +12,24 @@ our $VERSION = '20200110.01'; sub new { - my ( $class, $output_file, $tee_file, $line_separator, $rOpts, - $rpending_logfile_message, $is_encoded_data ) - = @_; - my $fh = undef; - my $fh_tee = undef; + my ( $class, @args ) = @_; + + my %defaults = ( + output_file => undef, + line_separator => undef, + rOpts => undef, + rpending_logfile_message => undef, + is_encoded_data => undef, + ); + my %args = ( %defaults, @args ); + + my $output_file = $args{output_file}; + my $line_separator = $args{line_separator}; + my $rOpts = $args{rOpts}; + my $rpending_logfile_message = $args{rpending_logfile_message}; + my $is_encoded_data = $args{is_encoded_data}; + + my $fh = undef; my $output_file_open = 0; @@ -45,12 +58,8 @@ EOM return bless { _fh => $fh, - _fh_tee => $fh_tee, _output_file => $output_file, _output_file_open => $output_file_open, - _tee_flag => 0, - _tee_file => $tee_file, - _tee_file_opened => 0, _line_separator => $line_separator, _is_encoded_data => $is_encoded_data, }, $class; @@ -67,54 +76,6 @@ sub write_line { $fh->print($line) if ( $self->{_output_file_open} ); - if ( $self->{_tee_flag} ) { - unless ( $self->{_tee_file_opened} ) { $self->really_open_tee_file() } - my $fh_tee = $self->{_fh_tee}; - $fh_tee->print($line); - } - return; -} - -sub write_tee_line { - - # write line to tee file only... - # the original tee-on/tee-off method is being replaced because it - # did not allow simultaneous tee-ing and deleting - - my ( $self, $line ) = @_; - chomp $line; - $line .= $self->{_line_separator}; - unless ( $self->{_tee_file_opened} ) { $self->really_open_tee_file() } - my $fh_tee = $self->{_fh_tee}; - $fh_tee->print($line); - return; -} - -sub tee_on { - my $self = shift; - $self->{_tee_flag} = 1; - return; -} - -sub tee_off { - my $self = shift; - $self->{_tee_flag} = 0; - return; -} - -sub really_open_tee_file { - my $self = shift; - my $tee_file = $self->{_tee_file}; - my $is_encoded_data = $self->{_is_encoded_data}; - - my ( $fh_tee, $filename ) = - Perl::Tidy::streamhandle( $tee_file, 'w', $is_encoded_data ); - if ( !$fh_tee ) { - Perl::Tidy::Die("couldn't open TEE file $tee_file: $!\n"); - } - - $self->{_tee_file_opened} = 1; - $self->{_fh_tee} = $fh_tee; return; } @@ -126,23 +87,7 @@ sub close_output_file { if ( $output_file ne '-' && !ref $output_file ) { eval { $self->{_fh}->close() } if $self->{_output_file_open}; } - $self->close_tee_file(); - return; -} - -sub close_tee_file { - my $self = shift; - - # Only close physical files, not STDOUT and other objects - if ( $self->{_tee_file_opened} ) { - my $tee_file = $self->{_tee_file}; - if ( $tee_file ne '-' && !ref $tee_file ) { - eval { $self->{_fh_tee}->close() }; - $self->{_tee_file_opened} = 0; - } - } return; } 1; - -- 2.39.5