Skip to content

Commit 76c2d0b

Browse files
committed
fix: Use valid syntax for conditionals
Fix an issue where object literals inside conditional expressions were not rendered correctly, resulting in invalid expresions. Fixes: #253
1 parent f034ef2 commit 76c2d0b

2 files changed

Lines changed: 30 additions & 14 deletions

File tree

hcl2/transformer.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def attribute(self, args: List) -> Attribute:
178178

179179
def conditional(self, args: List) -> str:
180180
args = self.strip_new_line_tokens(args)
181-
args = self.process_nulls(args)
181+
args = self.all_to_tf_inline(args)
182182
return f"{args[0]} ? {args[1]} : {args[2]}"
183183

184184
def binary_op(self, args: List) -> str:
@@ -187,13 +187,13 @@ def binary_op(self, args: List) -> str:
187187
)
188188

189189
def unary_op(self, args: List) -> str:
190-
args = self.process_nulls(args)
191-
return "".join([self.to_tf_inline(arg) for arg in args])
190+
args = self.all_to_tf_inline(args)
191+
return "".join(args)
192192

193193
def binary_term(self, args: List) -> str:
194194
args = self.strip_new_line_tokens(args)
195-
args = self.process_nulls(args)
196-
return " ".join([self.to_tf_inline(arg) for arg in args])
195+
args = self.all_to_tf_inline(args)
196+
return " ".join(args)
197197

198198
def body(self, args: List) -> Dict[str, List]:
199199
# See https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#bodies
@@ -279,20 +279,24 @@ def new_line_or_comment(self, args: List) -> _DiscardType:
279279

280280
def for_tuple_expr(self, args: List) -> str:
281281
args = self.strip_new_line_tokens(args)
282-
for_expr = " ".join([self.to_tf_inline(arg) for arg in args[1:-1]])
282+
args = self.all_to_tf_inline(args[1:-1])
283+
for_expr = " ".join(args)
283284
return f"[{for_expr}]"
284285

285286
def for_intro(self, args: List) -> str:
286287
args = self.strip_new_line_tokens(args)
287-
return " ".join([self.to_tf_inline(arg) for arg in args])
288+
args = self.all_to_tf_inline(args)
289+
return " ".join(args)
288290

289291
def for_cond(self, args: List) -> str:
290292
args = self.strip_new_line_tokens(args)
291-
return " ".join([self.to_tf_inline(arg) for arg in args])
293+
args = self.all_to_tf_inline(args)
294+
return " ".join(args)
292295

293296
def for_object_expr(self, args: List) -> str:
294297
args = self.strip_new_line_tokens(args)
295-
for_expr = " ".join([self.to_tf_inline(arg) for arg in args[1:-1]])
298+
args = self.all_to_tf_inline(args[1:-1])
299+
for_expr = " ".join(args)
296300
# doubled curly braces stands for inlining the braces
297301
# and the third pair of braces is for the interpolation
298302
# e.g. f"{2 + 2} {{2 + 2}}" == "4 {2 + 2}"
@@ -308,7 +312,7 @@ def string_part(self, args: List) -> str:
308312
return value
309313

310314
def interpolation(self, args: List) -> str:
311-
return '"${' + str(args[0]) + '}"'
315+
return '"${' + self.to_tf_inline(args[0]) + '}"'
312316

313317
def strip_new_line_tokens(self, args: List) -> List:
314318
"""
@@ -369,6 +373,12 @@ def process_escape_sequences(self, value: str) -> str:
369373
def process_nulls(self, args: List) -> List:
370374
return ["null" if arg is None else arg for arg in args]
371375

376+
def all_to_tf_inline(self, args: List) -> List:
377+
"""
378+
Convert all items in a list to "inline" HCL syntax
379+
"""
380+
return [self.to_tf_inline(arg) for arg in args]
381+
372382
def to_tf_inline(self, value: Any) -> str:
373383
"""
374384
Converts complex objects (e.g.) dicts to an "inline" HCL syntax
@@ -387,7 +397,7 @@ def to_tf_inline(self, value: Any) -> str:
387397
if isinstance(value, (int, float)):
388398
return str(value)
389399
if value is None:
390-
return "None"
400+
return "null"
391401

392402
raise RuntimeError(f"Invalid type to convert to inline HCL: {type(value)}")
393403

test/unit/test_hcl2_syntax.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,7 @@ def test_function_call_and_arguments(self):
132132
arg1, arg2,
133133
arg3,
134134
)
135-
""": {
136-
"r": "${function(arg1, arg2, arg3)}"
137-
},
135+
""": {"r": "${function(arg1, arg2, arg3)}"},
138136
}
139137

140138
for call, expected in calls.items():
@@ -191,3 +189,11 @@ def test_expr_term_parenthesis(self):
191189
for actual, expected in literals.items():
192190
result = self.load_to_dict(actual)
193191
self.assertDictEqual(result, expected)
192+
193+
def test_dict_in_conditional(self):
194+
cond = "x = a ? { id = 1 } : null"
195+
196+
expected = {"x": '${a ? {"id": 1} : null}'}
197+
198+
result = self.load_to_dict(cond)
199+
self.assertDictEqual(result, expected)

0 commit comments

Comments
 (0)