Summary
ExprTermRule.serialize sets inside_parentheses to
self.parentheses or context.inside_parentheses
(hcl2/rules/expressions.py:103 at v8.1.3), so the flag stays set for the
whole subtree. _wrap_into_parentheses (:37) reads it at :47 as "my
immediate parent already wrapped me" and declines to wrap. Anything under a parenthesized
ancestor therefore loses the parentheses the option exists to add.
Reproduction
options = SerializationOptions(force_operation_parentheses=True)
hcl2.loads("a = b + c * d\n", serialization_options=options)["a"] # '${b + (c * d)}'
hcl2.loads("a = (b + c * d)\n", serialization_options=options)["a"] # '${(b + c * d)}'
The second should contain (c * d) as the first does.
Suggested shape of the fix
Drop or context.inside_parentheses. Each inner ExprTermRule re-sets the
flag from its own self.parentheses, so ((b + c) * d) still comes out right.
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
ExprTermRule.serializesetsinside_parenthesestoself.parentheses or context.inside_parentheses(
hcl2/rules/expressions.py:103atv8.1.3), so the flag stays set for thewhole subtree.
_wrap_into_parentheses(:37) reads it at:47as "myimmediate parent already wrapped me" and declines to wrap. Anything under a parenthesized
ancestor therefore loses the parentheses the option exists to add.
Reproduction
The second should contain
(c * d)as the first does.Suggested shape of the fix
Drop
or context.inside_parentheses. Each innerExprTermRulere-sets theflag from its own
self.parentheses, so((b + c) * d)still comes out right.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.