Cherry pick: Desugared lib: Fix conversions keep rules
CL: https://r8-review.googlesource.com/c/r8/+/48000
Cherry pick hash: 890fbe2f8ca0b36d90d51f2cdb7d399dce3b67d3
Bug:148373997
Change-Id: I8f7f464bdc7ddcb6076842e40f2cf8d4283a3fec
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 62988d6..d5cf7a4 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "2.0.22";
+ public static final String LABEL = "2.0.23";
private Version() {
}
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 7a2c325..f327f21 100644
--- a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
+++ b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
@@ -43,25 +43,28 @@
public static class DesugaredLibraryCodeToKeep extends CodeToKeep {
private static class KeepStruct {
+
Set<DexField> fields = Sets.newConcurrentHashSet();
Set<DexMethod> methods = Sets.newConcurrentHashSet();
boolean all = false;
}
private final NamingLens namingLens;
- private final Set<DexType> emulatedInterfaces = Sets.newIdentityHashSet();
+ private final Set<DexType> potentialTypesToKeep = Sets.newIdentityHashSet();
private final Map<DexType, KeepStruct> toKeep = new ConcurrentHashMap<>();
private final InternalOptions options;
public DesugaredLibraryCodeToKeep(NamingLens namingLens, InternalOptions options) {
- emulatedInterfaces.addAll(
- options.desugaredLibraryConfiguration.getEmulateLibraryInterface().values());
this.namingLens = namingLens;
this.options = options;
+ potentialTypesToKeep.addAll(
+ options.desugaredLibraryConfiguration.getEmulateLibraryInterface().values());
+ potentialTypesToKeep.addAll(
+ options.desugaredLibraryConfiguration.getCustomConversions().values());
}
private boolean shouldKeep(DexType type) {
- return namingLens.prefixRewrittenType(type) != null || emulatedInterfaces.contains(type);
+ return namingLens.prefixRewrittenType(type) != null || potentialTypesToKeep.contains(type);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
index 61296c9..2c5e7e6 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
@@ -16,7 +16,9 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -30,6 +32,22 @@
public class DesugaredLibraryTestBase extends TestBase {
+ protected static TestParametersCollection getConversionParametersFrom(AndroidApiLevel apiLevel) {
+ if (apiLevel == AndroidApiLevel.N) {
+ return getTestParameters()
+ .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
+ .withApiLevelsEndingAtExcluding(AndroidApiLevel.N)
+ .build();
+ }
+ if (apiLevel == AndroidApiLevel.O) {
+ return getTestParameters()
+ .withDexRuntimesStartingFromIncluding(Version.V8_1_0)
+ .withApiLevelsEndingAtExcluding(AndroidApiLevel.O)
+ .build();
+ }
+ throw new Error("Unsupported conversion parameters");
+ }
+
protected boolean requiresEmulatedInterfaceCoreLibDesugaring(TestParameters parameters) {
return parameters.getApiLevel().getLevel() < AndroidApiLevel.N.getLevel();
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicTimeConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicTimeConversionTest.java
index 1e66f26..6f6d2f9 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicTimeConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicTimeConversionTest.java
@@ -4,62 +4,84 @@
package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import com.android.tools.r8.L8Command;
-import com.android.tools.r8.OutputMode;
-import com.android.tools.r8.StringResource;
-import com.android.tools.r8.TestDiagnosticMessagesImpl;
-import com.android.tools.r8.TestRuntime.DexRuntime;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import java.nio.file.Path;
import java.time.ZoneId;
+import java.util.List;
import java.util.TimeZone;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+@RunWith(Parameterized.class)
public class BasicTimeConversionTest extends DesugaredLibraryTestBase {
- @Test
- public void testTimeGeneratedDex() throws Exception {
- TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
- Path desugaredLib = temp.newFolder().toPath().resolve("conversion_dex.zip");
- L8Command.Builder l8Builder =
- L8Command.builder(diagnosticsHandler)
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
- .addProgramFiles(ToolHelper.DESUGAR_LIB_CONVERSIONS)
- .addDesugaredLibraryConfiguration(
- StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
- .setMinApiLevel(AndroidApiLevel.B.getLevel())
- .setOutput(desugaredLib, OutputMode.DexIndexed);
- ToolHelper.runL8(l8Builder.build(), x -> {});
- this.checkTimeConversionGeneratedDex(new CodeInspector(desugaredLib));
+ private final TestParameters parameters;
+ private final boolean shrinkDesugaredLibrary;
+ private static final String GMT = StringUtils.lines("GMT");
+
+ @Parameters(name = "{0}, shrinkDesugaredLibrary: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(getConversionParametersFrom(AndroidApiLevel.O), BooleanUtils.values());
}
- private void checkTimeConversionGeneratedDex(CodeInspector inspector) {
- ClassSubject clazz = inspector.clazz("j$.time.TimeConversions");
- assertThat(clazz, isPresent());
- assertEquals(13, clazz.allMethods().size());
+ public BasicTimeConversionTest(TestParameters parameters, boolean shrinkDesugaredLibrary) {
+ this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+ this.parameters = parameters;
}
@Test
- public void testRewrittenAPICalls() throws Exception {
+ public void testRewrittenAPICallsD8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
- .setMinApi(AndroidApiLevel.B)
+ .setMinApi(parameters.getApiLevel())
.addInnerClasses(BasicTimeConversionTest.class)
- .enableCoreLibraryDesugaring(AndroidApiLevel.B)
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
.inspect(this::checkAPIRewritten)
- .addDesugaredCoreLibraryRunClassPath(this::buildDesugaredLibrary, AndroidApiLevel.B)
- .run(new DexRuntime(DexVm.ART_9_0_0_HOST), Executor.class);
+ .run(parameters.getRuntime(), Executor.class)
+ .assertSuccessWithOutput(GMT);
+ if (shrinkDesugaredLibrary) {
+ checkKeepRules(keepRuleConsumer.get());
+ }
+ }
+
+ private void checkKeepRules(String keepRules) {
+ assertTrue(keepRules.contains("TimeConversion"));
+ }
+
+ @Test
+ public void testRewrittenAPICallsR8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ testForR8(parameters.getBackend())
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Executor.class)
+ .addInnerClasses(BasicTimeConversionTest.class)
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Executor.class)
+ .assertSuccessWithOutput(GMT);
+ if (shrinkDesugaredLibrary) {
+ checkKeepRules(keepRuleConsumer.get());
+ }
}
private void checkAPIRewritten(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionsPresentTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionsPresentTest.java
new file mode 100644
index 0000000..43d5b9a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionsPresentTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+import com.android.tools.r8.L8Command;
+import com.android.tools.r8.OutputMode;
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ConversionsPresentTest extends DesugaredLibraryTestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ }
+
+ public ConversionsPresentTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testConversionsDex() throws Exception {
+ TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
+ Path desugaredLib = temp.newFolder().toPath().resolve("conversion_dex.zip");
+ L8Command.Builder l8Builder =
+ L8Command.builder(diagnosticsHandler)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .addProgramFiles(ToolHelper.DESUGAR_LIB_CONVERSIONS)
+ .addDesugaredLibraryConfiguration(
+ StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
+ .setMinApiLevel(parameters.getApiLevel().getLevel())
+ .setOutput(desugaredLib, OutputMode.DexIndexed);
+ ToolHelper.runL8(l8Builder.build(), x -> {});
+ this.checkConversionGeneratedDex(new CodeInspector(desugaredLib));
+ }
+
+ private void checkConversionGeneratedDex(CodeInspector inspector) {
+ List<FoundClassSubject> conversionsClasses =
+ inspector.allClasses().stream()
+ .filter(c -> c.getOriginalName().contains("Conversions"))
+ .collect(Collectors.toList());
+ if (parameters.getApiLevel().isLessThan(AndroidApiLevel.N)) {
+ assertEquals(5, conversionsClasses.size());
+ assertTrue(inspector.clazz("j$.util.OptionalConversions").isPresent());
+ assertTrue(inspector.clazz("j$.time.TimeConversions").isPresent());
+ assertTrue(inspector.clazz("j$.util.LongSummaryStatisticsConversions").isPresent());
+ assertTrue(inspector.clazz("j$.util.IntSummaryStatisticsConversions").isPresent());
+ assertTrue(inspector.clazz("j$.util.DoubleSummaryStatisticsConversions").isPresent());
+ } else if (parameters.getApiLevel().isLessThan(AndroidApiLevel.O)) {
+ assertEquals(1, conversionsClasses.size());
+ assertTrue(inspector.clazz("j$.time.TimeConversions").isPresent());
+ } else {
+ assertEquals(0, inspector.allClasses().size());
+ }
+ }
+}