Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 41 additions & 15 deletions rules/terraform_lists_trailing_comma.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,51 @@ func (r *TerraformListsTrailingCommaRule) Check(runner tflint.Runner) error {
return nil
}

if lastItemRange.End.Byte < len(file.Bytes) && file.Bytes[lastItemRange.End.Byte] != ',' {
if err := runner.EmitIssueWithFix(
r,
"Last item in lists should always end with a trailing comma",
listRange,
func(f tflint.Fixer) error {
return f.InsertTextAfter(lastItemRange, ",")
},
); err != nil {
return hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "failed to call EmitIssueWithFix()",
Detail: err.Error(),
},
// Check if there's already a trailing comma after the last item
// We need to skip whitespace and newlines to handle heredoc cases
commaPos := lastItemRange.End.Byte

// Skip whitespace and newlines after the last item to look for a comma
for commaPos < len(file.Bytes) && (file.Bytes[commaPos] == ' ' || file.Bytes[commaPos] == '\t' || file.Bytes[commaPos] == '\n' || file.Bytes[commaPos] == '\r') {
commaPos++
}

if commaPos < len(file.Bytes) && file.Bytes[commaPos] == ',' {
// It already has a trailling comma
return nil
}

insertText := ","
// Check if the last item is a heredoc.
// A heredoc is a TemplateExpr with a single LiteralValueExpr part.
if template, ok := lastItem.(*hclsyntax.TemplateExpr); ok {
if len(template.Parts) == 1 {
if _, isLiteral := template.Parts[0].(*hclsyntax.LiteralValueExpr); isLiteral {
// This is a strong indicator of a heredoc, especially if it spans multiple lines.
if template.Range().Start.Line != template.Range().End.Line {
insertText = "\n,"
}
}
}
}

if err := runner.EmitIssueWithFix(
r,
"Last item in lists should always end with a trailing comma",
listRange,
func(f tflint.Fixer) error {
return f.InsertTextAfter(lastItemRange, insertText)
},
); err != nil {
return hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "failed to call EmitIssueWithFix()",
Detail: err.Error(),
},
}
}

return nil
}))

Expand Down
35 changes: 35 additions & 0 deletions rules/terraform_lists_trailing_comma_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,41 @@ func Test_TerraformListsTrailingCommaRule(t *testing.T) {
},
},
},
{
Name: "heredoc without trailing comma",
Content: `resource "terraform_data" "test" {
input = [
"test",
<<-HERE
Lorem ipsum
HERE
]
}`,
Expected: helper.Issues{
{
Rule: NewTerraformListsTrailingCommaRule(),
Message: "Last item in lists should always end with a trailing comma",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{Line: 2, Column: 11},
End: hcl.Pos{Line: 7, Column: 4},
},
},
},
},
{
Name: "heredoc with trailing comma",
Content: `resource "terraform_data" "test" {
input = [
"test",
<<-HERE
Lorem ipsum
HERE
,
]
}`,
Expected: helper.Issues{},
},
}

rule := NewTerraformListsTrailingCommaRule()
Expand Down