Skip to content

Commit

Permalink
Add WalkExpressions function
Browse files Browse the repository at this point in the history
  • Loading branch information
wata727 committed Aug 21, 2022
1 parent 9bf8cad commit cc2a529
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 0 deletions.
46 changes: 46 additions & 0 deletions helper/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"

"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
"github.com/terraform-linters/tflint-plugin-sdk/terraform/addrs"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
Expand Down Expand Up @@ -124,6 +125,51 @@ func (r *Runner) GetFiles() (map[string]*hcl.File, error) {
return r.files, nil
}

type nativeWalker struct {
walker tflint.ExprWalker
}

func (w *nativeWalker) Enter(node hclsyntax.Node) hcl.Diagnostics {
if expr, ok := node.(hcl.Expression); ok {
return w.walker.Enter(expr)
}
return nil
}

func (w *nativeWalker) Exit(node hclsyntax.Node) hcl.Diagnostics {
if expr, ok := node.(hcl.Expression); ok {
return w.walker.Exit(expr)
}
return nil
}

func (r *Runner) WalkExpressions(walker tflint.ExprWalker) hcl.Diagnostics {
diags := hcl.Diagnostics{}
for _, file := range r.files {
if body, ok := file.Body.(*hclsyntax.Body); ok {
walkDiags := hclsyntax.Walk(body, &nativeWalker{walker: walker})
diags = diags.Extend(walkDiags)
continue
}

// In JSON syntax, everything can be walked as an attribute.
attrs, jsonDiags := file.Body.JustAttributes()
if jsonDiags.HasErrors() {
diags = diags.Extend(jsonDiags)
continue
}

for _, attr := range attrs {
enterDiags := walker.Enter(attr.Expr)
diags = diags.Extend(enterDiags)
exitDiags := walker.Exit(attr.Expr)
diags = diags.Extend(exitDiags)
}
}

return diags
}

// DecodeRuleConfig extracts the rule's configuration into the given value
func (r *Runner) DecodeRuleConfig(name string, ret interface{}) error {
schema := hclext.ImpliedBodySchema(ret)
Expand Down
56 changes: 56 additions & 0 deletions plugin/plugin2host/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,62 @@ func (c *GRPCClient) GetFiles() (map[string]*hcl.File, error) {
return files, nil
}

type nativeWalker struct {
walker tflint.ExprWalker
}

func (w *nativeWalker) Enter(node hclsyntax.Node) hcl.Diagnostics {
if expr, ok := node.(hcl.Expression); ok {
return w.walker.Enter(expr)
}
return nil
}

func (w *nativeWalker) Exit(node hclsyntax.Node) hcl.Diagnostics {
if expr, ok := node.(hcl.Expression); ok {
return w.walker.Exit(expr)
}
return nil
}

func (c *GRPCClient) WalkExpressions(walker tflint.ExprWalker) hcl.Diagnostics {
files, err := c.GetFiles()
if err != nil {
return hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "failed to call GetFiles()",
Detail: err.Error(),
},
}
}

diags := hcl.Diagnostics{}
for _, file := range files {
if body, ok := file.Body.(*hclsyntax.Body); ok {
walkDiags := hclsyntax.Walk(body, &nativeWalker{walker: walker})
diags = diags.Extend(walkDiags)
continue
}

// In JSON syntax, everything can be walked as an attribute.
attrs, jsonDiags := file.Body.JustAttributes()
if jsonDiags.HasErrors() {
diags = diags.Extend(jsonDiags)
continue
}

for _, attr := range attrs {
enterDiags := walker.Enter(attr.Expr)
diags = diags.Extend(enterDiags)
exitDiags := walker.Exit(attr.Expr)
diags = diags.Extend(exitDiags)
}
}

return diags
}

// DecodeRuleConfig guesses the schema of the rule config from the passed interface and sends the schema to GRPC server.
// Content retrieved based on the schema is decoded into the passed interface.
func (c *GRPCClient) DecodeRuleConfig(name string, ret interface{}) error {
Expand Down
2 changes: 2 additions & 0 deletions tflint/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ type Runner interface {
// This is low level API for accessing information such as comments and syntax.
GetFiles() (map[string]*hcl.File, error)

WalkExpressions(walker ExprWalker) hcl.Diagnostics

// DecodeRuleConfig fetches the rule's configuration and reflects the result in the 2nd argument.
// The argument is expected to be a pointer to a structure tagged with hclext:
//
Expand Down
20 changes: 20 additions & 0 deletions tflint/walker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package tflint

import (
"github.com/hashicorp/hcl/v2"
)

type ExprWalker interface {
Enter(expr hcl.Expression) hcl.Diagnostics
Exit(expr hcl.Expression) hcl.Diagnostics
}

type ExprWalkFunc func(expr hcl.Expression) hcl.Diagnostics

func (f ExprWalkFunc) Enter(expr hcl.Expression) hcl.Diagnostics {
return f(expr)
}

func (f ExprWalkFunc) Exit(expr hcl.Expression) hcl.Diagnostics {
return nil
}

0 comments on commit cc2a529

Please sign in to comment.