@@ -3,6 +3,7 @@ package align
33
44import (
55 "sort"
6+ "strings"
67
78 "github.com/hashicorp/hcl/v2/hclwrite"
89)
@@ -11,13 +12,52 @@ type terraformStrategy struct{}
1112
1213func (terraformStrategy ) Name () string { return "terraform" }
1314
15+ // Align orders attributes and nested blocks within a terraform block. Attributes
16+ // are sorted alphabetically. Nested blocks are sorted by type and labels while
17+ // preserving the ordering of their contents. If a required_providers block is
18+ // present, the provider entries inside it are also sorted alphabetically.
1419func (terraformStrategy ) Align (block * hclwrite.Block , _ * Options ) error {
15- attrs := block .Body ().Attributes ()
20+ body := block .Body ()
21+
22+ // Sort provider entries within required_providers blocks
23+ for _ , nb := range body .Blocks () {
24+ if nb .Type () == "required_providers" {
25+ attrs := nb .Body ().Attributes ()
26+ names := make ([]string , 0 , len (attrs ))
27+ for name := range attrs {
28+ names = append (names , name )
29+ }
30+ sort .Strings (names )
31+ if err := reorderBlock (nb , names ); err != nil {
32+ return err
33+ }
34+ }
35+ }
36+
37+ // Order top-level blocks by type then labels
38+ blocks := body .Blocks ()
39+ sort .SliceStable (blocks , func (i , j int ) bool {
40+ bi , bj := blocks [i ], blocks [j ]
41+ if bi .Type () != bj .Type () {
42+ return bi .Type () < bj .Type ()
43+ }
44+ return strings .Join (bi .Labels (), "\x00 " ) < strings .Join (bj .Labels (), "\x00 " )
45+ })
46+ for _ , b := range body .Blocks () {
47+ body .RemoveBlock (b )
48+ }
49+ for _ , b := range blocks {
50+ body .AppendBlock (b )
51+ }
52+
53+ // Gather and order attributes
54+ attrs := body .Attributes ()
1655 names := make ([]string , 0 , len (attrs ))
1756 for name := range attrs {
1857 names = append (names , name )
1958 }
2059 sort .Strings (names )
60+
2161 return reorderBlock (block , names )
2262}
2363
0 commit comments