chainlint.sed: drop unnecessary distinction between ?!AMP?! and ?!SEMI?!

>From inception, when chainlint.sed encountered a line using semicolon to separate commands rather than `&&`, it would insert a ?!SEMI?! annotation at the beginning of the line rather ?!AMP?! even though the &&-chain is also broken by the semicolon. Given a line such as: ?!SEMI?! cmd1; cmd2 && the ?!SEMI?! annotation makes it easier to see what the problem is than if the output had been: ?!AMP?! cmd1; cmd2 && which might confuse the test author into thinking that the linter is broken (since the line clearly ends with `&&`). However, now that the ?!AMP?! an ?!SEMI?! annotations are inserted at the point of breakage rather than at the beginning of the line, and taking into account that both represent a broken &&-chain, there is little reason to distinguish between the two. Using ?!AMP?! alone is sufficient to point the test author at the problem. For instance, in: cmd1; ?!AMP?! cmd2 && cmd3 it is clear that the &&-chain is broken between `cmd1` and `cmd2`. Likewise, in: cmd1 && cmd2 ?!AMP?! cmd3 it is clear that the &&-chain is broken between `cmd2` and `cmd3`. Finally, in: cmd1; ?!AMP?! cmd2 ?!AMP?! cmd3 it is clear that the &&-chain is broken between each command. Hence, there is no longer a good reason to make a distinction between a broken &&-chain due to a semicolon and a broken chain due to a missing `&&` at end-of-line. Therefore, drop the ?!SEMI?! annotation and use ?!AMP?! exclusively. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Eric Sunshine committed Dec 13, 2021 at 01:30 UTC 0d7131763e7762dc34c407f32e3c63123001a292
5 files changed +24 -25
t/chainlint.sed
+10 -11
@@ -24,9 +24,9 @@
24 # in order to avoid misinterpreting the ")" in constructs such as "x=$(...)"
25 # and "case $x in *)" as ending the subshell.
26 #
27 -# Lines missing a final "&&" are flagged with "?!AMP?!", and lines which chain
28 -# commands with ";" internally rather than "&&" are flagged "?!SEMI?!". A line
29 -# may be flagged for both violations.
27 +# Lines missing a final "&&" are flagged with "?!AMP?!", as are lines which
28 +# chain commands with ";" internally rather than "&&". A line may be flagged
29 +# for both violations.
30 #
31 # Detection of a missing &&-link in a multi-line subshell is complicated by the
32 # fact that the last statement before the closing ")" must not end with "&&".
@@ -47,9 +47,8 @@
47 # "?!AMP?!" violation is removed from the "bar" line (retrieved from the "hold"
48 # area) since the final statement of a subshell must not end with "&&". The
49 # final line of a subshell may still break the &&-chain by using ";" internally
50 -# to chain commands together rather than "&&", so "?!SEMI?!" is not removed
51 -# from such a line; however, if the line ends with "?!SEMI?!", then the ";" is
52 -# harmless and the annotation is removed.
50 +# to chain commands together rather than "&&", but an internal "?!AMP?!" is
51 +# never removed from a line even though a line-ending "?!AMP?!" might be.
52 #
53 # Care is taken to recognize the last _statement_ of a multi-line subshell, not
54 # necessarily the last textual _line_ within the subshell, since &&-chaining
@@ -127,7 +126,7 @@ b
126 # "&&" (but not ";" in a string)
127 :oneline
128 /;/{
130 - /"[^"]*;[^"]*"/!s/;/; ?!SEMI?!/
129 + /"[^"]*;[^"]*"/!s/;/; ?!AMP?!/
130 }
131 b
132
@@ -231,7 +230,7 @@ s/.*\n//
230 # string and not ";;" in one-liner "case...esac")
231 /;/{
232 /;;/!{
234 - /"[^"]*;[^"]*"/!s/;/; ?!SEMI?!/
233 + /"[^"]*;[^"]*"/!s/;/; ?!AMP?!/
234 }
235 }
236 # line ends with pipe "...|" -- valid; not missing "&&"
@@ -304,7 +303,7 @@ bcase
303 # that line legitimately lacks "&&"
304 :else
305 x
307 -s/\( ?!SEMI?!\)* ?!AMP?!$//
306 +s/\( ?!AMP?!\)* ?!AMP?!$//
307 x
308 bcont
309
@@ -312,7 +311,7 @@ bcont
311 # "suspect" from final contained line since that line legitimately lacks "&&"
312 :done
313 x
315 -s/\( ?!SEMI?!\)* ?!AMP?!$//
314 +s/\( ?!AMP?!\)* ?!AMP?!$//
315 x
316 # is 'done' or 'fi' cuddled with ")" to close subshell?
317 /done.*)/bclose
@@ -355,7 +354,7 @@ bblock
354 # since that line legitimately lacks "&&" and exit subshell loop
355 :clssolo
356 x
358 -s/\( ?!SEMI?!\)* ?!AMP?!$//
357 +s/\( ?!AMP?!\)* ?!AMP?!$//
358 p
359 x
360 s/^/>/
t/chainlint/negated-one-liner.expect
+2 -2
@@ -1,5 +1,5 @@
1 ! (foo && bar) &&
2 ! (foo && bar) >baz &&
3
4 -! (foo; ?!SEMI?! bar) &&
5 -! (foo; ?!SEMI?! bar) >baz
4 +! (foo; ?!AMP?! bar) &&
5 +! (foo; ?!AMP?! bar) >baz
t/chainlint/one-liner.expect
+3 -3
@@ -2,8 +2,8 @@
2 (foo && bar) |
3 (foo && bar) >baz &&
4
5 -(foo; ?!SEMI?! bar) &&
6 -(foo; ?!SEMI?! bar) |
7 -(foo; ?!SEMI?! bar) >baz &&
5 +(foo; ?!AMP?! bar) &&
6 +(foo; ?!AMP?! bar) |
7 +(foo; ?!AMP?! bar) >baz &&
8
9 (foo "bar; baz")
t/chainlint/semicolon.expect
+5 -5
@@ -1,14 +1,14 @@
1 (
2 - cat foo ; ?!SEMI?! echo bar ?!AMP?!
3 - cat foo ; ?!SEMI?! echo bar
2 + cat foo ; ?!AMP?! echo bar ?!AMP?!
3 + cat foo ; ?!AMP?! echo bar
4 >) &&
5 (
6 - cat foo ; ?!SEMI?! echo bar &&
7 - cat foo ; ?!SEMI?! echo bar
6 + cat foo ; ?!AMP?! echo bar &&
7 + cat foo ; ?!AMP?! echo bar
8 >) &&
9 (
10 echo "foo; bar" &&
11 - cat foo; ?!SEMI?! echo bar
11 + cat foo; ?!AMP?! echo bar
12 >) &&
13 (
14 foo;
t/chainlint/subshell-one-liner.expect
+4 -4
@@ -2,13 +2,13 @@
2 (foo && bar) &&
3 (foo && bar) |
4 (foo && bar) >baz &&
5 - (foo; ?!SEMI?! bar) &&
6 - (foo; ?!SEMI?! bar) |
7 - (foo; ?!SEMI?! bar) >baz &&
5 + (foo; ?!AMP?! bar) &&
6 + (foo; ?!AMP?! bar) |
7 + (foo; ?!AMP?! bar) >baz &&
8 (foo || exit 1) &&
9 (foo || exit 1) |
10 (foo || exit 1) >baz &&
11 (foo && bar) ?!AMP?!
12 - (foo && bar; ?!SEMI?! baz) ?!AMP?!
12 + (foo && bar; ?!AMP?! baz) ?!AMP?!
13 foobar
14 >)