Skip to content

Commit

Permalink
rule: make value sorting configurable (alternative implementation) (b…
Browse files Browse the repository at this point in the history
…azel-contrib#1719)

* rule: add tests for attribute value sorting

* rule: make value sorting configurable
  • Loading branch information
t-8ch authored and jeromep-stripe committed Mar 22, 2024
1 parent a675ba0 commit 0eb6deb
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 9 deletions.
31 changes: 22 additions & 9 deletions rule/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -725,10 +725,11 @@ func (l *Load) sync() {
// Rule represents a rule statement within a build file.
type Rule struct {
stmt
kind bzl.Expr
args []bzl.Expr
attrs map[string]attrValue
private map[string]interface{}
kind bzl.Expr
args []bzl.Expr
attrs map[string]attrValue
private map[string]interface{}
sortedAttrs []string
}

type attrValue struct {
Expand All @@ -746,10 +747,11 @@ func NewRule(kind, name string) *Rule {
call := &bzl.CallExpr{X: kindIdent}

r := &Rule{
stmt: stmt{expr: call},
kind: kindIdent,
attrs: map[string]attrValue{},
private: map[string]interface{}{},
stmt: stmt{expr: call},
kind: kindIdent,
attrs: map[string]attrValue{},
private: map[string]interface{}{},
sortedAttrs: []string{"deps", "srcs"},
}
if name != "" {
nameAttr := attrValue{
Expand Down Expand Up @@ -1014,6 +1016,17 @@ func (r *Rule) AddArg(value bzl.Expr) {
r.updated = true
}

// SortedAttrs returns the keys of attributes whose values will be sorted
func (r *Rule) SortedAttrs() []string {
return r.sortedAttrs
}

// SetSortedAttrs sets the keys of attributes whose values will be sorted
func (r *Rule) SetSortedAttrs(keys []string) {
r.sortedAttrs = keys
r.updated = true
}

// Insert marks this statement for insertion at the end of the file. Multiple
// statements will be inserted in the order Insert is called.
func (r *Rule) Insert(f *File) {
Expand Down Expand Up @@ -1057,7 +1070,7 @@ func (r *Rule) sync() {
}
r.updated = false

for _, k := range []string{"srcs", "deps"} {
for _, k := range r.sortedAttrs {
attr, ok := r.attrs[k]
_, isUnsorted := attr.val.(UnsortedStrings)
if ok && !isUnsorted {
Expand Down
79 changes: 79 additions & 0 deletions rule/rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -666,3 +666,82 @@ export_files(glob(["**"]))
t.Errorf("got:%s\nwant:%s", got, want)
}
}

func TestAttributeValueSorting(t *testing.T) {
f := EmptyFile("foo", "bar")

r := NewRule("a_rule", "")
r.SetAttr("deps", []string{"foo", "bar", "baz"})
r.SetAttr("srcs", UnsortedStrings{"foo", "bar", "baz"})
r.SetAttr("hdrs", []string{"foo", "bar", "baz"})

r.Insert(f)
f.Sync()

got := strings.TrimSpace(string(bzl.FormatWithoutRewriting(f.File)))
want := strings.TrimSpace(`
a_rule(
srcs = [
"foo",
"bar",
"baz",
],
hdrs = [
"foo",
"bar",
"baz",
],
deps = [
"bar",
"baz",
"foo",
],
)
`)

if got != want {
t.Errorf("got:%s\nwant:%s", got, want)
}
}

func TestAttributeValueSortingOverride(t *testing.T) {
f := EmptyFile("foo", "bar")

r := NewRule("a_rule", "")
r.SetAttr("deps", []string{"foo", "bar", "baz"})
r.SetAttr("srcs", UnsortedStrings{"foo", "bar", "baz"})
r.SetAttr("hdrs", []string{"foo", "bar", "baz"})
r.SetSortedAttrs([]string{"srcs", "hdrs"})

r.Insert(f)
f.Sync()

got := strings.TrimSpace(string(bzl.FormatWithoutRewriting(f.File)))
want := strings.TrimSpace(`
a_rule(
srcs = [
"foo",
"bar",
"baz",
],
hdrs = [
"bar",
"baz",
"foo",
],
deps = [
"foo",
"bar",
"baz",
],
)
`)

if got != want {
t.Errorf("got:%s\nwant:%s", got, want)
}

if !reflect.DeepEqual(r.SortedAttrs(), []string{"srcs", "hdrs"}) {
t.Errorf("Unexpected r.SortedAttrs(): %v", r.SortedAttrs())
}
}

0 comments on commit 0eb6deb

Please sign in to comment.