Skip to content

Commit 827cf11

Browse files
authored
Merge pull request #83 from terraform-linters/evaluate_expr_with_type
tflint: Add wantType argument to EvaluateExpr
2 parents a0b477e + 7ac9a2a commit 827cf11

File tree

6 files changed

+45
-26
lines changed

6 files changed

+45
-26
lines changed

helper/runner.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -153,23 +153,29 @@ func (r *Runner) DecodeRuleConfig(name string, ret interface{}) error {
153153

154154
// EvaluateExpr returns a value of the passed expression.
155155
// Note that some features are limited
156-
func (r *Runner) EvaluateExpr(expr hcl.Expression, ret interface{}) error {
156+
func (r *Runner) EvaluateExpr(expr hcl.Expression, ret interface{}, wantTy *cty.Type) error {
157157
var wantType cty.Type
158-
switch ret.(type) {
159-
case *string, string:
160-
wantType = cty.String
161-
case *int, int:
162-
wantType = cty.Number
163-
case *[]string, []string:
164-
wantType = cty.List(cty.String)
165-
case *[]int, []int:
166-
wantType = cty.List(cty.Number)
167-
case *map[string]string, map[string]string:
168-
wantType = cty.Map(cty.String)
169-
case *map[string]int, map[string]int:
170-
wantType = cty.Map(cty.Number)
171-
default:
172-
panic(fmt.Errorf("Unexpected result type: %T", ret))
158+
159+
if wantTy != nil {
160+
wantType = *wantTy
161+
}
162+
if wantType == (cty.Type{}) {
163+
switch ret.(type) {
164+
case *string, string:
165+
wantType = cty.String
166+
case *int, int:
167+
wantType = cty.Number
168+
case *[]string, []string:
169+
wantType = cty.List(cty.String)
170+
case *[]int, []int:
171+
wantType = cty.List(cty.Number)
172+
case *map[string]string, map[string]string:
173+
wantType = cty.Map(cty.String)
174+
case *map[string]int, map[string]int:
175+
wantType = cty.Map(cty.Number)
176+
default:
177+
panic(fmt.Errorf("Unexpected result type: %T", ret))
178+
}
173179
}
174180

175181
variables := map[string]cty.Value{}
@@ -194,8 +200,8 @@ func (r *Runner) EvaluateExpr(expr hcl.Expression, ret interface{}) error {
194200

195201
// EvaluateExprOnRootCtx returns a value of the passed expression.
196202
// Note this is just alias of EvaluateExpr.
197-
func (r *Runner) EvaluateExprOnRootCtx(expr hcl.Expression, ret interface{}) error {
198-
return r.EvaluateExpr(expr, ret)
203+
func (r *Runner) EvaluateExprOnRootCtx(expr hcl.Expression, ret interface{}, wantType *cty.Type) error {
204+
return r.EvaluateExpr(expr, ret, wantType)
199205
}
200206

201207
// EmitIssueOnExpr adds an issue to the runner itself.

helper/runner_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ resource "aws_instance" "foo" {
369369

370370
err := runner.WalkResourceAttributes("aws_instance", "instance_type", func(attribute *hcl.Attribute) error {
371371
var instanceType string
372-
if err := runner.EvaluateExpr(attribute.Expr, &instanceType); err != nil {
372+
if err := runner.EvaluateExpr(attribute.Expr, &instanceType, nil); err != nil {
373373
t.Fatal(err)
374374
}
375375

tflint/client/client.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/hashicorp/hcl/v2/hclsyntax"
1313
"github.com/terraform-linters/tflint-plugin-sdk/terraform/configs"
1414
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
15+
"github.com/zclconf/go-cty/cty"
1516
"github.com/zclconf/go-cty/cty/gocty"
1617
)
1718

@@ -221,15 +222,19 @@ func (c *Client) DecodeRuleConfig(name string, ret interface{}) error {
221222

222223
// EvaluateExpr calls the server-side EvalExpr method and reflects the response
223224
// in the passed argument.
224-
func (c *Client) EvaluateExpr(expr hcl.Expression, ret interface{}) error {
225+
func (c *Client) EvaluateExpr(expr hcl.Expression, ret interface{}, wantType *cty.Type) error {
226+
if wantType == nil {
227+
wantType = &cty.Type{}
228+
}
229+
225230
var response EvalExprResponse
226231
var err error
227232

228233
src, err := ioutil.ReadFile(expr.Range().Filename)
229234
if err != nil {
230235
return err
231236
}
232-
req := EvalExprRequest{Ret: ret}
237+
req := EvalExprRequest{Ret: ret, Type: *wantType}
233238
req.Expr, req.ExprRange = encodeExpr(src, expr)
234239
if err := c.rpcClient.Call("Plugin.EvalExpr", req, &response); err != nil {
235240
return err
@@ -258,15 +263,19 @@ func (c *Client) EvaluateExpr(expr hcl.Expression, ret interface{}) error {
258263

259264
// EvaluateExprOnRootCtx calls the server-side EvalExprOnRootCtx method and reflects the response
260265
// in the passed argument.
261-
func (c *Client) EvaluateExprOnRootCtx(expr hcl.Expression, ret interface{}) error {
266+
func (c *Client) EvaluateExprOnRootCtx(expr hcl.Expression, ret interface{}, wantType *cty.Type) error {
267+
if wantType == nil {
268+
wantType = &cty.Type{}
269+
}
270+
262271
var response EvalExprResponse
263272
var err error
264273

265274
src, err := ioutil.ReadFile(expr.Range().Filename)
266275
if err != nil {
267276
return err
268277
}
269-
req := EvalExprRequest{Ret: ret}
278+
req := EvalExprRequest{Ret: ret, Type: *wantType}
270279
req.Expr, req.ExprRange = encodeExpr(src, expr)
271280
if err := c.rpcClient.Call("Plugin.EvalExprOnRootCtx", req, &response); err != nil {
272281
return err

tflint/client/client_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ func Test_EvaluateExpr(t *testing.T) {
354354
}
355355

356356
var ret string
357-
if err := client.EvaluateExpr(expr, &ret); err != nil {
357+
if err := client.EvaluateExpr(expr, &ret, nil); err != nil {
358358
t.Fatal(err)
359359
}
360360

tflint/client/rpc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ type RuleConfigResponse struct {
9595
type EvalExprRequest struct {
9696
Expr []byte
9797
ExprRange hcl.Range
98+
Type cty.Type
9899
Ret interface{}
99100
}
100101

tflint/interface.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package tflint
33
import (
44
"github.com/hashicorp/hcl/v2"
55
"github.com/terraform-linters/tflint-plugin-sdk/terraform/configs"
6+
"github.com/zclconf/go-cty/cty"
67
)
78

89
// RuleSet is a list of rules that a plugin should provide.
@@ -61,13 +62,15 @@ type Runner interface {
6162
DecodeRuleConfig(name string, ret interface{}) error
6263

6364
// EvaluateExpr evaluates the passed expression and reflects the result in ret.
65+
// If you want to ensure the type of ret, you can pass the type as the 3rd argument.
66+
// If you pass nil as the type, it will be inferred from the type of ret.
6467
// Since this function returns an application error, it is expected to use the EnsureNoError
6568
// to determine whether to continue processing.
66-
EvaluateExpr(expr hcl.Expression, ret interface{}) error
69+
EvaluateExpr(expr hcl.Expression, ret interface{}, wantType *cty.Type) error
6770

6871
// EvaluateExprOnRootCtx is the equivalent of EvaluateExpr method in the context of the root module.
6972
// Its main use is to evaluate the provider block obtained by the RootProvider method.
70-
EvaluateExprOnRootCtx(expr hcl.Expression, ret interface{}) error
73+
EvaluateExprOnRootCtx(expr hcl.Expression, ret interface{}, wantType *cty.Type) error
7174

7275
// EmitIssue sends an issue with an expression to TFLint. You need to pass the message of the issue and the expression.
7376
EmitIssueOnExpr(rule Rule, message string, expr hcl.Expression) error

0 commit comments

Comments
 (0)