package Perl::Tidy::Tokenizer;
use strict;
use warnings;
-our $VERSION = '20190601';
+our $VERSION = '20200110';
use Perl::Tidy::LineBuffer;
%is_keyword_taking_list
%is_keyword_taking_optional_args
%is_q_qq_qw_qx_qr_s_y_tr_m
+ %is_sub
+ %is_package
};
# possible values of operator_expected()
return;
}
+sub check_options {
+
+ # Check Tokenizer parameters
+ my $rOpts = shift;
+
+ %is_sub = ();
+ $is_sub{'sub'} = 1;
+
+ # Install any aliases to 'sub'
+ if ( $rOpts->{'sub-alias-list'} ) {
+
+ # Note that any 'sub-alias-list' has been preprocessed to
+ # be a trimmed, space-separated list which includes 'sub'
+ # for example, it might be 'sub method fun'
+ my @sub_alias_list = split /\s+/, $rOpts->{'sub-alias-list'};
+ foreach my $word (@sub_alias_list) {
+ $is_sub{$word} = 1;
+ }
+ }
+ return;
+}
+
sub new {
my ( $class, @args ) = @_;
}
}
+sub get_unexpected_error_count {
+ my ($self) = shift;
+ return $self->{_unexpected_error_count};
+}
+
# interface to Perl::Tidy::Diagnostics routines
sub write_diagnostics {
my $msg = shift;
{
$is_pattern = 0;
}
+
+ # 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 ) {
+ # 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,
@_ = qw(use require);
@is_use_require{@_} = (1) x scalar(@_);
- my %is_sub_package;
- @_ = qw(sub package);
- @is_sub_package{@_} = (1) x scalar(@_);
-
# This hash holds the hash key in $tokenizer_self for these keywords:
my %is_format_END_DATA = (
'format' => '_in_format',
# but do not start on blanks and comments
if ( $id_scan_state && $pre_type !~ /[b#]/ ) {
- if ( $id_scan_state =~ /^(sub|package)/ ) {
+ if ( $is_sub{$id_scan_state} || $is_package{$id_scan_state} ) {
scan_id();
}
else {
elsif (
( $next_nonblank_token eq ':' )
&& ( $rtokens->[ $i_next + 1 ] ne ':' )
- && ( $i_next <= $max_token_index ) # colon on same line
+ && ( $i_next <= $max_token_index ) # colon on same line
&& label_ok()
)
{
}
# 'sub' || 'package'
- elsif ( $is_sub_package{$tok_kw} ) {
+ elsif ( $is_sub{$tok_kw} || $is_package{$tok_kw} ) {
error_if_expecting_OPERATOR()
if ( $expecting == OPERATOR );
scan_id();
if ( $type eq ';' && $tok =~ /\w/ ) { $fix_type = 'k' }
# output anonymous 'sub' as keyword
- if ( $type eq 't' && $tok eq 'sub' ) { $fix_type = 'k' }
+ if ( $type eq 't' && $is_sub{$tok} ) { $fix_type = 'k' }
# -----------------------------------------------------------------
# could change the interpretation of the statement.
else {
if ( $tok =~ /^([x\/\+\-\*\%\&\.\?\<]|\>\>)$/ ) {
- complain("operator in print statement not recommended\n");
+
+ # Do not complain in 'use' statements, which have special syntax.
+ # For example, from RT#130344:
+ # use lib $FindBin::Bin . '/lib';
+ if ( $statement_type ne 'use' ) {
+ complain("operator in print statement not recommended\n");
+ }
$op_expected = OPERATOR;
}
}
return $last_nonblank_token;
}
+ # or a sub alias
+ elsif (( $last_nonblank_type eq 'i' || $last_nonblank_type eq 't' )
+ && ( $is_sub{$last_nonblank_token} ) )
+ {
+ return 'sub';
+ }
+
elsif ( $statement_type =~ /^(sub|package)\b/ ) {
return $statement_type;
}
write_on_underline( $underline, $pos_prev - $offset, '-' x $num );
$trailer = " (previous token underlined)";
}
+ $underline =~ s/\s+$//;
warning( $numbered_line . "\n" );
warning( $underline . "\n" );
warning( $msg . $trailer . "\n" );
# handle non-blank line; identifier, if any, must follow
unless ($blank_line) {
- if ( $id_scan_state eq 'sub' ) {
+ if ( $is_sub{$id_scan_state} ) {
( $i, $tok, $type, $id_scan_state ) = do_scan_sub(
$input_line, $i, $i_beg,
$tok, $type, $rtokens,
);
}
- elsif ( $id_scan_state eq 'package' ) {
+ elsif ( $is_package{$id_scan_state} ) {
( $i, $tok, $type ) =
do_scan_package( $input_line, $i, $i_beg, $tok, $type, $rtokens,
$rtoken_map, $max_token_index );
$attrs = $2;
# If we also found the sub name on this call then append PROTO.
- # This is not necessary but for compatability with previous
+ # This is not necessary but for compatibility with previous
# versions when the -csc flag is used:
if ( $match && $proto ) {
$tok .= $proto;
$statement_type = $tok;
}
elsif ($next_nonblank_token) { # EOF technically ok
+ $subname = "" unless defined($subname);
warning(
"expecting ':' or ';' or '{' after definition or declaration of sub '$subname' but saw '$next_nonblank_token'\n"
);
@q = qw(q qq qw qx qr s y tr m);
@is_q_qq_qw_qx_qr_s_y_tr_m{@q} = (1) x scalar(@q);
+ @q = qw(sub);
+ @is_sub{@q} = (1) x scalar(@q);
+
+ @q = qw(package);
+ @is_package{@q} = (1) x scalar(@q);
+
# These keywords are handled specially in the tokenizer code:
my @special_keywords = qw(
do