Skip to content

Commit a4a5f28

Browse files
sunshinecogitster
authored andcommitted
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 <[email protected]> Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 03763e6 commit a4a5f28

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

t/chainlint.pl

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ sub swallow_heredocs {
174174
$$b =~ /(?:\G|\n)$indent\Q$$tag[0]\E(?:\n|\z)/gc;
175175
if (pos($$b) > $start) {
176176
my $body = substr($$b, $start, pos($$b) - $start);
177+
$self->{parser}->{heredocs}->{$$tag[0]} = {
178+
content => substr($body, 0, length($body) - length($&)),
179+
start_line => $self->{lineno},
180+
};
177181
$self->{lineno} += () = $body =~ /\n/sg;
178182
next;
179183
}
@@ -232,7 +236,8 @@ sub new {
232236
my $self = bless {
233237
buff => [],
234238
stop => [],
235-
output => []
239+
output => [],
240+
heredocs => {},
236241
} => $class;
237242
$self->{lexer} = Lexer->new($self, $s);
238243
return $self;
@@ -616,14 +621,21 @@ sub unwrap {
616621

617622
sub check_test {
618623
my $self = shift @_;
619-
my ($title, $body) = map(unwrap, @_);
624+
my $title = unwrap(shift @_);
625+
my $body = shift @_;
626+
my $lineno = $body->[3];
627+
$body = unwrap($body);
628+
if ($body eq '-') {
629+
my $herebody = shift @_;
630+
$body = $herebody->{content};
631+
$lineno = $herebody->{start_line};
632+
}
620633
$self->{ntests}++;
621634
my $parser = TestParser->new(\$body);
622635
my @tokens = $parser->parse();
623636
my $problems = $parser->{problems};
624637
return unless $emit_all || @$problems;
625638
my $c = main::fd_colors(1);
626-
my $lineno = $_[1]->[3];
627639
my $start = 0;
628640
my $checked = '';
629641
for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) {
@@ -649,8 +661,13 @@ sub parse_cmd {
649661
return @tokens unless @tokens && $tokens[0]->[0] =~ /^test_expect_(?:success|failure)$/;
650662
my $n = $#tokens;
651663
$n-- while $n >= 0 && $tokens[$n]->[0] =~ /^(?:[;&\n|]|&&|\|\|)$/;
652-
$self->check_test($tokens[1], $tokens[2]) if $n == 2; # title body
653-
$self->check_test($tokens[2], $tokens[3]) if $n > 2; # prereq title body
664+
my $herebody;
665+
if ($n >= 2 && $tokens[$n-1]->[0] eq '-' && $tokens[$n]->[0] =~ /^<<-?(.+)$/) {
666+
$herebody = $self->{heredocs}->{$1};
667+
$n--;
668+
}
669+
$self->check_test($tokens[1], $tokens[2], $herebody) if $n == 2; # title body
670+
$self->check_test($tokens[2], $tokens[3], $herebody) if $n > 2; # prereq title body
654671
return @tokens;
655672
}
656673

0 commit comments

Comments
 (0)