chainlint.sed: stop throwing away here-doc tags

The purpose of chainlint is to highlight problems it finds in test code
by inserting annotations at the location of each problem. Arbitrarily
eliding bits of the code it is checking is not helpful, yet this is
exactly what chainlint.sed does by cavalierly and unnecessarily dropping
the here-doc operator and tag; i.e. `cat <<TAG` becomes simply `cat` in
the output. This behavior can make it more difficult for the test writer
to align the annotated output of chainlint.sed with the original test
code. Address this by retaining here-doc tags.

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Eric Sunshine 2021-12-13 01:30:57 -05:00 committed by Junio C Hamano
parent 22597af97d
commit 34ba05c296
11 changed files with 35 additions and 29 deletions

View file

@ -62,20 +62,20 @@
# receives similar treatment. # receives similar treatment.
# #
# Swallowing here-docs with arbitrary tags requires a bit of finesse. When a # Swallowing here-docs with arbitrary tags requires a bit of finesse. When a
# line such as "cat <<EOF >out" is seen, the here-doc tag is moved to the front # line such as "cat <<EOF" is seen, the here-doc tag is copied to the front of
# of the line enclosed in angle brackets as a sentinel, giving "<EOF>cat >out". # the line enclosed in angle brackets as a sentinel, giving "<EOF>cat <<EOF".
# As each subsequent line is read, it is appended to the target line and a # As each subsequent line is read, it is appended to the target line and a
# (whitespace-loose) back-reference match /^<(.*)>\n\1$/ is attempted to see if # (whitespace-loose) back-reference match /^<(.*)>\n\1$/ is attempted to see if
# the content inside "<...>" matches the entirety of the newly-read line. For # the content inside "<...>" matches the entirety of the newly-read line. For
# instance, if the next line read is "some data", when concatenated with the # instance, if the next line read is "some data", when concatenated with the
# target line, it becomes "<EOF>cat >out\nsome data", and a match is attempted # target line, it becomes "<EOF>cat <<EOF\nsome data", and a match is attempted
# to see if "EOF" matches "some data". Since it doesn't, the next line is # to see if "EOF" matches "some data". Since it doesn't, the next line is
# attempted. When a line consisting of only "EOF" (and possible whitespace) is # attempted. When a line consisting of only "EOF" (and possible whitespace) is
# encountered, it is appended to the target line giving "<EOF>cat >out\nEOF", # encountered, it is appended to the target line giving "<EOF>cat <<EOF\nEOF",
# in which case the "EOF" inside "<...>" does match the text following the # in which case the "EOF" inside "<...>" does match the text following the
# newline, thus the closing here-doc tag has been found. The closing tag line # newline, thus the closing here-doc tag has been found. The closing tag line
# and the "<...>" prefix on the target line are then discarded, leaving just # and the "<...>" prefix on the target line are then discarded, leaving just
# the target line "cat >out". # the target line "cat <<EOF".
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# incomplete line -- slurp up next line # incomplete line -- slurp up next line
@ -90,8 +90,7 @@
# command to which it was attached) # command to which it was attached)
/<<-*[ ]*[\\'"]*[A-Za-z0-9_]/ { /<<-*[ ]*[\\'"]*[A-Za-z0-9_]/ {
/"[^"]*<<[^"]*"/bnotdoc /"[^"]*<<[^"]*"/bnotdoc
s/^\(.*\)<<-*[ ]*[\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\2>\1<</ s/^\(.*<<-*[ ]*\)[\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\2>\1\2/
s/[ ]*<<//
:hered :hered
N N
/^<\([^>]*\)>.*\n[ ]*\1[ ]*$/!{ /^<\([^>]*\)>.*\n[ ]*\1[ ]*$/!{
@ -238,6 +237,7 @@ s/.*\n//
:cont :cont
# retrieve and print previous line # retrieve and print previous line
x x
s/?!HERE?!/<</g
n n
bslurp bslurp
@ -278,8 +278,7 @@ bfolded
# found here-doc -- swallow it to avoid false hits within its body (but keep # found here-doc -- swallow it to avoid false hits within its body (but keep
# the command to which it was attached) # the command to which it was attached)
:heredoc :heredoc
s/^\(.*\)<<-*[ ]*[\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\2>\1<</ s/^\(.*\)<<\(-*[ ]*\)[\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\3>\1?!HERE?!\2\3/
s/[ ]*<<//
:hdocsub :hdocsub
N N
/^<\([^>]*\)>.*\n[ ]*\1[ ]*$/!{ /^<\([^>]*\)>.*\n[ ]*\1[ ]*$/!{
@ -293,6 +292,7 @@ bfolded
# found "case ... in" -- pass through untouched # found "case ... in" -- pass through untouched
:case :case
x x
s/?!HERE?!/<</g
n n
/^[ ]*esac/bslurp /^[ ]*esac/bslurp
bcase bcase
@ -320,6 +320,7 @@ bchkchn
:nest :nest
x x
:nstslrp :nstslrp
s/?!HERE?!/<</g
n n
# closing ")" on own line -- stop nested slurp # closing ")" on own line -- stop nested slurp
/^[ ]*)/bnstcl /^[ ]*)/bnstcl
@ -342,6 +343,7 @@ bchkchn
# found multi-line "{...\n...}" block -- pass through untouched # found multi-line "{...\n...}" block -- pass through untouched
:block :block
x x
s/?!HERE?!/<</g
n n
# closing "}" -- stop block slurp # closing "}" -- stop block slurp
/}/bchkchn /}/bchkchn
@ -352,13 +354,17 @@ bblock
:clssolo :clssolo
x x
s/\( ?!AMP?!\)* ?!AMP?!$// s/\( ?!AMP?!\)* ?!AMP?!$//
s/?!HERE?!/<</g
p p
x x
s/?!HERE?!/<</g
b b
# found closing "...)" -- exit subshell loop # found closing "...)" -- exit subshell loop
:close :close
x x
s/?!HERE?!/<</g
p p
x x
s/?!HERE?!/<</g
b b

View file

@ -2,7 +2,7 @@
for i in a b c for i in a b c
do do
echo $i ?!AMP?! echo $i ?!AMP?!
cat cat <<-EOF
done ?!AMP?! done ?!AMP?!
for i in a b c; do for i in a b c; do
echo $i && echo $i &&

View file

@ -1,2 +1,2 @@
( (
cat) cat <<-INPUT)

View file

@ -1,5 +1,5 @@
( (
x=$(bobble && x=$(bobble <<-END &&
wiffle) ?!AMP?! wiffle) ?!AMP?!
echo $x echo $x
) )

View file

@ -1,4 +1,4 @@
( (
cat && echo "multi-line string" ?!AMP?! cat <<-TXT && echo "multi-line string" ?!AMP?!
bap bap
) )

View file

@ -1,7 +1,7 @@
boodle wobba gorgo snoot wafta snurb && boodle wobba gorgo snoot wafta snurb <<EOF &&
cat >foo && cat <<-Arbitrary_Tag_42 >foo &&
cat >boo && cat <<zump >boo &&
horticulture horticulture <<EOF

View file

@ -8,7 +8,7 @@
echo foo echo foo
else else
echo foo && echo foo &&
cat cat <<-EOF
fi ?!AMP?! fi ?!AMP?!
echo poodle echo poodle
) && ) &&

View file

@ -1,7 +1,7 @@
cat >foop && cat <<ARBITRARY >foop &&
( (
cat && cat <<-INPUT_END &&
cat ?!AMP?! cat <<-EOT ?!AMP?!
foobar foobar
) )

View file

@ -1,10 +1,10 @@
( (
echo wobba gorgo snoot wafta snurb && echo wobba gorgo snoot wafta snurb <<-EOF &&
cat >bip ?!AMP?! cat <<EOF >bip ?!AMP?!
echo >bop echo <<-EOF >bop
) && ) &&
( (
cat >bup && cat <<-ARBITRARY >bup &&
cat >bup3 && cat <<-ARBITRARY3 >bup3 &&
meep meep
) )

View file

@ -1,9 +1,9 @@
( (
chks="sub1sub2sub3sub4" && chks="sub1sub2sub3sub4" &&
chks_sub=$(cat | sed "s,^,sub dir/," chks_sub=$(cat <<TXT | sed "s,^,sub dir/,"
) && ) &&
chkms="main-sub1main-sub2main-sub3main-sub4" && chkms="main-sub1main-sub2main-sub3main-sub4" &&
chkms_sub=$(cat | sed "s,^,sub dir/," chkms_sub=$(cat <<TXT | sed "s,^,sub dir/,"
) && ) &&
subfiles=$(git ls-files) && subfiles=$(git ls-files) &&
check_equal "$subfiles" "$chkms$chks" check_equal "$subfiles" "$chkms$chks"

View file

@ -2,7 +2,7 @@
while true while true
do do
echo foo ?!AMP?! echo foo ?!AMP?!
cat cat <<-EOF
done ?!AMP?! done ?!AMP?!
while true; do while true; do
echo foo && echo foo &&