Skip to content

Commit 70a5307

Browse files
Fix missing space between binary operator and unary operand in reconstruction (#275)
The reconstructor's _should_add_space_before only checked for binary operator spacing when the next sibling was a Token, but after operators like && the next sibling can be a Tree (expr_term wrapping unary_op), causing "&&!foo" instead of "&& !foo". Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0c30780 commit 70a5307

5 files changed

Lines changed: 35 additions & 0 deletions

File tree

hcl2/reconstructor.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ def _should_add_space_before(
164164
elif isinstance(current_node, Tree):
165165
rule_name = current_node.data
166166

167+
# Space after binary operator tokens before a tree node (e.g. && !foo)
168+
if self._last_token_name in self._binary_op_types:
169+
return True
170+
167171
if parent_rule_name == BlockRule.lark_name():
168172
# Add space between multiple string/identifier labels in blocks
169173
if rule_name in [

test/integration/hcl2_original/smoke.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ block multiline_binary_ops {
6565
}
6666
}
6767

68+
block binary_op_before_unary {
69+
dedup_keys_layer7 = {
70+
for k, v in local.action_keys_layer7 :
71+
k => v
72+
if !contains(keys(local.dedup_keys_layer8), k)
73+
&& !contains(keys(local.dedup_keys_layer9), k)
74+
&& !contains(keys(local.dedup_keys_layer10), k)
75+
}
76+
}
77+
6878
block {
6979
route53_forwarding_rule_shares = {
7080
for forwarding_rule_key in keys(var.route53_resolver_forwarding_rule_shares) :

test/integration/hcl2_reconstructed/smoke.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ block multiline_binary_ops {
5353
}
5454

5555

56+
block binary_op_before_unary {
57+
dedup_keys_layer7 = {
58+
for k, v in local.action_keys_layer7 :
59+
k => v
60+
if !contains(keys(local.dedup_keys_layer8), k) && !contains(keys(local.dedup_keys_layer9), k) && !contains(keys(local.dedup_keys_layer10), k)
61+
}
62+
}
63+
64+
5665
block {
5766
route53_forwarding_rule_shares = {
5867
for forwarding_rule_key in keys(var.route53_resolver_forwarding_rule_shares) :

test/integration/json_reserialized/smoke.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@
6060
"__is_block__": true
6161
}
6262
},
63+
{
64+
"binary_op_before_unary": {
65+
"dedup_keys_layer7": "${{for k, v in local.action_keys_layer7 : k => v if !contains(keys(local.dedup_keys_layer8), k) && !contains(keys(local.dedup_keys_layer9), k) && !contains(keys(local.dedup_keys_layer10), k)}}",
66+
"__is_block__": true
67+
}
68+
},
6369
{
6470
"route53_forwarding_rule_shares": "${{for forwarding_rule_key in keys(var.route53_resolver_forwarding_rule_shares) : \"${forwarding_rule_key}\" => {aws_account_ids = [for account_name in var.route53_resolver_forwarding_rule_shares[forwarding_rule_key].aws_account_names : module.remote_state_subaccounts.map[account_name].outputs[\"aws_account_id\"]]}... if substr(bucket_name, 0, 1) == \"l\"}}",
6571
"__is_block__": true

test/integration/json_serialized/smoke.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@
6060
"__is_block__": true
6161
}
6262
},
63+
{
64+
"binary_op_before_unary": {
65+
"dedup_keys_layer7": "${{for k, v in local.action_keys_layer7 : k => v if !contains(keys(local.dedup_keys_layer8), k) && !contains(keys(local.dedup_keys_layer9), k) && !contains(keys(local.dedup_keys_layer10), k)}}",
66+
"__is_block__": true
67+
}
68+
},
6369
{
6470
"route53_forwarding_rule_shares": "${{for forwarding_rule_key in keys(var.route53_resolver_forwarding_rule_shares) : \"${forwarding_rule_key}\" => {aws_account_ids = [for account_name in var.route53_resolver_forwarding_rule_shares[forwarding_rule_key].aws_account_names : module.remote_state_subaccounts.map[account_name].outputs[\"aws_account_id\"]]}... if substr(bucket_name, 0, 1) == \"l\"}}",
6571
"__is_block__": true

0 commit comments

Comments
 (0)