chainlint.pl: recognize test bodies defined via heredoc
In order to check tests for semantic problems, chainlint.pl scans test scripts, looking for tests defined as: test_expect_success [prereq] title ' body ' where `body` is a single string which is then treated as a standalone chunk of code and "linted" to detect semantic issues. (The same happens for `test_expect_failure` definitions.) The introduction of test definitions in which the test body is instead presented via a heredoc rather than as a single string creates a blind spot in the linting process since such invocations are not recognized by chainlint.pl. Prepare for this new style by also recognizing tests defined as: test_expect_success [prereq] title - <<\EOT body EOT A minor complication is that chainlint.pl has never considered heredoc bodies significant since it doesn't scan them for semantic problems, thus it has always simply thrown them away. However, with the new `test_expect_success` calling sequence, heredoc bodies become meaningful, thus need to be captured. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
parent
03763e68fb
commit
a4a5f282f5
|
@ -174,6 +174,10 @@ sub swallow_heredocs {
|
|||
$$b =~ /(?:\G|\n)$indent\Q$$tag[0]\E(?:\n|\z)/gc;
|
||||
if (pos($$b) > $start) {
|
||||
my $body = substr($$b, $start, pos($$b) - $start);
|
||||
$self->{parser}->{heredocs}->{$$tag[0]} = {
|
||||
content => substr($body, 0, length($body) - length($&)),
|
||||
start_line => $self->{lineno},
|
||||
};
|
||||
$self->{lineno} += () = $body =~ /\n/sg;
|
||||
next;
|
||||
}
|
||||
|
@ -232,7 +236,8 @@ sub new {
|
|||
my $self = bless {
|
||||
buff => [],
|
||||
stop => [],
|
||||
output => []
|
||||
output => [],
|
||||
heredocs => {},
|
||||
} => $class;
|
||||
$self->{lexer} = Lexer->new($self, $s);
|
||||
return $self;
|
||||
|
@ -616,14 +621,21 @@ sub unwrap {
|
|||
|
||||
sub check_test {
|
||||
my $self = shift @_;
|
||||
my ($title, $body) = map(unwrap, @_);
|
||||
my $title = unwrap(shift @_);
|
||||
my $body = shift @_;
|
||||
my $lineno = $body->[3];
|
||||
$body = unwrap($body);
|
||||
if ($body eq '-') {
|
||||
my $herebody = shift @_;
|
||||
$body = $herebody->{content};
|
||||
$lineno = $herebody->{start_line};
|
||||
}
|
||||
$self->{ntests}++;
|
||||
my $parser = TestParser->new(\$body);
|
||||
my @tokens = $parser->parse();
|
||||
my $problems = $parser->{problems};
|
||||
return unless $emit_all || @$problems;
|
||||
my $c = main::fd_colors(1);
|
||||
my $lineno = $_[1]->[3];
|
||||
my $start = 0;
|
||||
my $checked = '';
|
||||
for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) {
|
||||
|
@ -649,8 +661,13 @@ sub parse_cmd {
|
|||
return @tokens unless @tokens && $tokens[0]->[0] =~ /^test_expect_(?:success|failure)$/;
|
||||
my $n = $#tokens;
|
||||
$n-- while $n >= 0 && $tokens[$n]->[0] =~ /^(?:[;&\n|]|&&|\|\|)$/;
|
||||
$self->check_test($tokens[1], $tokens[2]) if $n == 2; # title body
|
||||
$self->check_test($tokens[2], $tokens[3]) if $n > 2; # prereq title body
|
||||
my $herebody;
|
||||
if ($n >= 2 && $tokens[$n-1]->[0] eq '-' && $tokens[$n]->[0] =~ /^<<-?(.+)$/) {
|
||||
$herebody = $self->{heredocs}->{$1};
|
||||
$n--;
|
||||
}
|
||||
$self->check_test($tokens[1], $tokens[2], $herebody) if $n == 2; # title body
|
||||
$self->check_test($tokens[2], $tokens[3], $herebody) if $n > 2; # prereq title body
|
||||
return @tokens;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue