Skip to content

Commit

Permalink
Add autofix support (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
wata727 authored Jun 13, 2023
1 parent c5f4437 commit ab8ad03
Show file tree
Hide file tree
Showing 18 changed files with 538 additions and 195 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl/v2 v2.17.0
github.com/hashicorp/terraform-registry-address v0.2.0
github.com/terraform-linters/tflint-plugin-sdk v0.16.1
github.com/terraform-linters/tflint-plugin-sdk v0.16.2-0.20230605170513-64de942491dc
github.com/zclconf/go-cty v1.13.2
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,8 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/terraform-linters/tflint-plugin-sdk v0.16.1 h1:fBfLL8KzP3pkQrNp3iQxaGoKBoMo2sFYoqmhuo6yc+A=
github.com/terraform-linters/tflint-plugin-sdk v0.16.1/go.mod h1:ltxVy04PRwptL6P/Ugz2ZeTNclYapClrLn/kVFXJGzo=
github.com/terraform-linters/tflint-plugin-sdk v0.16.2-0.20230605170513-64de942491dc h1:z0PQWOWfWOYps2Oo7nT/v9XASazFZITnMA+oGWZzB78=
github.com/terraform-linters/tflint-plugin-sdk v0.16.2-0.20230605170513-64de942491dc/go.mod h1:ltxVy04PRwptL6P/Ugz2ZeTNclYapClrLn/kVFXJGzo=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
Expand Down
5 changes: 4 additions & 1 deletion rules/terraform_comment_syntax.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,13 @@ func (r *TerraformCommentSyntaxRule) checkComments(runner tflint.Runner, filenam
}

if strings.HasPrefix(string(token.Bytes), "//") {
if err := runner.EmitIssue(
if err := runner.EmitIssueWithFix(
r,
"Single line comments should begin with #",
token.Range,
func(f tflint.Fixer) error {
return f.ReplaceText(f.RangeTo("//", filename, token.Range.Start), "#")
},
); err != nil {
return err
}
Expand Down
7 changes: 7 additions & 0 deletions rules/terraform_comment_syntax_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func Test_TerraformCommentSyntaxRule(t *testing.T) {
Content string
JSON bool
Expected helper.Issues
Fixed string
}{
{
Name: "hash comment",
Expand Down Expand Up @@ -48,6 +49,7 @@ func Test_TerraformCommentSyntaxRule(t *testing.T) {
},
},
},
Fixed: `# foo`,
},
{
Name: "end-of-line hash comment",
Expand Down Expand Up @@ -82,6 +84,11 @@ variable "foo" {
}

helper.AssertIssues(t, tc.Expected, runner.Issues)
want := map[string]string{}
if tc.Fixed != "" {
want[filename] = tc.Fixed
}
helper.AssertChanges(t, want, runner.Changes())
})
}
}
16 changes: 11 additions & 5 deletions rules/terraform_deprecated_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,18 @@ func (r *TerraformDeprecatedIndexRule) Check(runner tflint.Runner) error {
r.checkLegacyTraversalIndex(runner, expr.Traversal, file.Bytes)
case *hclsyntax.SplatExpr:
if strings.HasPrefix(string(expr.MarkerRange.SliceBytes(file.Bytes)), ".") {
if err := runner.EmitIssue(
if err := runner.EmitIssueWithFix(
r,
"List items should be accessed using square brackets",
expr.MarkerRange,
func(f tflint.Fixer) error {
return f.ReplaceText(expr.MarkerRange, "[*]")
},
); err != nil {
return hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "failed to call EmitIssue()",
Summary: "failed to call EmitIssueWithFix()",
Detail: err.Error(),
},
}
Expand All @@ -98,17 +101,20 @@ func (r *TerraformDeprecatedIndexRule) Check(runner tflint.Runner) error {

func (r *TerraformDeprecatedIndexRule) checkLegacyTraversalIndex(runner tflint.Runner, traversal hcl.Traversal, file []byte) hcl.Diagnostics {
for _, t := range traversal {
if _, ok := t.(hcl.TraverseIndex); ok {
if tn, ok := t.(hcl.TraverseIndex); ok {
if strings.HasPrefix(string(t.SourceRange().SliceBytes(file)), ".") {
if err := runner.EmitIssue(
if err := runner.EmitIssueWithFix(
r,
"List items should be accessed using square brackets",
t.SourceRange(),
func(f tflint.Fixer) error {
return f.ReplaceText(t.SourceRange(), "[", f.ValueText(tn.Key), "]")
},
); err != nil {
return hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "failed to call EmitIssue()",
Summary: "failed to call EmitIssueWithFix()",
Detail: err.Error(),
},
}
Expand Down
94 changes: 70 additions & 24 deletions rules/terraform_deprecated_index_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ func Test_TerraformDeprecatedIndexRule(t *testing.T) {
Content string
JSON bool
Expected helper.Issues
Fixed string
}{
{
Name: "deprecated dot index style",
Content: `
locals {
list = ["a"]
list = ["a"]
value = list.0
}
`,
Expand All @@ -39,13 +40,19 @@ locals {
},
},
},
Fixed: `
locals {
list = ["a"]
value = list[0]
}
`,
},
{
Name: "deprecated dot splat index style",
Content: `
locals {
maplist = [{a = "b"}]
values = maplist.*.a
maplist = [{ a = "b" }]
values = maplist.*.a
}
`,
Expected: helper.Issues{
Expand All @@ -56,21 +63,27 @@ locals {
Filename: "config.tf",
Start: hcl.Pos{
Line: 4,
Column: 19,
Column: 20,
},
End: hcl.Pos{
Line: 4,
Column: 21,
Column: 22,
},
},
},
},
Fixed: `
locals {
maplist = [{ a = "b" }]
values = maplist[*].a
}
`,
},
{
Name: "attribute access",
Content: `
locals {
map = {a = "b"}
map = { a = "b" }
value = map.a
}
`,
Expand All @@ -90,9 +103,9 @@ locals {
Content: `
locals {
servers = <<EOF
%{ for ip in aws_instance.example[*].private_ip }
%{for ip in aws_instance.example[*].private_ip}
server ${ip}
%{ endfor }
%{endfor}
EOF
}
`,
Expand All @@ -101,14 +114,14 @@ EOF
{
Name: "directive: invalid",
Content: `
locals {
servers = <<EOF
%{ for ip in aws_instance.example.*.private_ip }
server ${ip}
%{ endfor }
EOF
}
`,
locals {
servers = <<EOF
%{for ip in aws_instance.example.*.private_ip}
server ${ip}
%{endfor}
EOF
}
`,
Expected: helper.Issues{
{
Rule: NewTerraformDeprecatedIndexRule(),
Expand All @@ -117,22 +130,31 @@ EOF
Filename: "config.tf",
Start: hcl.Pos{
Line: 4,
Column: 36,
Column: 33,
},
End: hcl.Pos{
Line: 4,
Column: 38,
Column: 35,
},
},
},
},
Fixed: `
locals {
servers = <<EOF
%{for ip in aws_instance.example[*].private_ip}
server ${ip}
%{endfor}
EOF
}
`,
},
{
Name: "legacy splat and legacy index",
Content: `
locals {
nested_list = [["a"]]
value = nested_list.*.0
value = nested_list.*.0
}
`,
Expected: helper.Issues{
Expand All @@ -143,11 +165,11 @@ locals {
Filename: "config.tf",
Start: hcl.Pos{
Line: 4,
Column: 22,
Column: 28,
},
End: hcl.Pos{
Line: 4,
Column: 24,
Column: 30,
},
},
},
Expand All @@ -158,21 +180,27 @@ locals {
Filename: "config.tf",
Start: hcl.Pos{
Line: 4,
Column: 24,
Column: 30,
},
End: hcl.Pos{
Line: 4,
Column: 26,
Column: 32,
},
},
},
},
Fixed: `
locals {
nested_list = [["a"]]
value = nested_list[*][0]
}
`,
},
{
Name: "complex expression",
Content: `
locals {
create_namespace = true
create_namespace = true
kubernetes_namespace = local.create_namespace ? join("", kubernetes_namespace.default.*.id) : var.kubernetes_namespace
}
`,
Expand All @@ -193,6 +221,12 @@ locals {
},
},
},
Fixed: `
locals {
create_namespace = true
kubernetes_namespace = local.create_namespace ? join("", kubernetes_namespace.default[*].id) : var.kubernetes_namespace
}
`,
},
{
Name: "json invalid",
Expand Down Expand Up @@ -221,6 +255,13 @@ locals {
},
},
},
Fixed: `
{
"locals": {
"list": ["a"],
"value": "${list[0]}"
}
}`,
},
{
Name: "json valid",
Expand Down Expand Up @@ -264,6 +305,11 @@ locals {
}

helper.AssertIssues(t, tc.Expected, runner.Issues)
want := map[string]string{}
if tc.Fixed != "" {
want[filename] = tc.Fixed
}
helper.AssertChanges(t, want, runner.Changes())
})
}
}
10 changes: 7 additions & 3 deletions rules/terraform_deprecated_interpolation.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,24 @@ func (r *TerraformDeprecatedInterpolationRule) Check(runner tflint.Runner) error
}

func (r *TerraformDeprecatedInterpolationRule) checkForDeprecatedInterpolationsInExpr(runner tflint.Runner, expr hcl.Expression) hcl.Diagnostics {
if _, ok := expr.(*hclsyntax.TemplateWrapExpr); !ok {
wrapExpr, ok := expr.(*hclsyntax.TemplateWrapExpr)
if !ok {
return nil
}

err := runner.EmitIssue(
err := runner.EmitIssueWithFix(
r,
"Interpolation-only expressions are deprecated in Terraform v0.12.14",
expr.Range(),
func(f tflint.Fixer) error {
return f.ReplaceText(expr.Range(), f.TextAt(wrapExpr.Wrapped.Range()))
},
)
if err != nil {
return hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "failed to call EmitIssue()",
Summary: "failed to call EmitIssueWithFix()",
Detail: err.Error(),
},
}
Expand Down
Loading

0 comments on commit ab8ad03

Please sign in to comment.