sub set_ci {
- # Set the basic continuation indentation (ci) for all tokens.
+ my ($self) = @_;
- # This is an experimental routine intended to eventually replace
- # the ci values computed by the tokenizer. For testing it is invoked
- # with -exp=ci
- my $use_experimental_ci = DEVEL_MODE
- || $rOpts->{'experimental'} && $rOpts->{'experimental'} =~ /\bci\b/;
+ # Set the basic continuation indentation (ci) for all tokens.
+ # This is a replacement for the values previously computed in
+ # sub Perl::Tidy::Tokenizer::tokenizer_wrapup. In most cases it
+ # produces identical results, but in a few cases it is an improvement.
- # This flag causes sub set_ci to still operate on comments when it would
- # otherwise not be used. This allows the effect on comments to be
- # filtered out in testing. This option is only for testing.
- my $use_experimental_ci1 =
- $rOpts->{'experimental'} && $rOpts->{'experimental'} =~ /\bci1\b/;
+ use constant DEBUG_SET_CI => 0;
- return if ( !$use_experimental_ci && !$use_experimental_ci1 );
+ # The following flag values are temporavailable for experimentation:
+ # -exp=ci0 OLD: use ci values computed by tokenizer
+ # -exp=ci1 MIXED: old ci values except for new ci for comments.
+ # -exp=ci2 NEW: ci values computed by this sub
+ my $calculate_ci = 2; # current default
+ if ( DEVEL_MODE || DEBUG_SET_CI ) { $calculate_ci = 2 }
+ elsif ($rOpts->{'experimental'}
+ && $rOpts->{'experimental'} =~ /\bci(\d+)\b/ )
+ {
+ $calculate_ci = $1;
+ }
+ return if ( !$calculate_ci );
+ my $ci_comments_only = $calculate_ci == 1;
# This turns on an optional piece of logic which makes the new and
# old computations of ci agree. It has almost no effect on actual
# programs but is useful for testing.
use constant SET_CI_OPTION_0 => 1;
- use constant DEBUG_SET_CI => 0;
-
- #---------------------------------------------------------------------------
- ## FIXME: This is also in break_lists; might become a global constant
+ # NOTE: This is slightly different from the hash in in break_lists
+ # with the same name
my %is_logical_container;
-
- # Removed ? : to fix t007 and others
+ ## Removed ? : to fix t007 and others
##my @q = qw# if elsif unless while and or err not && | || ? : ! #;
my @q = qw# if elsif unless while and or err not && | || ! #;
@is_logical_container{@q} = (1) x scalar(@q);
- # CAUTION: using differnt hash than in tokenizer here, but same name:
+ # NOTE: using differnt hash than in tokenizer here, but same name:
my %is_container_label_type;
- ## From tokenizer ???@q = qw( k => && || ? : . );
- ## Need to include '!'
- ## What about placing '.' in logical container
@q = qw# k && | || ? : ! #;
@is_container_label_type{@q} = (1) x scalar(@q);
- #---------------------------------------------------------------------------
-
- # - Contents are set to match old version for issue t027
- # - add '=' for t015
- # - add '=~' for 'locale.in'
- # - add '<=>' for 'corelist.in'
+ # The following hash is set to match old ci values
+ # - initially defined for issue t027, then
+ # - added '=' for t015
+ # - added '=~' for 'locale.in'
+ # - added '<=>' for 'corelist.in'
# Note:
# See @value_requestor_type for more that might be included
# See also @is_binary_type
push @q, ',';
@is_list_end_type{@q} = (1) x scalar(@q);
- my ($self) = @_;
my $rLL = $self->[_rLL_];
my $Klimit = $self->[_Klimit_];
return unless defined($Klimit);
_ci_close => 0,
_ci_close_next => 0,
_container_type => 'Block',
- _ci_default => 1,
+ _ci_next_next => 1,
_comma_count => 0,
_redo_list => undef,
_Kc => undef,
$token = $rtoken_K->[_TOKEN_];
# Definitions:
- # $ci_this = the ci for this token
- # $ci_next = the ci for the next token
- # $ci_default = the default ci for this container
+ # $ci_this = the ci for this token
+ # $ci_next = the ci for the next token
+ # $ci_next_next = the normal next value of $ci_next in this container
# Normally we use the ci value value set by previous token.
my $ci_this = $ci_next;
# First guess at next value uses the stored default
# which is 0 for logical containers, 1 for other containers:
- $ci_next = $rparent->{_ci_default};
+ $ci_next = $rparent->{_ci_next_next};
- # We will change these two ci values necessary for special cases...
+ # We will change these ci values necessary for special cases...
#-------------------------------
# Handle certain specific tokens
# Default ci values for the closing token, to be modified
# as necessary:
my $ci_close = $ci_next;
- my $ci_close_next = $rparent->{_ci_default};
+ my $ci_close_next = $rparent->{_ci_next_next};
my $Kc =
$type eq '?'
elsif ( $last_type eq '!' ) { $ci_this = $ci_last }
}
- my $ci_default = 1;
+ my $ci_next_next = 1;
my $block_type = $rblock_type_of_seqno->{$seqno};
$block_type = EMPTY_STRING unless ($block_type);
elsif ($is_logical) {
$container_type = 'Logical';
- $ci_default = 0;
+ $ci_next_next = 0;
$ci_close_next = $ci_this;
# Part 2 of optional patch to get agreement with previous ci
if ( $type eq '[' && SET_CI_OPTION_0 ) {
- $ci_default = $ci_this;
+ $ci_next_next = $ci_this;
# Undo ci at a chain of indexes or hash keys
if ( $last_type eq '}' ) {
$rparent = {
_seqno => $seqno,
_container_type => $container_type,
- _ci_default => $ci_default,
+ _ci_next_next => $ci_next_next,
_ci_open => $ci_this,
_ci_open_next => $ci_next,
_ci_close => $ci_close,
$rtoken_K->[_CI_LEVEL_] = $ci_this
- # TESTING
- if ($use_experimental_ci);
+ # do not store in hybrid testing mode
+ if ( !$ci_comments_only );
# Remember last nonblank, non-comment token info
$ci_last = $ci_this;
}
+ # if the logfile is saved, we need to save the leading ci of
+ # each old line of code.
+ if ( $self->[_save_logfile_] ) {
+ my $rlines = $self->[_rlines_];
+ foreach my $line_of_tokens ( @{$rlines} ) {
+ my $line_type = $line_of_tokens->{_line_type};
+ next if ( $line_type ne 'CODE' );
+ my ( $Kfirst, $Klast ) = @{ $line_of_tokens->{_rK_range} };
+ next if ( !defined($Kfirst) );
+ $line_of_tokens->{_ci_level_0} = $rLL->[$Kfirst]->[_CI_LEVEL_];
+ }
+ }
+
if (DEBUG_SET_CI) {
my @output_lines;
foreach my $KK ( 0 .. $Klimit ) {
$rOpts->{'maximum-unexpected-errors'};
$self->[_rOpts_logfile_] = $rOpts->{'logfile'};
$self->[_rOpts_] = $rOpts;
- $self->[_calculate_ci_] =
- !$rOpts->{'experimental'} || $rOpts->{'experimental'} !~ /\bci\b/;
+
+ # -exp=ci0 and -exp=ci1 turn on the tokenizer ci calculation for testing.
+ # See comments in sub Perl::Tidy::Formatter::set_ci.
+ my $calculate_ci = 0; # current default
+ if ( $rOpts->{'experimental'} && $rOpts->{'experimental'} =~ /\bci(\d+)\b/ )
+ {
+ $calculate_ci = ( $1 == 0 || $1 == 1 );
+ }
+ $self->[_calculate_ci_] = $calculate_ci;
# These vars are used for guessing indentation and must be positive
$self->[_tabsize_] = 8 if ( !$self->[_tabsize_] );
# Package a line of tokens for shipping back to the caller
#---------------------------------------------------------
+ # NOTE: This routine is only called when -exp=ci0 or -exp=ci1 are set
+ # for testing purposes.
+
# Most of the remaining work involves defining the two indentation
# parameters that the formatter needs for each token:
# - $level = structural indentation level and
# Package a line of tokens for shipping back to the caller
#---------------------------------------------------------
- # This version does not compute continuation indentation
- # and instead returns 0 values.
+ # This version does not compute continuation indentation and instead
+ # returns 0 values. The ci values are computed later by the Formatter
+ # in sub set_ci.
my @token_type = (); # stack of output token types
my @block_type = (); # stack of output code block types