Backport Optional/OptionalInt/OptionalLong/OptionalDouble.isEmpty()
Test: tools/test.py --dex_vm all --no-internal -v *Backport*Test*
Test: tools/test.py --no-internal -v *GenerateBackportMethods*
Change-Id: I2c575b9ab62f5817a513ec9e9a15c1a2aac9c91a
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index d6650ab..bdc98f0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -507,6 +507,7 @@
|| options.minApiLevel >= AndroidApiLevel.N.getLevel()) {
initializeJava9OptionalMethodProviders(factory);
initializeJava10OptionalMethodProviders(factory);
+ initializeJava11OptionalMethodProviders(factory);
}
if (appView.rewritePrefix.hasRewrittenType(factory.streamType)
|| options.minApiLevel >= AndroidApiLevel.N.getLevel()) {
@@ -1520,6 +1521,32 @@
}
}
+ private void initializeJava11OptionalMethodProviders(DexItemFactory factory) {
+ // Optional{void,Int,Long,Double}.isEmpty()
+ DexType[] optionalTypes =
+ new DexType[] {
+ factory.optionalType,
+ factory.optionalDoubleType,
+ factory.optionalLongType,
+ factory.optionalIntType,
+ };
+ TemplateMethodFactory[] methodFactories =
+ new TemplateMethodFactory[]{
+ BackportedMethods::OptionalMethods_isEmpty,
+ BackportedMethods::OptionalMethods_isEmptyDouble,
+ BackportedMethods::OptionalMethods_isEmptyLong,
+ BackportedMethods::OptionalMethods_isEmptyInt
+ };
+ DexString name = factory.createString("isEmpty");
+ for (int i = 0; i < optionalTypes.length; i++) {
+ DexType optionalType = optionalTypes[i];
+ DexProto proto = factory.createProto(factory.booleanType);
+ DexMethod method = factory.createMethod(optionalType, proto, name);
+ addProvider(
+ new StatifyingMethodGenerator(method, methodFactories[i], "isEmpty", optionalType));
+ }
+ }
+
private void initializeStreamMethodProviders(DexItemFactory factory) {
// Stream
DexType streamType = factory.streamType;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index bd87524..8440fc2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -5170,6 +5170,130 @@
ImmutableList.of());
}
+ public static CfCode OptionalMethods_isEmpty(InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 1,
+ 1,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/util/Optional;"),
+ options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createString("isPresent")),
+ false),
+ new CfIf(If.Type.NE, ValueType.INT, label1),
+ new CfConstNumber(1, ValueType.INT),
+ new CfGoto(label2),
+ label1,
+ new CfConstNumber(0, ValueType.INT),
+ label2,
+ new CfReturn(ValueType.INT),
+ label3),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode OptionalMethods_isEmptyDouble(InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 1,
+ 1,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/util/OptionalDouble;"),
+ options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createString("isPresent")),
+ false),
+ new CfIf(If.Type.NE, ValueType.INT, label1),
+ new CfConstNumber(1, ValueType.INT),
+ new CfGoto(label2),
+ label1,
+ new CfConstNumber(0, ValueType.INT),
+ label2,
+ new CfReturn(ValueType.INT),
+ label3),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode OptionalMethods_isEmptyInt(InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 1,
+ 1,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/util/OptionalInt;"),
+ options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createString("isPresent")),
+ false),
+ new CfIf(If.Type.NE, ValueType.INT, label1),
+ new CfConstNumber(1, ValueType.INT),
+ new CfGoto(label2),
+ label1,
+ new CfConstNumber(0, ValueType.INT),
+ label2,
+ new CfReturn(ValueType.INT),
+ label3),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode OptionalMethods_isEmptyLong(InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 1,
+ 1,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfInvoke(
+ 182,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/util/OptionalLong;"),
+ options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createString("isPresent")),
+ false),
+ new CfIf(If.Type.NE, ValueType.INT, label1),
+ new CfConstNumber(1, ValueType.INT),
+ new CfGoto(label2),
+ label1,
+ new CfConstNumber(0, ValueType.INT),
+ label2,
+ new CfReturn(ValueType.INT),
+ label3),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
public static CfCode OptionalMethods_or(InternalOptions options, DexMethod method) {
CfLabel label0 = new CfLabel();
CfLabel label1 = new CfLabel();
diff --git a/src/test/examplesJava11/backport/OptionalBackportJava11Main.java b/src/test/examplesJava11/backport/OptionalBackportJava11Main.java
new file mode 100644
index 0000000..d1f6fa1
--- /dev/null
+++ b/src/test/examplesJava11/backport/OptionalBackportJava11Main.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2019, 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 backport;
+
+import java.util.Optional;
+
+public final class OptionalBackportJava11Main {
+
+ public static void main(String[] args) {
+ testIsEmpty();
+ }
+
+ private static void testIsEmpty() {
+ Optional<String> present = Optional.of("hey");
+ assertFalse(present.isEmpty());
+
+ Optional<String> absent = Optional.empty();
+ assertTrue(absent.isEmpty());
+ }
+
+ private static void assertTrue(boolean value) {
+ if (!value) {
+ throw new AssertionError("Expected <true> but was <false>");
+ }
+ }
+
+ private static void assertFalse(boolean value) {
+ if (value) {
+ throw new AssertionError("Expected <false> but was <true>");
+ }
+ }
+}
diff --git a/src/test/examplesJava11/backport/OptionalDoubleBackportJava11Main.java b/src/test/examplesJava11/backport/OptionalDoubleBackportJava11Main.java
new file mode 100644
index 0000000..1fa5617
--- /dev/null
+++ b/src/test/examplesJava11/backport/OptionalDoubleBackportJava11Main.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2019, 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 backport;
+
+import java.util.OptionalDouble;
+
+public final class OptionalDoubleBackportJava11Main {
+
+ public static void main(String[] args) {
+ testIsEmpty();
+ }
+
+ private static void testIsEmpty() {
+ OptionalDouble present = OptionalDouble.of(2d);
+ assertFalse(present.isEmpty());
+
+ OptionalDouble absent = OptionalDouble.empty();
+ assertTrue(absent.isEmpty());
+ }
+
+ private static void assertTrue(boolean value) {
+ if (!value) {
+ throw new AssertionError("Expected <true> but was <false>");
+ }
+ }
+
+ private static void assertFalse(boolean value) {
+ if (value) {
+ throw new AssertionError("Expected <false> but was <true>");
+ }
+ }
+}
diff --git a/src/test/examplesJava11/backport/OptionalIntBackportJava11Main.java b/src/test/examplesJava11/backport/OptionalIntBackportJava11Main.java
new file mode 100644
index 0000000..9d1a09a
--- /dev/null
+++ b/src/test/examplesJava11/backport/OptionalIntBackportJava11Main.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2019, 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 backport;
+
+import java.util.OptionalInt;
+
+public final class OptionalIntBackportJava11Main {
+
+ public static void main(String[] args) {
+ testIsEmpty();
+ }
+
+ private static void testIsEmpty() {
+ OptionalInt present = OptionalInt.of(2);
+ assertFalse(present.isEmpty());
+
+ OptionalInt absent = OptionalInt.empty();
+ assertTrue(absent.isEmpty());
+ }
+
+ private static void assertTrue(boolean value) {
+ if (!value) {
+ throw new AssertionError("Expected <true> but was <false>");
+ }
+ }
+
+ private static void assertFalse(boolean value) {
+ if (value) {
+ throw new AssertionError("Expected <false> but was <true>");
+ }
+ }
+}
diff --git a/src/test/examplesJava11/backport/OptionalLongBackportJava11Main.java b/src/test/examplesJava11/backport/OptionalLongBackportJava11Main.java
new file mode 100644
index 0000000..573bbba
--- /dev/null
+++ b/src/test/examplesJava11/backport/OptionalLongBackportJava11Main.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2019, 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 backport;
+
+import java.util.OptionalLong;
+
+public final class OptionalLongBackportJava11Main {
+
+ public static void main(String[] args) {
+ testIsEmpty();
+ }
+
+ private static void testIsEmpty() {
+ OptionalLong present = OptionalLong.of(2L);
+ assertFalse(present.isEmpty());
+
+ OptionalLong absent = OptionalLong.empty();
+ assertTrue(absent.isEmpty());
+ }
+
+ private static void assertTrue(boolean value) {
+ if (!value) {
+ throw new AssertionError("Expected <true> but was <false>");
+ }
+ }
+
+ private static void assertFalse(boolean value) {
+ if (value) {
+ throw new AssertionError("Expected <false> but was <true>");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/OptionalBackportJava11Test.java b/src/test/java/com/android/tools/r8/desugar/backports/OptionalBackportJava11Test.java
new file mode 100644
index 0000000..dee14c1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/OptionalBackportJava11Test.java
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, 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.backports;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Optional;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+@RunWith(Parameterized.class)
+public final class OptionalBackportJava11Test extends AbstractBackportTest {
+ @Parameters(name = "{0}")
+ public static Iterable<?> data() {
+ return getTestParameters()
+ .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
+ .withApiLevelsStartingAtIncluding(AndroidApiLevel.N)
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
+ .build();
+ }
+
+ private static final Path TEST_JAR =
+ Paths.get(ToolHelper.EXAMPLES_JAVA11_JAR_DIR).resolve("backport" + JAR_EXTENSION);
+
+ public OptionalBackportJava11Test(TestParameters parameters) {
+ super(parameters, Optional.class, TEST_JAR, "backport.OptionalBackportJava11Main");
+ // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+ // an actual API level, migrate these tests to OptionalBackportTest.
+
+ // Available since N as part of library desugaring.
+ ignoreInvokes("empty");
+ ignoreInvokes("of");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/OptionalDoubleBackportJava11Test.java b/src/test/java/com/android/tools/r8/desugar/backports/OptionalDoubleBackportJava11Test.java
new file mode 100644
index 0000000..981e1e2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/OptionalDoubleBackportJava11Test.java
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, 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.backports;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.OptionalDouble;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+@RunWith(Parameterized.class)
+public final class OptionalDoubleBackportJava11Test extends AbstractBackportTest {
+ @Parameters(name = "{0}")
+ public static Iterable<?> data() {
+ return getTestParameters()
+ .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
+ .withApiLevelsStartingAtIncluding(AndroidApiLevel.N)
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
+ .build();
+ }
+
+ private static final Path TEST_JAR =
+ Paths.get(ToolHelper.EXAMPLES_JAVA11_JAR_DIR).resolve("backport" + JAR_EXTENSION);
+
+ public OptionalDoubleBackportJava11Test(TestParameters parameters) {
+ super(parameters, OptionalDouble.class, TEST_JAR, "backport.OptionalDoubleBackportJava11Main");
+ // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+ // an actual API level, migrate these tests to OptionalBackportTest.
+
+ // Available since N as part of library desugaring.
+ ignoreInvokes("empty");
+ ignoreInvokes("of");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/OptionalIntBackportJava11Test.java b/src/test/java/com/android/tools/r8/desugar/backports/OptionalIntBackportJava11Test.java
new file mode 100644
index 0000000..e594db3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/OptionalIntBackportJava11Test.java
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, 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.backports;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.OptionalInt;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+@RunWith(Parameterized.class)
+public final class OptionalIntBackportJava11Test extends AbstractBackportTest {
+ @Parameters(name = "{0}")
+ public static Iterable<?> data() {
+ return getTestParameters()
+ .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
+ .withApiLevelsStartingAtIncluding(AndroidApiLevel.N)
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
+ .build();
+ }
+
+ private static final Path TEST_JAR =
+ Paths.get(ToolHelper.EXAMPLES_JAVA11_JAR_DIR).resolve("backport" + JAR_EXTENSION);
+
+ public OptionalIntBackportJava11Test(TestParameters parameters) {
+ super(parameters, OptionalInt.class, TEST_JAR, "backport.OptionalIntBackportJava11Main");
+ // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+ // an actual API level, migrate these tests to OptionalBackportTest.
+
+ // Available since N as part of library desugaring.
+ ignoreInvokes("empty");
+ ignoreInvokes("of");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/OptionalLongBackportJava11Test.java b/src/test/java/com/android/tools/r8/desugar/backports/OptionalLongBackportJava11Test.java
new file mode 100644
index 0000000..bc1f4aa
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/OptionalLongBackportJava11Test.java
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, 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.backports;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.OptionalLong;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+@RunWith(Parameterized.class)
+public final class OptionalLongBackportJava11Test extends AbstractBackportTest {
+ @Parameters(name = "{0}")
+ public static Iterable<?> data() {
+ return getTestParameters()
+ .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
+ .withApiLevelsStartingAtIncluding(AndroidApiLevel.N)
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
+ .build();
+ }
+
+ private static final Path TEST_JAR =
+ Paths.get(ToolHelper.EXAMPLES_JAVA11_JAR_DIR).resolve("backport" + JAR_EXTENSION);
+
+ public OptionalLongBackportJava11Test(TestParameters parameters) {
+ super(parameters, OptionalLong.class, TEST_JAR, "backport.OptionalLongBackportJava11Main");
+ // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+ // an actual API level, migrate these tests to OptionalBackportTest.
+
+ // Available since N as part of library desugaring.
+ ignoreInvokes("empty");
+ ignoreInvokes("of");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/OptionalMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/OptionalMethods.java
index 6a1bbc2..6fb1a83 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/OptionalMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/OptionalMethods.java
@@ -100,4 +100,20 @@
return DoubleStream.empty();
}
}
+
+ public static boolean isEmpty(Optional<?> receiver) {
+ return !receiver.isPresent();
+ }
+
+ public static boolean isEmptyInt(OptionalInt receiver) {
+ return !receiver.isPresent();
+ }
+
+ public static boolean isEmptyLong(OptionalLong receiver) {
+ return !receiver.isPresent();
+ }
+
+ public static boolean isEmptyDouble(OptionalDouble receiver) {
+ return !receiver.isPresent();
+ }
}