Summary
SerializationContext.inside_dollar_string tells a rule it is being
serialized into expression source rather than into a value. StringRule
checks it and keeps its quotes. HeredocTemplateRule and
HeredocTrimTemplateRule never read it, so a heredoc argument is written into
the expression as its bare body, newlines and all.
Reproduction
hcl2.loads("a = upper(<<E\nx\nE\n)\n",
serialization_options=SerializationOptions(preserve_heredocs=False,
strip_string_quotes=True))
# {'a': '${upper(x)}'}
x is now a bare reference rather than a string, and with a multi-line body
the result contains a raw newline inside ${...}, which is not parseable HCL.
The quoted-string case one line away is correct: upper("x") gives
${upper("x")}.
Both << and <<- are affected: HeredocTemplateRule.serialize
(hcl2/rules/strings.py:164 at v8.1.3) and
HeredocTrimTemplateRule.serialize (:197) both take the context and pass it
to their child, but branch only on options.strip_string_quotes.
StringRule.serialize (:115) checks context.inside_dollar_string for
exactly this case.
This issue, and the investigation behind it, were produced by an AI assistant (Claude) working on behalf of the author. Please review with that provenance in mind.
Summary
SerializationContext.inside_dollar_stringtells a rule it is beingserialized into expression source rather than into a value.
StringRulechecks it and keeps its quotes.
HeredocTemplateRuleandHeredocTrimTemplateRulenever read it, so a heredoc argument is written intothe expression as its bare body, newlines and all.
Reproduction
xis now a bare reference rather than a string, and with a multi-line bodythe result contains a raw newline inside
${...}, which is not parseable HCL.The quoted-string case one line away is correct:
upper("x")gives${upper("x")}.Both
<<and<<-are affected:HeredocTemplateRule.serialize(
hcl2/rules/strings.py:164atv8.1.3) andHeredocTrimTemplateRule.serialize(:197) both take the context and pass itto their child, but branch only on
options.strip_string_quotes.StringRule.serialize(:115) checkscontext.inside_dollar_stringforexactly this case.
This issue, and the investigation behind it, were produced by an AI assistant (Claude) working on behalf of the author. Please review with that provenance in mind.