Skip to content

Commit e6cc693

Browse files
committed
Merge branch 'es/chainlint-message-updates'
The error messages from the test script checker have been improved. * es/chainlint-message-updates: chainlint: reduce annotation noise-factor chainlint: make error messages self-explanatory chainlint: don't be fooled by "?!...?!" in test body
2 parents 5d55832 + a13ff41 commit e6cc693

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+113
-95
lines changed

t/chainlint.pl

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
# Input arguments are pathnames of shell scripts containing test definitions,
1010
# or globs referencing a collection of scripts. For each problem discovered,
1111
# the pathname of the script containing the test is printed along with the test
12-
# name and the test body with a `?!FOO?!` annotation at the location of each
13-
# detected problem, where "FOO" is a tag such as "AMP" which indicates a broken
14-
# &&-chain. Returns zero if no problems are discovered, otherwise non-zero.
12+
# name and the test body with a `?!LINT: ...?!` annotation at the location of
13+
# each detected problem, where "..." is an explanation of the problem. Returns
14+
# zero if no problems are discovered, otherwise non-zero.
1515

1616
use warnings;
1717
use strict;
@@ -181,7 +181,7 @@ sub swallow_heredocs {
181181
$self->{lineno} += () = $body =~ /\n/sg;
182182
next;
183183
}
184-
push(@{$self->{parser}->{problems}}, ['UNCLOSED-HEREDOC', $tag]);
184+
push(@{$self->{parser}->{problems}}, ['HEREDOC', $tag]);
185185
$$b =~ /(?:\G|\n).*\z/gc; # consume rest of input
186186
my $body = substr($$b, $start, pos($$b) - $start);
187187
$self->{lineno} += () = $body =~ /\n/sg;
@@ -238,6 +238,7 @@ sub new {
238238
stop => [],
239239
output => [],
240240
heredocs => {},
241+
insubshell => 0,
241242
} => $class;
242243
$self->{lexer} = Lexer->new($self, $s);
243244
return $self;
@@ -296,8 +297,11 @@ sub parse_group {
296297

297298
sub parse_subshell {
298299
my $self = shift @_;
299-
return ($self->parse(qr/^\)$/),
300-
$self->expect(')'));
300+
$self->{insubshell}++;
301+
my @tokens = ($self->parse(qr/^\)$/),
302+
$self->expect(')'));
303+
$self->{insubshell}--;
304+
return @tokens;
301305
}
302306

303307
sub parse_case_pattern {
@@ -528,7 +532,7 @@ sub parse_loop_body {
528532
return @tokens if ends_with(\@tokens, [qr/^\|\|$/, "\n", qr/^echo$/, qr/^.+$/]);
529533
# flag missing "return/exit" handling explicit failure in loop body
530534
my $n = find_non_nl(\@tokens);
531-
push(@{$self->{problems}}, ['LOOP', $tokens[$n]]);
535+
push(@{$self->{problems}}, [$self->{insubshell} ? 'LOOPEXIT' : 'LOOPRETURN', $tokens[$n]]);
532536
return @tokens;
533537
}
534538

@@ -587,6 +591,7 @@ sub new {
587591
my $class = shift @_;
588592
my $self = $class->SUPER::new(@_);
589593
$self->{ntests} = 0;
594+
$self->{nerrs} = 0;
590595
return $self;
591596
}
592597

@@ -619,6 +624,15 @@ sub unwrap {
619624
return $s
620625
}
621626

627+
sub format_problem {
628+
local $_ = shift;
629+
/^AMP$/ && return "missing '&&'";
630+
/^LOOPRETURN$/ && return "missing '|| return 1'";
631+
/^LOOPEXIT$/ && return "missing '|| exit 1'";
632+
/^HEREDOC$/ && return 'unclosed heredoc';
633+
die("unrecognized problem type '$_'\n");
634+
}
635+
622636
sub check_test {
623637
my $self = shift @_;
624638
my $title = unwrap(shift @_);
@@ -634,22 +648,26 @@ sub check_test {
634648
my $parser = TestParser->new(\$body);
635649
my @tokens = $parser->parse();
636650
my $problems = $parser->{problems};
651+
$self->{nerrs} += @$problems;
637652
return unless $emit_all || @$problems;
638653
my $c = main::fd_colors(1);
654+
my ($erropen, $errclose) = -t 1 ? ("$c->{rev}$c->{red}", $c->{reset}) : ('?!', '?!');
639655
my $start = 0;
640656
my $checked = '';
641657
for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) {
642658
my ($label, $token) = @$_;
643659
my $pos = $token->[2];
644-
$checked .= substr($body, $start, $pos - $start) . " ?!$label?! ";
660+
my $err = format_problem($label);
661+
$checked .= substr($body, $start, $pos - $start);
662+
$checked .= ' ' unless $checked =~ /\s$/;
663+
$checked .= "${erropen}LINT: $err$errclose";
664+
$checked .= ' ' unless $pos >= length($body) ||
665+
substr($body, $pos, 1) =~ /^\s/;
645666
$start = $pos;
646667
}
647668
$checked .= substr($body, $start);
648669
$checked =~ s/^/$lineno++ . ' '/mge;
649670
$checked =~ s/^\d+ \n//;
650-
$checked =~ s/(\s) \?!/$1?!/mg;
651-
$checked =~ s/\?! (\s)/?!$1/mg;
652-
$checked =~ s/(\?![^?]+\?!)/$c->{rev}$c->{red}$1$c->{reset}/mg;
653671
$checked =~ s/^\d+/$c->{dim}$&$c->{reset}/mg;
654672
$checked .= "\n" unless $checked =~ /\n$/;
655673
push(@{$self->{output}}, "$c->{blue}# chainlint: $title$c->{reset}\n$checked");
@@ -791,9 +809,9 @@ sub check_script {
791809
my $c = fd_colors(1);
792810
my $s = join('', @{$parser->{output}});
793811
$emit->("$c->{bold}$c->{blue}# chainlint: $path$c->{reset}\n" . $s);
794-
$nerrs += () = $s =~ /\?![^?]+\?!/g;
795812
}
796813
$ntests += $parser->{ntests};
814+
$nerrs += $parser->{nerrs};
797815
}
798816
return [$id, $nscripts, $ntests, $nerrs];
799817
}

t/chainlint/arithmetic-expansion.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
5 baz
55
6 ) &&
66
7 (
7-
8 bar=$((42 + 1)) ?!AMP?!
7+
8 bar=$((42 + 1)) ?!LINT: missing '&&'?!
88
9 baz
99
10 )

t/chainlint/block.expect

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
2 (
22
3 foo &&
33
4 {
4-
5 echo a ?!AMP?!
4+
5 echo a ?!LINT: missing '&&'?!
55
6 echo b
66
7 } &&
77
8 bar &&
88
9 {
99
10 echo c
10-
11 } ?!AMP?!
10+
11 } ?!LINT: missing '&&'?!
1111
12 baz
1212
13 ) &&
1313
14
1414
15 {
15-
16 echo a; ?!AMP?! echo b
15+
16 echo a; ?!LINT: missing '&&'?! echo b
1616
17 } &&
17-
18 { echo a; ?!AMP?! echo b; } &&
17+
18 { echo a; ?!LINT: missing '&&'?! echo b; } &&
1818
19
1919
20 {
2020
21 echo "${var}9" &&

t/chainlint/broken-chain.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
2 (
22
3 foo &&
3-
4 bar ?!AMP?!
3+
4 bar ?!LINT: missing '&&'?!
44
5 baz &&
55
6 wop
66
7 )

t/chainlint/case.expect

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
10 case "$x" in
1010
11 x) foo ;;
1111
12 *) bar ;;
12-
13 esac ?!AMP?!
12+
13 esac ?!LINT: missing '&&'?!
1313
14 foobar
1414
15 ) &&
1515
16 (
1616
17 case "$x" in 1) true;; esac &&
17-
18 case "$y" in 2) false;; esac ?!AMP?!
17+
18 case "$y" in 2) false;; esac ?!LINT: missing '&&'?!
1818
19 foobar
1919
20 )

t/chainlint/chain-break-false.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
5 echo failed!
55
6 false
66
7 else
7-
8 echo it went okay ?!AMP?!
7+
8 echo it went okay ?!LINT: missing '&&'?!
88
9 congratulate user
99
10 fi

t/chainlint/chained-block.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
2 echo nobody home && {
2-
3 test the doohicky ?!AMP?!
2+
3 test the doohicky ?!LINT: missing '&&'?!
33
4 right now
44
5 } &&
55
6

t/chainlint/chained-subshell.expect

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
2 mkdir sub && (
22
3 cd sub &&
3-
4 foo the bar ?!AMP?!
3+
4 foo the bar ?!LINT: missing '&&'?!
44
5 nuff said
55
6 ) &&
66
7
77
8 cut "-d " -f actual | (read s1 s2 s3 &&
8-
9 test -f $s1 ?!AMP?!
8+
9 test -f $s1 ?!LINT: missing '&&'?!
99
10 test $(cat $s2) = tree2path1 &&
1010
11 test $(cat $s3) = tree3path1)

t/chainlint/command-substitution.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
5 baz
55
6 ) &&
66
7 (
7-
8 bar=$(gobble blocks) ?!AMP?!
7+
8 bar=$(gobble blocks) ?!LINT: missing '&&'?!
88
9 baz
99
10 )

t/chainlint/complex-if-in-cuddled-loop.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
5 :
55
6 else
66
7 echo >file
7-
8 fi ?!LOOP?!
7+
8 fi ?!LINT: missing '|| exit 1'?!
88
9 done) &&
99
10 test ! -f file

0 commit comments

Comments
 (0)