Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to evaluate naked identifier map keys #338

Open
wata727 opened this issue Jul 28, 2024 · 0 comments
Open

Failed to evaluate naked identifier map keys #338

wata727 opened this issue Jul 28, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@wata727
Copy link
Member

wata727 commented Jul 28, 2024

Follow up of terraform-linters/tflint-ruleset-terraform#196

Naked identifier map keys are typically not valid references, but can still be successfully evaluated. Despite this, it fails to evaluate in the TFLint plugin SDK. This is exactly the same problem that occurs in terraform-linters/tflint-ruleset-terraform#196, where the test runner doesn't throw an error, but the actual runner does.

The cause of this is in the serialization of expressions. In the actual runner, in order to send an expression via gRPC, it is converted into a byte sequence of the expression's source code and then parsed again as an expression:

out := &proto.Expression{
Bytes: expr.Range().SliceBytes(source),
Range: Range(expr.Range()),
}

parsed, diags := hclext.ParseExpression(expr.Bytes, expr.Range.Filename, Pos(expr.Range.Start))

However, expressions such as map keys are context-sensitive and when parsed in this manner the result is a different expression type.

package main

import (
        "fmt"

        "github.com/hashicorp/hcl/v2"
        "github.com/hashicorp/hcl/v2/hclsyntax"
)

func main() {
        source := []byte(`{ keys = "value" }`)
        expr, diags := hclsyntax.ParseExpression(source, "main.tf", hcl.InitialPos)
        if diags.HasErrors() {
                panic(diags)
        }
        pairs, diags := hcl.ExprMap(expr)
        if diags.HasErrors() {
                panic(diags)
        }
        originalExpr := pairs[0].Key

        fmt.Printf("original_expr=%T\n", originalExpr)
        keySource := originalExpr.Range().SliceBytes(source)
        parsedExpr, diags := hclsyntax.ParseExpression(keySource, "main.tf", originalExpr.Range().Start)
        if diags.HasErrors() {
                panic(diags)
        }
        fmt.Printf("parsed_expr=%T\n", parsedExpr)
}
$ go run main.go
original_expr=*hclsyntax.ObjectConsKeyExpr
parsed_expr=*hclsyntax.ScopeTraversalExpr

The ObjectConsKeyExpr is a wrapper expression that allows a naked identifier to be evaluated without error.
https://github.com/hashicorp/hcl/blob/v2.21.0/hclsyntax/expression.go#L1286-L1292

To fix this in the SDK, we would need to include the fact that the expression was a map key in proto.Expression and restore it on the host side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

1 participant