Replace SortedStringKeys with SortedKeys
Now that we have generics.
Bug: 193460475
Test: presubmits
Change-Id: I1594fd8feb505175d5c09c03ef397e5ffd5b09cb
diff --git a/android/apex.go b/android/apex.go
index 3c945ae..358818f 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -817,7 +817,7 @@
var flatContent strings.Builder
fmt.Fprintf(&fullContent, "%s(minSdkVersion:%s):\n", ctx.ModuleName(), minSdkVersion)
- for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) {
+ for _, key := range FirstUniqueStrings(SortedKeys(depInfos)) {
info := depInfos[key]
toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion)
if info.IsExternal {
diff --git a/android/defaults.go b/android/defaults.go
index 925eafc..a821b28 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -302,7 +302,7 @@
delete(propertiesSet, "visibility")
// Replace the "*" with the names of all the properties that have been set.
- protectedProperties = SortedStringKeys(propertiesSet)
+ protectedProperties = SortedKeys(propertiesSet)
module.setProtectedProperties(protectedProperties)
} else {
for _, property := range protectedProperties {
diff --git a/android/module.go b/android/module.go
index 97c9706..58c5464 100644
--- a/android/module.go
+++ b/android/module.go
@@ -3675,7 +3675,7 @@
// Ensure ancestor directories are in dirMap
// Make directories build their direct subdirectories
// Returns a slice of all directories and a slice of top-level directories.
- dirs := SortedStringKeys(dirMap)
+ dirs := SortedKeys(dirMap)
for _, dir := range dirs {
dir := parentDir(dir)
for dir != "." && dir != "/" {
@@ -3686,7 +3686,7 @@
dir = parentDir(dir)
}
}
- dirs = SortedStringKeys(dirMap)
+ dirs = SortedKeys(dirMap)
var topDirs []string
for _, dir := range dirs {
p := parentDir(dir)
@@ -3696,7 +3696,7 @@
topDirs = append(topDirs, dir)
}
}
- return SortedStringKeys(dirMap), topDirs
+ return SortedKeys(dirMap), topDirs
}
func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
@@ -3782,7 +3782,7 @@
}
// Wrap those into host|host-cross|target phony rules
- for _, class := range SortedStringKeys(osClass) {
+ for _, class := range SortedKeys(osClass) {
ctx.Phony(class, osClass[class]...)
}
}
diff --git a/android/neverallow.go b/android/neverallow.go
index ad9880a..ba5385c 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -542,7 +542,7 @@
s = append(s, fmt.Sprintf("properties matching: %s", r.props))
}
if len(r.directDeps) > 0 {
- s = append(s, fmt.Sprintf("dep(s): %q", SortedStringKeys(r.directDeps)))
+ s = append(s, fmt.Sprintf("dep(s): %q", SortedKeys(r.directDeps)))
}
if len(r.osClasses) > 0 {
s = append(s, fmt.Sprintf("os class(es): %q", r.osClasses))
diff --git a/android/packaging.go b/android/packaging.go
index ecd84a2..4a9b591 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -240,7 +240,7 @@
// entries into the specified directory.
func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir ModuleOutPath) (entries []string) {
seenDir := make(map[string]bool)
- for _, k := range SortedStringKeys(specs) {
+ for _, k := range SortedKeys(specs) {
ps := specs[k]
destPath := dir.Join(ctx, ps.relPathInPackage).String()
destDir := filepath.Dir(destPath)
diff --git a/android/phony.go b/android/phony.go
index 0adbb55..814a9e3 100644
--- a/android/phony.go
+++ b/android/phony.go
@@ -48,7 +48,7 @@
func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
p.phonyMap = getPhonyMap(ctx.Config())
- p.phonyList = SortedStringKeys(p.phonyMap)
+ p.phonyList = SortedKeys(p.phonyMap)
for _, phony := range p.phonyList {
p.phonyMap[phony] = SortedUniquePaths(p.phonyMap[phony])
}
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index ed4888d..9239ca9 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -301,23 +301,6 @@
}
}
-// This is a copy of the one available in soong/android/util.go, but depending
-// on the android package causes a cyclic dependency. A refactoring here is to
-// extract common utils out from android/utils.go for other packages like this.
-func sortedStringKeys(m interface{}) []string {
- v := reflect.ValueOf(m)
- if v.Kind() != reflect.Map {
- panic(fmt.Sprintf("%#v is not a map", m))
- }
- keys := v.MapKeys()
- s := make([]string, 0, len(keys))
- for _, key := range keys {
- s = append(s, key.String())
- }
- sort.Strings(s)
- return s
-}
-
// String emits the Soong config variable definitions as Starlark dictionaries.
func (defs Bp2BuildSoongConfigDefinitions) String() string {
ret := ""
diff --git a/android/test_suites.go b/android/test_suites.go
index 55e1da7..b570b23 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -57,7 +57,7 @@
func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath {
var installedPaths InstallPaths
- for _, module := range SortedStringKeys(files) {
+ for _, module := range SortedKeys(files) {
installedPaths = append(installedPaths, files[module]...)
}
testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases", false)
diff --git a/android/util.go b/android/util.go
index 8f4c17d..6c0ddf4 100644
--- a/android/util.go
+++ b/android/util.go
@@ -62,25 +62,9 @@
return buf.String()
}
-// JoinWithSuffix appends the suffix to each string in the list and
-// returns them joined together with given separator.
-func JoinWithSuffix(strs []string, suffix string, separator string) string {
- if len(strs) == 0 {
- return ""
- }
-
- var buf strings.Builder
- buf.WriteString(strs[0])
- buf.WriteString(suffix)
- for i := 1; i < len(strs); i++ {
- buf.WriteString(separator)
- buf.WriteString(strs[i])
- buf.WriteString(suffix)
- }
- return buf.String()
-}
-
-// SorterStringKeys returns the keys of the given string-keyed map in the ascending order.
+// SortedStringKeys returns the keys of the given map in the ascending order.
+//
+// Deprecated: Use SortedKeys instead.
func SortedStringKeys(m interface{}) []string {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Map {
@@ -98,6 +82,28 @@
return s
}
+type Ordered interface {
+ ~string |
+ ~float32 | ~float64 |
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
+}
+
+// SortedKeys returns the keys of the given map in the ascending order.
+func SortedKeys[T Ordered, V any](m map[T]V) []T {
+ if len(m) == 0 {
+ return nil
+ }
+ ret := make([]T, 0, len(m))
+ for k := range m {
+ ret = append(ret, k)
+ }
+ sort.Slice(ret, func(i, j int) bool {
+ return ret[i] < ret[j]
+ })
+ return ret
+}
+
// stringValues returns the values of the given string-valued map in randomized map order.
func stringValues(m interface{}) []string {
v := reflect.ValueOf(m)
diff --git a/android/util_test.go b/android/util_test.go
index 9b9253b..51d8e32 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -641,6 +641,36 @@
}
}
+func testSortedKeysHelper[K Ordered, V any](t *testing.T, name string, input map[K]V, expected []K) {
+ t.Helper()
+ t.Run(name, func(t *testing.T) {
+ actual := SortedKeys(input)
+ if !reflect.DeepEqual(actual, expected) {
+ t.Errorf("expected %q, got %q", expected, actual)
+ }
+ })
+}
+
+func TestSortedKeys(t *testing.T) {
+ testSortedKeysHelper(t, "simple", map[string]string{
+ "b": "bar",
+ "a": "foo",
+ }, []string{
+ "a",
+ "b",
+ })
+ testSortedKeysHelper(t, "ints", map[int]interface{}{
+ 10: nil,
+ 5: nil,
+ }, []int{
+ 5,
+ 10,
+ })
+
+ testSortedKeysHelper(t, "nil", map[string]string(nil), nil)
+ testSortedKeysHelper(t, "empty", map[string]string{}, nil)
+}
+
func TestSortedStringKeys(t *testing.T) {
testCases := []struct {
name string