cli: Fix fmt output for multi-line value exprs

The formatter for value expressions which use legacy interpolation
syntax was previously behaving incorrectly with some multi-line
expressions. Any HCL expression which requires parenthesis to be allowed
to span multiple lines could be skip those parens if already inside
string interpolation (`"${}"`).

When removing string interpolation, we now check for a resulting
multi-line expression, and conservatively ensure that it starts and ends
with parenthesis. These may be redundant, as not all expressions require
parens to permit spanning multiple lines, but at least it will be valid
output.
This commit is contained in:
Alisdair McDiarmid 2021-03-25 15:40:54 -04:00
parent 550de86135
commit d71f0c6149
3 changed files with 53 additions and 1 deletions

View File

@ -366,7 +366,41 @@ func (c *FmtCommand) formatValueExpr(tokens hclwrite.Tokens) hclwrite.Tokens {
// "${ // "${
// foo // foo
// }" // }"
return c.trimNewlines(inside) trimmed := c.trimNewlines(inside)
// Finally, we check if the unwrapped expression is on multiple lines. If
// so, we ensure that it is surrounded by parenthesis to make sure that it
// parses correctly after unwrapping. This may be redundant in some cases,
// but is required for at least multi-line ternary expressions.
isMultiLine := false
hasLeadingParen := false
hasTrailingParen := false
for i, token := range trimmed {
switch {
case i == 0 && token.Type == hclsyntax.TokenOParen:
hasLeadingParen = true
case token.Type == hclsyntax.TokenNewline:
isMultiLine = true
case i == len(trimmed)-1 && token.Type == hclsyntax.TokenCParen:
hasTrailingParen = true
}
}
if isMultiLine && !(hasLeadingParen && hasTrailingParen) {
wrapped := make(hclwrite.Tokens, 0, len(trimmed)+2)
wrapped = append(wrapped, &hclwrite.Token{
Type: hclsyntax.TokenOParen,
Bytes: []byte("("),
})
wrapped = append(wrapped, trimmed...)
wrapped = append(wrapped, &hclwrite.Token{
Type: hclsyntax.TokenCParen,
Bytes: []byte(")"),
})
return wrapped
}
return trimmed
} }
func (c *FmtCommand) formatTypeExpr(tokens hclwrite.Tokens) hclwrite.Tokens { func (c *FmtCommand) formatTypeExpr(tokens hclwrite.Tokens) hclwrite.Tokens {

View File

@ -42,3 +42,12 @@ resource "foo_instance" /* ... */ "baz" {
provider "" { provider "" {
} }
locals {
name = "${contains(["foo"], var.my_var) ? "${var.my_var}-bar" :
contains(["baz"], var.my_var) ? "baz-${var.my_var}" :
file("ERROR: unsupported type ${var.my_var}")}"
wrapped = "${(var.my_var == null ? 1 :
var.your_var == null ? 2 :
3)}"
}

View File

@ -42,3 +42,12 @@ resource "foo_instance" "baz" {
provider "" { provider "" {
} }
locals {
name = (contains(["foo"], var.my_var) ? "${var.my_var}-bar" :
contains(["baz"], var.my_var) ? "baz-${var.my_var}" :
file("ERROR: unsupported type ${var.my_var}"))
wrapped = (var.my_var == null ? 1 :
var.your_var == null ? 2 :
3)
}