From 6bdc52886fdc50d5487ca0e019faf038c3250cac Mon Sep 17 00:00:00 2001 From: Ben Drucker Date: Thu, 1 Dec 2022 18:49:14 -0800 Subject: [PATCH 1/2] terraform_deprecated_index: improve perf for files with many expressions --- rules/terraform_deprecated_index.go | 30 ++++++---- rules/terraform_deprecated_index_test.go | 73 ++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 11 deletions(-) diff --git a/rules/terraform_deprecated_index.go b/rules/terraform_deprecated_index.go index dc028a3..a7f5c9f 100644 --- a/rules/terraform_deprecated_index.go +++ b/rules/terraform_deprecated_index.go @@ -48,20 +48,28 @@ func (r *TerraformDeprecatedIndexRule) Check(runner tflint.Runner) error { return nil } + files := map[string]*hcl.File{} + diags := runner.WalkExpressions(tflint.ExprWalkFunc(func(expr hcl.Expression) hcl.Diagnostics { - filename := expr.Range().Filename - file, err := runner.GetFile(filename) - if err != nil { - return hcl.Diagnostics{ - { - Severity: hcl.DiagError, - Summary: "failed to call GetFile()", - Detail: err.Error(), - }, + for _, variable := range expr.Variables() { + filename := expr.Range().Filename + file, ok := files[filename] + + if !ok { + file, err = runner.GetFile(filename) + if err != nil { + return hcl.Diagnostics{ + { + Severity: hcl.DiagError, + Summary: "failed to call GetFile()", + Detail: err.Error(), + }, + } + } + + files[filename] = file } - } - for _, variable := range expr.Variables() { bytes := expr.Range().SliceBytes(file.Bytes) tokens, diags := hclsyntax.LexExpression(bytes, filename, variable.SourceRange().Start) diff --git a/rules/terraform_deprecated_index_test.go b/rules/terraform_deprecated_index_test.go index 615c9f8..9e6a3f4 100644 --- a/rules/terraform_deprecated_index_test.go +++ b/rules/terraform_deprecated_index_test.go @@ -1,6 +1,9 @@ package rules import ( + "bytes" + "fmt" + "html/template" "testing" "github.com/hashicorp/hcl/v2" @@ -142,3 +145,73 @@ EOF }) } } + +func BenchmarkTerraformDeprecatedInterpolation(b *testing.B) { + cases := []struct { + Size int + Content string + }{ + { + Size: 10, + }, + { + Size: 100, + }, + { + Size: 1000, + }, + // { + // Size: 10000, + // }, + } + + for _, tc := range cases { + tc := tc + + // Generate a list of n objects as locals, where each has keys a-z + // and values 0-n + ct, err := template.New("test").Parse(` + locals { + alphas = [ + {{- range .Size }} + { + {{- range $i, $c := $.Alpha }} + {{ $c }} = {{ $i }}, + {{- end }} + }, + {{- end }} + ] + }`) + + if err != nil { + b.Fatalf("Error rendering content template: %v", err) + } + + buf := bytes.Buffer{} + + err = ct.Execute(&buf, struct { + Size []struct{} + Alpha []string + }{ + Size: make([]struct{}, tc.Size), + Alpha: []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}, + }) + + if err != nil { + b.Fatalf("Error executing content template: %v", err) + } + + tc.Content = buf.String() + + b.Run(fmt.Sprintf("size=%d", tc.Size), func(b *testing.B) { + rule := NewTerraformDeprecatedIndexRule() + runner := helper.TestRunner(b, map[string]string{"config.tf": tc.Content}) + + if err := rule.Check(runner); err != nil { + b.Fatalf("Unexpected error occurred: %s", err) + } + + helper.AssertIssues(b, helper.Issues{}, runner.Issues) + }) + } +} From 0553d6d188dc9cc0d99f6bbe5e6dab09e2502428 Mon Sep 17 00:00:00 2001 From: Ben Drucker Date: Thu, 15 Dec 2022 15:25:26 -0800 Subject: [PATCH 2/2] call GetFiles(), remove benchmark --- rules/terraform_deprecated_index.go | 22 ++----- rules/terraform_deprecated_index_test.go | 73 ------------------------ 2 files changed, 5 insertions(+), 90 deletions(-) diff --git a/rules/terraform_deprecated_index.go b/rules/terraform_deprecated_index.go index a7f5c9f..0cfd438 100644 --- a/rules/terraform_deprecated_index.go +++ b/rules/terraform_deprecated_index.go @@ -48,27 +48,15 @@ func (r *TerraformDeprecatedIndexRule) Check(runner tflint.Runner) error { return nil } - files := map[string]*hcl.File{} + files, err := runner.GetFiles() + if err != nil { + return err + } diags := runner.WalkExpressions(tflint.ExprWalkFunc(func(expr hcl.Expression) hcl.Diagnostics { for _, variable := range expr.Variables() { filename := expr.Range().Filename - file, ok := files[filename] - - if !ok { - file, err = runner.GetFile(filename) - if err != nil { - return hcl.Diagnostics{ - { - Severity: hcl.DiagError, - Summary: "failed to call GetFile()", - Detail: err.Error(), - }, - } - } - - files[filename] = file - } + file := files[filename] bytes := expr.Range().SliceBytes(file.Bytes) diff --git a/rules/terraform_deprecated_index_test.go b/rules/terraform_deprecated_index_test.go index 9e6a3f4..615c9f8 100644 --- a/rules/terraform_deprecated_index_test.go +++ b/rules/terraform_deprecated_index_test.go @@ -1,9 +1,6 @@ package rules import ( - "bytes" - "fmt" - "html/template" "testing" "github.com/hashicorp/hcl/v2" @@ -145,73 +142,3 @@ EOF }) } } - -func BenchmarkTerraformDeprecatedInterpolation(b *testing.B) { - cases := []struct { - Size int - Content string - }{ - { - Size: 10, - }, - { - Size: 100, - }, - { - Size: 1000, - }, - // { - // Size: 10000, - // }, - } - - for _, tc := range cases { - tc := tc - - // Generate a list of n objects as locals, where each has keys a-z - // and values 0-n - ct, err := template.New("test").Parse(` - locals { - alphas = [ - {{- range .Size }} - { - {{- range $i, $c := $.Alpha }} - {{ $c }} = {{ $i }}, - {{- end }} - }, - {{- end }} - ] - }`) - - if err != nil { - b.Fatalf("Error rendering content template: %v", err) - } - - buf := bytes.Buffer{} - - err = ct.Execute(&buf, struct { - Size []struct{} - Alpha []string - }{ - Size: make([]struct{}, tc.Size), - Alpha: []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}, - }) - - if err != nil { - b.Fatalf("Error executing content template: %v", err) - } - - tc.Content = buf.String() - - b.Run(fmt.Sprintf("size=%d", tc.Size), func(b *testing.B) { - rule := NewTerraformDeprecatedIndexRule() - runner := helper.TestRunner(b, map[string]string{"config.tf": tc.Content}) - - if err := rule.Check(runner); err != nil { - b.Fatalf("Unexpected error occurred: %s", err) - } - - helper.AssertIssues(b, helper.Issues{}, runner.Issues) - }) - } -}