git-commit-vandalism/t/chainlint
Eric Sunshine 73c768dae9 chainlint: annotate original test definition rather than token stream
When chainlint detects problems in a test, such as a broken &&-chain, it
prints out the test with "?!FOO?!" annotations inserted at each problem
location. However, rather than annotating the original test definition,
it instead dumps out a parsed token representation of the test. Since it
lacks comments, indentations, here-doc bodies, and so forth, this
tokenized representation can be difficult for the test author to digest
and relate back to the original test definition.

However, now that each parsed token carries positional information, the
location of a detected problem can be pinpointed precisely in the
original test definition. Therefore, take advantage of this information
to annotate the test definition itself rather than annotating the parsed
token stream, thus making it easier for a test author to relate a
problem back to the source.

Maintaining the positional meta-information associated with each
detected problem requires a slight change in how the problems are
managed internally. In particular, shell syntax such as:

    msg="total: $(cd data; wc -w *.txt) words"

requires the lexical analyzer to recursively invoke the parser in order
to detect problems within the $(...) expression inside the double-quoted
string. In this case, the recursive parse context will detect the broken
&&-chain between the `cd` and `wc` commands, returning the token stream:

    cd data ; ?!AMP?! wc -w *.txt

However, the parent parse context will see everything inside the
double-quotes as a single string token:

    "total: $(cd data ; ?!AMP?! wc -w *.txt) words"

losing whatever positional information was attached to the ";" token
where the problem was detected.

One way to preserve the positional information of a detected problem in
a recursive parse context within a string would be to attach the
positional information to the annotation textually; for instance:

    "total: $(cd data ; ?!AMP:21:22?! wc -w *.txt) words"

and then extract the positional information when annotating the original
test definition.

However, a cleaner and much simpler approach is to maintain the list of
detected problems separately rather than embedding the problems as
annotations directly in the parsed token stream. Not only does this
ensure that positional information within recursive parse contexts is
not lost, but it keeps the token stream free from non-token pollution,
which may simplify implementation of validations added in the future
since they won't have to handle non-token "?!FOO!?" items specially.

Finally, the chainlint self-test "expect" files need a few mechanical
adjustments now that the original test definitions are emitted rather
than the parsed token stream. In particular, the following items missing
from the historic parsed-token output are now preserved verbatim:

    * indentation (and whitespace, in general)

    * comments

    * here-doc bodies

    * here-doc tag quoting (i.e. "\EOF")

    * line-splices (i.e. "\" at the end of a line)

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-08 15:10:49 -05:00
..
arithmetic-expansion.expect
arithmetic-expansion.test
bash-array.expect
bash-array.test
blank-line-before-esac.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
blank-line-before-esac.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
blank-line.expect
blank-line.test
block-comment.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
block-comment.test
block.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
block.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
broken-chain.expect
broken-chain.test
case-comment.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
case-comment.test
case.expect
case.test
chain-break-background.expect chainlint.pl: don't require & background command to end with && 2022-09-01 10:07:40 -07:00
chain-break-background.test chainlint.pl: don't require & background command to end with && 2022-09-01 10:07:40 -07:00
chain-break-continue.expect
chain-break-continue.test
chain-break-false.expect chainlint.pl: don't flag broken &&-chain if failure indicated explicitly 2022-09-01 10:07:41 -07:00
chain-break-false.test chainlint.pl: don't flag broken &&-chain if failure indicated explicitly 2022-09-01 10:07:41 -07:00
chain-break-return-exit.expect chainlint.pl: don't flag broken &&-chain if failure indicated explicitly 2022-09-01 10:07:41 -07:00
chain-break-return-exit.test chainlint.pl: don't flag broken &&-chain if failure indicated explicitly 2022-09-01 10:07:41 -07:00
chain-break-status.expect chainlint.pl: don't flag broken &&-chain if $? handled explicitly 2022-09-01 10:07:41 -07:00
chain-break-status.test chainlint.pl: don't flag broken &&-chain if $? handled explicitly 2022-09-01 10:07:41 -07:00
chained-block.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
chained-block.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
chained-subshell.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
chained-subshell.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
close-nested-and-parent-together.expect
close-nested-and-parent-together.test
close-subshell.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
close-subshell.test
command-substitution-subsubshell.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
command-substitution-subsubshell.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
command-substitution.expect
command-substitution.test
comment.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
comment.test
complex-if-in-cuddled-loop.expect chainlint.pl: complain about loops lacking explicit failure handling 2022-09-01 10:07:41 -07:00
complex-if-in-cuddled-loop.test
cuddled-if-then-else.expect
cuddled-if-then-else.test
cuddled-loop.expect
cuddled-loop.test
cuddled.expect
cuddled.test
double-here-doc.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
double-here-doc.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
dqstring-line-splice.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
dqstring-line-splice.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
dqstring-no-interpolate.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
dqstring-no-interpolate.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
empty-here-doc.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
empty-here-doc.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
exclamation.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
exclamation.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
exit-loop.expect
exit-loop.test
exit-subshell.expect
exit-subshell.test
for-loop-abbreviated.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
for-loop-abbreviated.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
for-loop.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
for-loop.test
function.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
function.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
here-doc-close-subshell.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
here-doc-close-subshell.test
here-doc-indent-operator.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
here-doc-indent-operator.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
here-doc-multi-line-command-subst.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
here-doc-multi-line-command-subst.test
here-doc-multi-line-string.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
here-doc-multi-line-string.test
here-doc.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
here-doc.test
if-condition-split.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
if-condition-split.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
if-in-loop.expect chainlint.pl: don't flag broken &&-chain if failure indicated explicitly 2022-09-01 10:07:41 -07:00
if-in-loop.test chainlint.pl: don't flag broken &&-chain if failure indicated explicitly 2022-09-01 10:07:41 -07:00
if-then-else.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
if-then-else.test
incomplete-line.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
incomplete-line.test
inline-comment.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
inline-comment.test
loop-detect-failure.expect chainlint.pl: complain about loops lacking explicit failure handling 2022-09-01 10:07:41 -07:00
loop-detect-failure.test chainlint.pl: complain about loops lacking explicit failure handling 2022-09-01 10:07:41 -07:00
loop-detect-status.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
loop-detect-status.test chainlint.pl: complain about loops lacking explicit failure handling 2022-09-01 10:07:41 -07:00
loop-in-if.expect chainlint.pl: complain about loops lacking explicit failure handling 2022-09-01 10:07:41 -07:00
loop-in-if.test
loop-upstream-pipe.expect chainlint.pl: allow || echo to signal failure upstream of a pipe 2022-09-01 10:07:41 -07:00
loop-upstream-pipe.test chainlint.pl: allow || echo to signal failure upstream of a pipe 2022-09-01 10:07:41 -07:00
multi-line-nested-command-substitution.expect
multi-line-nested-command-substitution.test
multi-line-string.expect
multi-line-string.test
negated-one-liner.expect
negated-one-liner.test
nested-cuddled-subshell.expect
nested-cuddled-subshell.test
nested-here-doc.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
nested-here-doc.test
nested-loop-detect-failure.expect chainlint.pl: complain about loops lacking explicit failure handling 2022-09-01 10:07:41 -07:00
nested-loop-detect-failure.test chainlint.pl: complain about loops lacking explicit failure handling 2022-09-01 10:07:41 -07:00
nested-subshell-comment.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
nested-subshell-comment.test
nested-subshell.expect
nested-subshell.test
not-heredoc.expect
not-heredoc.test
one-liner-for-loop.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
one-liner-for-loop.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
one-liner.expect
one-liner.test
p4-filespec.expect
p4-filespec.test
pipe.expect
pipe.test
return-loop.expect
return-loop.test
semicolon.expect chainlint.pl: complain about loops lacking explicit failure handling 2022-09-01 10:07:41 -07:00
semicolon.test
sqstring-in-sqstring.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
sqstring-in-sqstring.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
subshell-here-doc.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
subshell-here-doc.test
subshell-one-liner.expect
subshell-one-liner.test
t7900-subtree.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
t7900-subtree.test
token-pasting.expect t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
token-pasting.test t/chainlint: add more chainlint.pl self-tests 2022-09-01 10:07:41 -07:00
while-loop.expect chainlint: annotate original test definition rather than token stream 2022-11-08 15:10:49 -05:00
while-loop.test