parser: do not consume the newline that ends a heredoc terminator line - #115
Merged
m-ildefons merged 1 commit intoAug 11, 2026
Merged
Conversation
The heredoc terminator consumed the line break that follows the marker, so the top level parser had nothing left to accept as the separator before the next instruction. A comment or an instruction placed directly after a heredoc failed to parse, while an empty line or a leading space made the error go away. Stop at the marker and only look ahead for the newline. The delimiter of an empty heredoc has the same shape and is fixed the same way. closes hadolint#99 related-to: hadolint/hadolint#960 Signed-off-by: Eljees <3.14hell@gmail.com>
m-ildefons
approved these changes
Aug 11, 2026
m-ildefons
left a comment
Member
There was a problem hiding this comment.
Thanks a lot. This is awesome.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes #99
related-to: hadolint/hadolint#960
What I did
Anything that follows a heredoc immediately — a comment or the next instruction — fails to parse:
Both reporters noticed that the error disappears if you add an empty line after the terminator,
or a single space before the
#. That is the signature of the defect: the character is fine,the newline is gone.
How I did it
heredocContent(src/Language/Docker/Parser/Prelude.hs) recognises the terminator asso it consumes the line break that comes after the marker. The top-level loop in
Language/Docker/Parser.hsthen asks for a separator:and there is nothing left to consume — hence the error, and hence the two workarounds: an empty
line supplies a second newline, and a space before
#is caught by theonlySpaces1branchof
eol.The patch stops at the marker and only looks ahead for the newline, so the line break stays
available for the caller.
delEOL(the empty-heredoc delimiter) has the same shape and the samedefect, and is fixed symmetrically — it is reachable: it is the branch taken by the existing
"empty heredoc" test, which I confirmed with a
traceMprobe before touching it.terEOF/delEOF(marker at end of file, no trailing newline) are left alone.How to verify it
test/Language/Docker/ParseRunSpec.hsandtest/Language/Docker/ParseCopySpec.hs: heredoc followed by a comment, heredoc followed byanother instruction, and the same two for an empty heredoc;
302 examples, 5 failures, each with the exact error from the issues;302 examples, 0 failures(the 297 pre-existing tests are untouched), including"empty heredoc", "empty heredoc not followed by newline" and "evil heredoc";
hlint src/ test/reports the same 5 hints before and after the patch.Environment: GHC 9.8.4,
cabal testas in.github/workflows/haskell.yml.