From 714d594e552f52f539e0087921a02158473c8ba0 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 18 Aug 2026 11:15:21 -0700 Subject: [PATCH 1/2] fix: parse heredocs with an empty body (#309) `a = <[a-zA-Z][a-zA-Z0-9._-]+)\n(?:.|\n)*?\n\s*(?P=heredoc)\n/ -HEREDOC_TEMPLATE_TRIM : /<<-(?P[a-zA-Z][a-zA-Z0-9._-]+)\n(?:.|\n)*?\n\s*(?P=heredoc_trim)\n/ +HEREDOC_TEMPLATE : /<<(?P[a-zA-Z][a-zA-Z0-9._-]+)\n(?:(?:.|\n)*?\n)??\s*(?P=heredoc)\n/ +HEREDOC_TEMPLATE_TRIM : /<<-(?P[a-zA-Z][a-zA-Z0-9._-]+)\n(?:(?:.|\n)*?\n)??\s*(?P=heredoc_trim)\n/ // Ignore whitespace (but not newlines, as they're significant in HCL) %ignore /[ \t]+/ diff --git a/test/integration/specialized/heredocs.tf b/test/integration/specialized/heredocs.tf index 9fc16498..6a10897b 100644 --- a/test/integration/specialized/heredocs.tf +++ b/test/integration/specialized/heredocs.tf @@ -31,4 +31,16 @@ EOF json_content = < Date: Mon, 24 Aug 2026 16:09:48 +0200 Subject: [PATCH 2/2] test: cover the empty-heredoc cases the fix also repairs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The grammar change fixes more than the existing tests pin down. Two consecutive empty heredocs are the tightest form of the run-on and were silent data loss before: main returned one attribute spanning both, with the second absent and no exception. The run-on also latched onto a non-matching later delimiter. Add container contexts too — tuple element, object value, function argument — which all raised before the fix, showing the repair is not limited to top-level attributes. Tab-indented closing delimiter covers the whitespace class in `\s*`. Co-Authored-By: Claude Opus 5 (1M context) --- test/unit/test_api.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/unit/test_api.py b/test/unit/test_api.py index 8814acbd..6d32b78a 100644 --- a/test/unit/test_api.py +++ b/test/unit/test_api.py @@ -332,3 +332,30 @@ def test_consecutive_heredocs_stay_separate(self): def test_indented_closing_delimiter_still_allowed(self): self.assertEqual(loads("a = <