Ensure deterministic output from generating keep rules in CodeToKeep
Change-Id: I17dc9ded018c6ba5716021dc71a314f1cdffc9bb
diff --git a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
index 7595a40..177e303 100644
--- a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
+++ b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
@@ -8,12 +8,15 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.CollectionUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.Sets;
+import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -155,7 +158,7 @@
// TODO(b/134734081): Stream the consumer instead of building the String.
StringBuilder sb = new StringBuilder();
String cr = System.lineSeparator();
- for (DexType type : toKeep.keySet()) {
+ for (DexType type : CollectionUtils.sort(toKeep.keySet(), getComparator())) {
KeepStruct keepStruct = toKeep.get(type);
sb.append("-keep class ").append(convertType(type));
if (keepStruct.all) {
@@ -167,7 +170,7 @@
continue;
}
sb.append(" {").append(cr);
- for (DexField field : keepStruct.fields) {
+ for (DexField field : CollectionUtils.sort(keepStruct.fields, getComparator())) {
sb.append(" ")
.append(convertType(field.type))
.append(" ")
@@ -175,7 +178,7 @@
.append(";")
.append(cr);
}
- for (DexMethod method : keepStruct.methods) {
+ for (DexMethod method : CollectionUtils.sort(keepStruct.methods, getComparator())) {
sb.append(" ")
.append(convertType(method.proto.returnType))
.append(" ")
@@ -194,6 +197,15 @@
options.desugaredLibraryKeepRuleConsumer.accept(sb.toString(), options.reporter);
options.desugaredLibraryKeepRuleConsumer.finished(options.reporter);
}
+
+ private static <T extends DexReference> Comparator<T> getComparator() {
+ return new Comparator<T>() {
+ @Override
+ public int compare(T o1, T o2) {
+ return o1.compareTo(o2);
+ }
+ };
+ }
}
public static class NopCodeToKeep extends CodeToKeep {
diff --git a/src/main/java/com/android/tools/r8/utils/CollectionUtils.java b/src/main/java/com/android/tools/r8/utils/CollectionUtils.java
index 91b0638..6af263f 100644
--- a/src/main/java/com/android/tools/r8/utils/CollectionUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/CollectionUtils.java
@@ -5,7 +5,9 @@
package com.android.tools.r8.utils;
import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.Set;
import java.util.function.Consumer;
@@ -24,4 +26,10 @@
collection.forEach(consumer);
}
}
+
+ public static <T> Collection<T> sort(Collection<T> items, Comparator<T> comparator) {
+ ArrayList<T> ts = new ArrayList<>(items);
+ ts.sort(comparator);
+ return ts;
+ }
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
index aeb159d..ee66aab 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
@@ -188,31 +188,31 @@
private void assertGeneratedKeepRulesAreCorrect(String keepRules) {
String expectedResult =
StringUtils.lines(
- "-keep class j$.util.List$-EL {",
- " void sort(java.util.List, java.util.Comparator);",
- "}",
"-keep class j$.util.Collection$-EL {",
" j$.util.stream.Stream stream(java.util.Collection);",
"}",
- "-keep class j$.util.stream.IntStream$-CC {",
- " j$.util.stream.IntStream range(int, int);",
- "}",
"-keep class j$.util.Comparator$-CC {",
" java.util.Comparator comparingInt(j$.util.function.ToIntFunction);",
"}",
+ "-keep class j$.util.DesugarArrays {",
+ " j$.util.Spliterator spliterator(java.lang.Object[]);",
+ " j$.util.Spliterator spliterator(java.lang.Object[], int, int);",
+ " j$.util.stream.Stream stream(java.lang.Object[]);",
+ " j$.util.stream.Stream stream(java.lang.Object[], int, int);",
+ "}",
+ "-keep class j$.util.List$-EL {",
+ " void sort(java.util.List, java.util.Comparator);",
+ "}",
"-keep class j$.util.Set$-EL {",
" j$.util.Spliterator spliterator(java.util.Set);",
"}",
- "-keep class j$.util.DesugarArrays {",
- " j$.util.Spliterator spliterator(java.lang.Object[]);",
- " j$.util.stream.Stream stream(java.lang.Object[], int, int);",
- " j$.util.stream.Stream stream(java.lang.Object[]);",
- " j$.util.Spliterator spliterator(java.lang.Object[], int, int);",
+ "-keep class j$.util.Spliterator",
+ "-keep class j$.util.function.ToIntFunction { *; }",
+ "-keep class j$.util.stream.IntStream$-CC {",
+ " j$.util.stream.IntStream range(int, int);",
"}",
"-keep class j$.util.stream.IntStream",
- "-keep class j$.util.stream.Stream",
- "-keep class j$.util.Spliterator",
- "-keep class j$.util.function.ToIntFunction { *; }");
+ "-keep class j$.util.stream.Stream");
assertEquals(expectedResult, keepRules);
}
}