rules/helper.go (84 lines of code) (raw):
package rules
import (
"fmt"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/hashicorp/hcl/v2/hclwrite"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"sort"
"strings"
)
var headMetaArgPriority = map[string]int{"for_each": 0, "count": 0, "provider": 1}
var tailMetaArgPriority = map[string]int{"lifecycle": 0, "depends_on": 1}
// IsHeadMeta checks whether a name represents a type of head Meta arg
func IsHeadMeta(argName string) bool {
_, isHeadMeta := headMetaArgPriority[argName]
return isHeadMeta
}
// IsTailMeta checks whether a name represents a type of tail Meta arg
func IsTailMeta(argName string) bool {
_, isTailMeta := tailMetaArgPriority[argName]
return isTailMeta
}
func ref(hr hcl.Range) *hcl.Range {
return &hr
}
func ForFiles(runner tflint.Runner, action func(tflint.Runner, *hcl.File) error) error {
files, err := runner.GetFiles()
if err != nil {
return err
}
for _, file := range files {
if subErr := action(runner, file); subErr != nil {
err = multierror.Append(err, subErr)
}
}
return err
}
// PrintSortedAttrTxt print the sorted hcl text of an attribute
func PrintSortedAttrTxt(src []byte, attr *hclsyntax.Attribute) (string, bool) {
isSorted := true
exp, isMap := attr.Expr.(*hclsyntax.ObjectConsExpr)
if !isMap {
return string(attr.Range().SliceBytes(src)), isSorted
}
var keys []string
object := make(map[string]string)
for _, item := range exp.Items {
key := string(item.KeyExpr.Range().SliceBytes(src))
value := fmt.Sprintf("%s = %s", key, string(item.ValueExpr.Range().SliceBytes(src)))
keys = append(keys, key)
object[key] = value
}
isSorted = sort.StringsAreSorted(keys)
if !isSorted {
sort.Strings(keys)
}
var objectAttrs []string
for _, key := range keys {
objectAttrs = append(objectAttrs, object[key])
}
sortedExpTxt := strings.Join(objectAttrs, "\n")
var sortedAttrTxt string
if RemoveSpaceAndLine(sortedExpTxt) == "" {
sortedAttrTxt = fmt.Sprintf("%s = {}", attr.Name)
} else {
sortedAttrTxt = fmt.Sprintf("%s = {\n%s\n}", attr.Name, sortedExpTxt)
}
formattedTxt := string(hclwrite.Format([]byte(sortedAttrTxt)))
return formattedTxt, isSorted
}
// RemoveSpaceAndLine remove space, "\t" and "\n" from the given string
func RemoveSpaceAndLine(str string) string {
newStr := strings.ReplaceAll(str, " ", "")
newStr = strings.ReplaceAll(newStr, "\t", "")
newStr = strings.ReplaceAll(newStr, "\n", "")
return newStr
}
func attributesByLines(attributes hclsyntax.Attributes) []*hclsyntax.Attribute {
var attrs []*hclsyntax.Attribute
for _, attr := range attributes {
attrs = append(attrs, attr)
}
sort.Slice(attrs, func(i, j int) bool {
return attrs[i].Range().Start.Line < attrs[j].Range().Start.Line
})
return attrs
}