From 851f47dc07daad1bd89dee1f725a2fc0ba1deefa Mon Sep 17 00:00:00 2001 From: Steve Hancock Date: Sat, 4 Nov 2023 19:13:14 -0700 Subject: [PATCH] add integer option range checks before processing Previously, integer ranges were checked and fixed after processing started. --- CHANGES.md | 15 + bin/perltidy | 20 ++ dev-bin/perltidy_random_setup.pl | 58 +++- dev-bin/run_convergence_tests.pl | 4 +- dev-bin/run_convergence_tests.pl.expect | 1 - lib/Perl/Tidy.pm | 393 +++++++++++++++++++----- lib/Perl/Tidy/Formatter.pm | 3 +- lib/Perl/Tidy/Tokenizer.pm | 12 +- 8 files changed, 410 insertions(+), 96 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5ae7af23..e31050c6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,21 @@ ## 2023 09 12.04 + - All parameters taking integer values are now checked for + out-of-range values before processing starts. When a + minimum or maximum range is exceeded, the new default + behavior is to write a warning message, reset the + value to its default setting, and continue. If this default + behavior causes a problem, it can be changed with the new + parameter B<--integer-range-check=n>, or B<-irc=n>, as follows: + + n=0 skip check completely (for stress-testing perltidy only) + n=1 reset bad values to defaults but do not issue a warning + n=2 reset bad values to defaults and issue a warning [DEFAULT] + n=3 stop immediately if any values are out of bounds + + The settings n=0 and n=1 are mainly useful for testing purposes. + - The --dump-block-summary (-dbs) option now includes the number of sub args in the 'type' column. For example, 'sub(9)' indicates a sub with 9 args. Subs whose arg count cannot easily be determined are diff --git a/bin/perltidy b/bin/perltidy index 0bf970f5..54ec503f 100755 --- a/bin/perltidy +++ b/bin/perltidy @@ -511,6 +511,8 @@ produce one tab for each indentation level and and one for each continuation indentation level. You may want to coordinate the value of B with what your display software assumes for the spacing of a tab. +The default is not to use this, which can also be indicated using B<-et=0>. + =item B<-t>, B<--tabs> This flag causes one leading tab character to be inserted for each level @@ -5294,6 +5296,8 @@ string. B<--dump-defaults> or B<-ddf> will write the default option set to standard output and quit +B<--dump-integer-option-range> or B<-dior> will write a list of comma-separated values. Each line contains the name of an integer option along with its minimum, maximum, and default values. + B<--dump-profile> or B<-dpro> will write the name of the current configuration file and its contents to standard output and quit. @@ -5511,6 +5515,22 @@ this might cause problems if C is active. There is no way to override these rules. +=item B + +Many of the input parameters take integer values. Before processing +begins, a check is made to see if any of these integer parameters exceed +their valid ranges. The default behavior when a range is exceeded is to +write a warning message and reset the value to its default setting. This +default behavior can be changed with the parameter +B<--integer-range-check=n>, or B<-irc=n>, as follows: + + n=0 skip check completely (for stress-testing perltidy only) + n=1 reset bad values to defaults but do not issue a warning + n=2 reset bad values to defaults and issue warning [DEFAULT] + n=3 stop if any values are out of bounds + +The values B and B are mainly useful for testing purposes. + =back =head1 HTML OPTIONS diff --git a/dev-bin/perltidy_random_setup.pl b/dev-bin/perltidy_random_setup.pl index a3d0bb32..b326b335 100755 --- a/dev-bin/perltidy_random_setup.pl +++ b/dev-bin/perltidy_random_setup.pl @@ -663,6 +663,7 @@ sub get_num { # - to make 20 random profiles my @parameters; + my $rinteger_option_range; sub get_parameters { @@ -683,6 +684,44 @@ sub get_num { return \@parameters; } + sub get_integer_option_range { + + # get integer ranges + use File::Temp qw(tempfile); + my ( $fout, $tmpnam ) = File::Temp::tempfile(); + if ( !$fout ) { die "cannot get tempfile\n" } + my %integer_option_range; + system "perltidy --dump-integer-option-range>$tmpnam"; + open( IN, "<", $tmpnam ) || die "cannot open $tmpnam: $!\n"; + while ( my $line = ) { + next if $line =~ /#/; + chomp $line; + $line =~ s/\s+//g; + my ( $opt, $min, $max, $default ) = split /,/, $line; + foreach ( $min, $max, $default ) { + if ( $_ eq 'undef' ) { $_ = undef } + } + $integer_option_range{$opt} = [ $min, $max, $default ]; + } + close IN; + unlink $tmpnam if ( -e $tmpnam ); + return \%integer_option_range; + } + + sub dump_integer_option_range { + my ($rinteger_option_range) = @_; + print {*STDOUT} "Option, min, max, default\n"; + foreach my $key ( sort keys %{$rinteger_option_range} ) { + my ( $min, $max, $default ) = @{ $rinteger_option_range->{$key} }; + foreach ( $min, $max, $default ) { + $_ = 'undef' unless defined($_); + } + print {*STDOUT} "$key, $min, $max, $default\n"; + } + return; + } ## end sub dump_integer_option-range + + BEGIN { # Here is a static list of all parameters current as of v.20200907 @@ -991,8 +1030,10 @@ sub get_num { @parameters = @{$rparameters_current}; print STDERR "Updating perltidy parameters....\n"; } - } + $rinteger_option_range = get_integer_option_range(); + + } sub make_profiles { my $nfiles_old = @{$rprofiles}; my $case = 0; @@ -1363,6 +1404,21 @@ EOM $line = "--$name=$string"; } elsif ( $flag eq '=i' ) { + + # Override old options with new integer options + if ( defined($rinteger_option_range) ) { + my $irange = $rinteger_option_range->{$name}; + if ( defined($irange) ) { + my ( $min, $max, $def ) = @{$irange}; + if ( !defined($min) ) { $min = 0 } + if ( !defined($max) ) { + if ( defined($rrange) ) { $max = $rrange->[1] } + if ( !defined($max) ) { $max = 100; } + } + $rrange = [ $min, $max ]; + } + } + my $int; if ( !$rrange ) { $rrange = [ 0, 100 ]; diff --git a/dev-bin/run_convergence_tests.pl b/dev-bin/run_convergence_tests.pl index ed1d5f09..471243c7 100755 --- a/dev-bin/run_convergence_tests.pl +++ b/dev-bin/run_convergence_tests.pl @@ -368,11 +368,13 @@ sub run_test_cases { my @output_history; for ( my $iteration = 1 ; $iteration <= $iteration_max ; $iteration++ ) { + # FIXME: remove the -irc flag below when several test cases + # are corrected to avoid out-of-bounds integer flags my $err = Perl::Tidy::perltidy( source => \$source, destination => \$output, perltidyrc => \$params, - argv => '', # don't let perltidy look at my @ARGV + argv => '-irc=1', # no warnings messages on bad integers stderr => \$stderr_string, errorfile => \$errorfile_string, # not used when -se flag is set ); diff --git a/dev-bin/run_convergence_tests.pl.expect b/dev-bin/run_convergence_tests.pl.expect index fbcd4a4f..ec324363 100644 --- a/dev-bin/run_convergence_tests.pl.expect +++ b/dev-bin/run_convergence_tests.pl.expect @@ -9453,7 +9453,6 @@ my%where= my %hash= (Four => '4', Five => '5', Six => '6') ; - my %hash= (Four => '4', Five => '5', Six => '6') ; diff --git a/lib/Perl/Tidy.pm b/lib/Perl/Tidy.pm index a97470e1..53d3683a 100644 --- a/lib/Perl/Tidy.pm +++ b/lib/Perl/Tidy.pm @@ -836,7 +836,7 @@ EOM # get command line options #------------------------- my ( $rOpts, $config_file, $rraw_options, $roption_string, - $rexpansion, $roption_category, $roption_range ) + $rexpansion, $roption_category, $roption_range, $rinteger_option_range ) = process_command_line( $perltidyrc_stream, $is_Windows, $Windows_type, $rpending_complaint, $dump_options_type, @@ -923,8 +923,15 @@ EOM #---------------------------------------- # check parameters and their interactions #---------------------------------------- - $self->check_options( $is_Windows, $Windows_type, $rpending_complaint, - $num_files ); + $self->check_options( + + $is_Windows, + $Windows_type, + $rpending_complaint, + $num_files, + $rinteger_option_range + + ); if ($user_formatter) { $rOpts->{'format'} = 'user'; @@ -3286,6 +3293,7 @@ sub generate_options { my %option_category = (); my %option_range = (); my $rexpansion = \%expansion; + my %integer_option_range; # names of categories in manual # leading integers will allow sorting @@ -3654,6 +3662,7 @@ sub generate_options { $add_option->( 'dump-block-types', 'dbt', '=s' ); $add_option->( 'dump-cuddled-block-list', 'dcbl', '!' ); $add_option->( 'dump-defaults', 'ddf', '!' ); + $add_option->( 'dump-integer-option-range', 'dior', '!' ); $add_option->( 'dump-long-names', 'dln', '!' ); $add_option->( 'dump-options', 'dop', '!' ); $add_option->( 'dump-profile', 'dpro', '!' ); @@ -3673,6 +3682,7 @@ sub generate_options { $add_option->( 'maximum-file-size-mb', 'maxfs', '=i' ); $add_option->( 'maximum-level-errors', 'maxle', '=i' ); $add_option->( 'maximum-unexpected-errors', 'maxue', '=i' ); + $add_option->( 'integer-range-check', 'irc', '=i' ); #--------------------------------------------------------------------- @@ -3701,60 +3711,6 @@ sub generate_options { } } - #--------------------------------------- - # Assign valid ranges to certain options - #--------------------------------------- - # In the future, these may be used to make preliminary checks - # hash keys are long names - # If key or value is undefined: - # strings may have any value - # integer ranges are >=0 - # If value is defined: - # value is [qw(any valid words)] for strings - # value is [min, max] for integers - # if min is undefined, there is no lower limit - # if max is undefined, there is no upper limit - # Parameters not listed here have defaults - %option_range = ( - 'format' => [ 'tidy', 'html', 'user' ], - 'output-line-ending' => [ 'dos', 'win', 'mac', 'unix' ], - 'space-backslash-quote' => [ 0, 2 ], - 'block-brace-tightness' => [ 0, 2 ], - 'keyword-paren-inner-tightness' => [ 0, 2 ], - 'brace-tightness' => [ 0, 2 ], - 'paren-tightness' => [ 0, 2 ], - 'square-bracket-tightness' => [ 0, 2 ], - - 'block-brace-vertical-tightness' => [ 0, 2 ], - 'brace-follower-vertical-tightness' => [ 0, 2 ], - 'brace-vertical-tightness' => [ 0, 2 ], - 'brace-vertical-tightness-closing' => [ 0, 2 ], - 'paren-vertical-tightness' => [ 0, 2 ], - 'paren-vertical-tightness-closing' => [ 0, 2 ], - 'square-bracket-vertical-tightness' => [ 0, 2 ], - 'square-bracket-vertical-tightness-closing' => [ 0, 2 ], - 'vertical-tightness' => [ 0, 2 ], - 'vertical-tightness-closing' => [ 0, 2 ], - - 'closing-brace-indentation' => [ 0, 3 ], - 'closing-paren-indentation' => [ 0, 3 ], - 'closing-square-bracket-indentation' => [ 0, 3 ], - 'closing-token-indentation' => [ 0, 3 ], - - 'closing-side-comment-else-flag' => [ 0, 2 ], - 'comma-arrow-breakpoints' => [ 0, 5 ], - - 'keyword-group-blanks-before' => [ 0, 2 ], - 'keyword-group-blanks-after' => [ 0, 2 ], - - 'space-prototype-paren' => [ 0, 2 ], - 'space-signature-paren' => [ 0, 2 ], - 'break-after-labels' => [ 0, 2 ], - ); - - # Note: we could actually allow negative ci if someone really wants it: - # $option_range{'continuation-indentation'} = [ undef, undef ]; - #------------------------------------------------------------------ # DEFAULTS: Assign default values to the above options here, except # for 'outfile' and 'help'. @@ -3818,6 +3774,7 @@ sub generate_options { hanging-side-comments indent-block-comments indent-columns=4 + integer-range-check=2 iterations=1 keep-old-blank-lines=1 keyword-paren-inner-tightness=1 @@ -3877,11 +3834,217 @@ sub generate_options { format-skipping default-tabsize=8 + whitespace-cycle=0 + entab-leading-whitespace=0 + blank-lines-before-closing-block=0 + blank-lines-after-opening-block=0 + pod2html html-table-of-contents html-entities ); + #--------------------------------------- + # Assign valid ranges to certain options + #--------------------------------------- + # In the future, these may be used to make preliminary checks + # hash keys are long names + # If key or value is undefined: + # strings may have any value + # integer ranges are >=0 + # If value is defined: + # value is [qw(any valid words)] for strings + # value is [min, max] for integers + # if min is undefined, there is no lower limit + # if max is undefined, there is no upper limit + # Parameters not listed here have defaults + %option_range = ( + 'format' => [ 'tidy', 'html', 'user' ], + 'output-line-ending' => [ 'dos', 'win', 'mac', 'unix' ], + 'space-backslash-quote' => [ 0, 2 ], + 'block-brace-tightness' => [ 0, 2 ], + 'keyword-paren-inner-tightness' => [ 0, 2 ], + 'brace-tightness' => [ 0, 2 ], + 'paren-tightness' => [ 0, 2 ], + 'square-bracket-tightness' => [ 0, 2 ], + + 'block-brace-vertical-tightness' => [ 0, 2 ], + 'brace-follower-vertical-tightness' => [ 0, 2 ], + 'brace-vertical-tightness' => [ 0, 2 ], + 'brace-vertical-tightness-closing' => [ 0, 3 ], + 'paren-vertical-tightness' => [ 0, 2 ], + 'paren-vertical-tightness-closing' => [ 0, 3 ], + 'square-bracket-vertical-tightness' => [ 0, 2 ], + 'square-bracket-vertical-tightness-closing' => [ 0, 3 ], + 'vertical-tightness' => [ 0, 2 ], + 'vertical-tightness-closing' => [ 0, 3 ], + + 'closing-brace-indentation' => [ 0, 3 ], + 'closing-paren-indentation' => [ 0, 3 ], + 'closing-square-bracket-indentation' => [ 0, 3 ], + 'closing-token-indentation' => [ 0, 3 ], + + 'closing-side-comment-else-flag' => [ 0, 2 ], + 'comma-arrow-breakpoints' => [ 0, 5 ], + + 'keyword-group-blanks-before' => [ 0, 2 ], + 'keyword-group-blanks-after' => [ 0, 2 ], + + 'space-prototype-paren' => [ 0, 2 ], + 'space-signature-paren' => [ 0, 2 ], + 'break-after-labels' => [ 0, 2 ], + ); + + # Valid [min,max] ranges of all integer options (type '=i'). This hash is + # replacing %option_range, above, for use by sub 'check_options' + %integer_option_range = ( + 'blank-lines-after-opening-block' => [ 0, undef ], + 'blank-lines-before-closing-block' => [ 0, undef ], + 'blank-lines-before-packages' => [ 0, undef ], + 'blank-lines-before-subs' => [ 0, undef ], + 'block-brace-tightness' => [ 0, 2 ], + 'block-brace-vertical-tightness' => [ 0, 2 ], + 'brace-follower-vertical-tightness' => [ 0, 2 ], + 'brace-tightness' => [ 0, 2 ], + 'brace-vertical-tightness' => [ 0, 2 ], + 'brace-vertical-tightness-closing' => [ 0, 3 ], + 'break-after-labels' => [ 0, 2 ], + 'break-before-hash-brace' => [ 0, 3 ], + 'break-before-hash-brace-and-indent' => [ 0, 2 ], + 'break-before-paren' => [ 0, 3 ], + 'break-before-paren-and-indent' => [ 0, 2 ], + 'break-before-square-bracket' => [ 0, 3 ], + 'break-before-square-bracket-and-indent' => [ 0, 2 ], + 'closing-brace-indentation' => [ 0, 3 ], + 'closing-paren-indentation' => [ 0, 3 ], + 'closing-side-comment-else-flag' => [ 0, 2 ], + 'closing-side-comment-interval' => [ 0, undef ], + 'closing-side-comment-maximum-text' => [ 0, undef ], + 'closing-square-bracket-indentation' => [ 0, 3 ], + 'closing-token-indentation' => [ 0, 3 ], + 'comma-arrow-breakpoints' => [ 0, 5 ], + 'continuation-indentation' => [ 0, undef ], + 'cuddled-break-option' => [ 0, 2 ], + 'default-tabsize' => [ 0, undef ], + 'dump-block-minimum-lines' => [ 0, undef ], + 'entab-leading-whitespace' => [ 0, undef ], + 'fixed-position-side-comment' => [ 0, undef ], + 'indent-columns' => [ 0, undef ], + 'integer-range-check' => [ 0, 3 ], + 'iterations' => [ 0, undef ], + 'keep-old-blank-lines' => [ 0, 2 ], + 'keyword-group-blanks-after' => [ 0, 2 ], + 'keyword-group-blanks-before' => [ 0, 2 ], + 'keyword-group-blanks-repeat-count' => [ 0, undef ], + 'keyword-paren-inner-tightness' => [ 0, 2 ], + 'long-block-line-count' => [ 0, undef ], + 'maximum-consecutive-blank-lines' => [ 0, undef ], + 'maximum-fields-per-table' => [ 0, undef ], + 'maximum-file-size-mb' => [ 0, undef ], + 'maximum-level-errors' => [ 0, undef ], + 'maximum-line-length' => [ 0, undef ], + 'maximum-unexpected-errors' => [ 0, undef ], + 'minimum-space-to-comment' => [ 0, undef ], + 'one-line-block-nesting' => [ 0, 1 ], + 'one-line-block-semicolons' => [ 0, 2 ], + 'paren-tightness' => [ 0, 2 ], + 'paren-vertical-tightness' => [ 0, 2 ], + 'paren-vertical-tightness-closing' => [ 0, 3 ], + 'short-concatenation-item-length' => [ 0, undef ], + 'space-backslash-quote' => [ 0, 2 ], + 'space-prototype-paren' => [ 0, 2 ], + 'space-signature-paren' => [ 0, 2 ], + 'square-bracket-tightness' => [ 0, 2 ], + 'square-bracket-vertical-tightness' => [ 0, 2 ], + 'square-bracket-vertical-tightness-closing' => [ 0, 3 ], + 'starting-indentation-level' => [ 0, undef ], + 'vertical-tightness' => [ 0, 2 ], + 'vertical-tightness-closing' => [ 0, 3 ], + 'whitespace-cycle' => [ 0, undef ], + ); + + # Enter default values into the integer option range table + foreach my $opt (@defaults) { + if ( $opt =~ /^(.*)=(\d+)$/ ) { + my $key = $1; + my $def = $2; + if ( defined( $integer_option_range{$key} ) ) { + $integer_option_range{$key}[2] = $def; + } + } + } + + # Enter special values which have undef as the default. + # Note that cti, vt, and vtc are aliases which are included to work + # around an old problem with msdos (see note in check_options). + foreach my $key ( + qw( + closing-token-indentation + vertical-tightness + vertical-tightness-closing + fixed-position-side-comment + starting-indentation-level + ) + ) + { + if ( defined( $integer_option_range{$key} ) + && @{ $integer_option_range{$key} } < 3 ) + { + $integer_option_range{$key}[2] = undef; + } + } + + # Verify that only integers of type =i are in the above list during + # development. This will guard against spelling errors. + if (DEVEL_MODE) { + my %option_flag; + my $msg = EMPTY_STRING; + foreach my $opt (@option_string) { + my $key = $opt; + my $flag = EMPTY_STRING; + if ( $key =~ /(.*)(!|=.*|:.*)$/ ) { + $key = $1; + $flag = $2; + } + $option_flag{$key} = $flag; + } + + # Be sure all keys of %integer_option_range have option type '=i' + foreach my $opt ( keys %integer_option_range ) { + my $flag = $option_flag{$opt}; + if ( !defined($flag) ) { $flag = EMPTY_STRING } + if ( $flag ne '=i' ) { + + # If this fault occurs, one of the items in the previous hash + # is not type =i, possibly due to incorrect spelling. + $msg .= +"Option '$opt' has an entry in '%integer_option_range' but is not an integer\n"; + } + } + + # Be sure all '=i' options are in %integer_option_range. This is not + # strictly necessary but helps insure that nothing was missed. + foreach my $opt ( keys %option_flag ) { + my $flag = $option_flag{$opt}; + next if ( $flag ne '=i' ); + if ( !defined( $integer_option_range{$opt} ) ) { + $msg .= +"Integer option '$opt' is needs an entry in '%integer_option_range'\n"; + } + } + + # look for integer options without default values + foreach my $opt ( keys %integer_option_range ) { + if ( @{ $integer_option_range{$opt} } < 3 ) { + $msg .= "Integer option '$opt' does not have a default value\n"; + } + } + + if ($msg) { + Fault($msg); + } + } + #----------------------------------------------------------------------- # Define abbreviations which will be expanded into the above primitives. # These may be defined recursively. @@ -4103,10 +4266,8 @@ q(wbb=% + - * / x != == >= <= =~ !~ < > | & = **= += *= &= <<= &&= -= /= |= >>= # Uncomment next line to dump all expansions for debugging: # dump_short_names(\%expansion); - return ( - \@option_string, \@defaults, \%expansion, - \%option_category, \%option_range - ); + return ( \@option_string, \@defaults, \%expansion, \%option_category, + \%option_range, \%integer_option_range, ); } ## end sub generate_options @@ -4171,10 +4332,9 @@ sub _process_command_line { } else { $glc = undef } - my ( - $roption_string, $rdefaults, $rexpansion, - $roption_category, $roption_range - ) = generate_options(); + my ( $roption_string, $rdefaults, $rexpansion, + $roption_category, $roption_range, $rinteger_option_range, ) + = generate_options(); #-------------------------------------------------------------- # set the defaults by passing the above list through GetOptions @@ -4259,6 +4419,10 @@ sub _process_command_line { dump_defaults( @{$rdefaults} ); Exit(0); } + elsif ( $i =~ /^-(dump-integer-option-range|dior)$/ ) { + dump_integer_option_range($rinteger_option_range); + Exit(0); + } elsif ( $i =~ /^-(dump-long-names|dln)$/ ) { dump_long_names( @{$roption_string} ); Exit(0); @@ -4378,6 +4542,7 @@ EOM qw{ dump-cuddled-block-list dump-defaults + dump-integer-option_range dump-long-names dump-options dump-profile @@ -4421,7 +4586,8 @@ EOM } return ( \%Opts, $config_file, \@raw_options, $roption_string, - $rexpansion, $roption_category, $roption_range ); + $rexpansion, $roption_category, $roption_range, + $rinteger_option_range ); } ## end sub _process_command_line sub make_grep_alias_string { @@ -4534,8 +4700,16 @@ sub cleanup_word_list { sub check_options { - my ( $self, $is_Windows, $Windows_type, $rpending_complaint, $num_files ) = - @_; + my ( + $self, + + $is_Windows, + $Windows_type, + $rpending_complaint, + $num_files, + $rinteger_option_range + + ) = @_; # $num_files = number of files to be processed, for error checks @@ -4554,29 +4728,65 @@ sub check_options { EOM } - # do not allow negative --indent-columns - if ( $rOpts->{'indent-columns'} < 0 ) { - $rOpts->{'indent-columns'} = 0; - } - - # negative ci is currently allowed provided that ci+i is not negative - if ( $rOpts->{'continuation-indentation'} < -$rOpts->{'indent-columns'} ) { - $rOpts->{'continuation-indentation'} = -$rOpts->{'indent-columns'}; - } - - my $sil = $rOpts->{'starting-indentation-level'}; - if ( defined($sil) && $sil < 0 ) { - Die(<{'integer-range-check'}; + if ( !defined($integer_range_check) + || $integer_range_check < 0 + || $integer_range_check > 3 ) + { + $integer_range_check = 2; + } + + # Check for integer values out of bounds as follows: + # $integer_range_check= + # 0 => skip check completely (for stress-testing perltidy only) + # 1 => quietly reset bad values to defaults + # 2 => issue warning and reset bad values defaults [DEFAULT] + # 3 => stop if any values are out of bounds + if ($integer_range_check) { + my $Error_message; + foreach my $opt ( keys %{$rinteger_option_range} ) { + my $range = $rinteger_option_range->{$opt}; + next unless defined($range); + my ( $min, $max, $default ) = @{$range}; + + my $val = $rOpts->{$opt}; + if ( defined($min) && defined($val) && $val < $min ) { + $Error_message .= "--$opt=$val but should be >= $min"; + if ( $integer_range_check < 3 ) { + $rOpts->{$opt} = $default; + my $def = defined($default) ? $default : 'undef'; + $Error_message .= "; using default $def"; + } + $Error_message .= "\n"; + } + if ( defined($max) && defined($val) && $val > $max ) { + $Error_message .= "--$opt=$val but should be <= $max"; + if ( $integer_range_check < 3 ) { + $rOpts->{$opt} = $default; + my $def = defined($default) ? $default : 'undef'; + $Error_message .= "; using default $def"; + } + $Error_message .= "\n"; + } + } + if ($Error_message) { + if ( $integer_range_check == 1 ) { + ## no warning + } + elsif ( $integer_range_check == 2 ) { + Warn($Error_message); + } + else { + Die($Error_message); + } + } } - # Since -vt, -vtc, and -cti are abbreviations, but under + # Note that -vt, -vtc, and -cti are abbreviations. But under # msdos, an unquoted input parameter like vtc=1 will be # seen as 2 parameters, vtc and 1, so the abbreviations # won't be seen. Therefore, we will catch them here if # they get through. - if ( defined $rOpts->{'vertical-tightness'} ) { my $vt = $rOpts->{'vertical-tightness'}; $rOpts->{'paren-vertical-tightness'} = $vt; @@ -5514,6 +5724,19 @@ EOM return; } ## end sub dump_long_names +sub dump_integer_option_range { + my ($rinteger_option_range) = @_; + print {*STDOUT} "Option, min, max, default\n"; + foreach my $key ( sort keys %{$rinteger_option_range} ) { + my ( $min, $max, $default ) = @{ $rinteger_option_range->{$key} }; + foreach ( $min, $max, $default ) { + $_ = 'undef' unless defined($_); + } + print {*STDOUT} "$key, $min, $max, $default\n"; + } + return; +} ## end sub dump_integer_option-range + sub dump_defaults { my @defaults = @_; print {*STDOUT} "Default command line options:\n"; diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm index 0b3cbcc3..18d43728 100644 --- a/lib/Perl/Tidy/Formatter.pm +++ b/lib/Perl/Tidy/Formatter.pm @@ -13482,8 +13482,7 @@ sub special_indentation_adjustments { return unless ( @{$rLL} ); # Initialize the adjusted levels to be the structural levels - my @adjusted_levels; - foreach ( @{$rLL} ) { push @adjusted_levels, $_->[_LEVEL_] } + my @adjusted_levels = map { $_->[_LEVEL_] } @{$rLL}; $self->[_radjusted_levels_] = \@adjusted_levels; my $min_starting_level = min(@adjusted_levels); diff --git a/lib/Perl/Tidy/Tokenizer.pm b/lib/Perl/Tidy/Tokenizer.pm index 1d281e65..91a284d1 100644 --- a/lib/Perl/Tidy/Tokenizer.pm +++ b/lib/Perl/Tidy/Tokenizer.pm @@ -5395,12 +5395,11 @@ EOM my $pre_tok = $tok = $rtokens->[$i]; # get the next pre-token my $pre_type = $type = $rtoken_type->[$i]; # and type - # remember the starting index of this token; we will be updating $i - $i_tok = $i; - # re-initialize various flags for the next output token ( + # remember the starting index of this token; we will update $i + $i_tok, $block_type, $container_type, $type_sequence, @@ -5409,6 +5408,7 @@ EOM ) = ( + $i, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING, @@ -5597,9 +5597,9 @@ EOM next; } - # Turn off attribute list on first non-blank, non-bareword. - # Added '#' to fix c038 (later moved above). - $self->[_in_attribute_list_] &&= 0; + # Turn off attribute list on first non-blank, non-bareword, + # and non-comment (added to fix c038) + $self->[_in_attribute_list_] = 0; #------------------------------- # END NODE 4: a string of digits -- 2.39.5