Add desugar-specific diagnostics for missing types.
Bug: 118842646
Bug: 132671303
Change-Id: Idaddfde6e88379678af40680bd044cf28c85a9a6
diff --git a/src/main/java/com/android/tools/r8/errors/DesugarDiagnostic.java b/src/main/java/com/android/tools/r8/errors/DesugarDiagnostic.java
new file mode 100644
index 0000000..59711e9
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/errors/DesugarDiagnostic.java
@@ -0,0 +1,11 @@
+// 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.errors;
+
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.KeepForSubclassing;
+
+/** Common interface type for all diagnostics related to desugaring. */
+@KeepForSubclassing
+public interface DesugarDiagnostic extends Diagnostic {}
diff --git a/src/main/java/com/android/tools/r8/errors/InterfaceDesugarDiagnostic.java b/src/main/java/com/android/tools/r8/errors/InterfaceDesugarDiagnostic.java
new file mode 100644
index 0000000..7bd18fd
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/errors/InterfaceDesugarDiagnostic.java
@@ -0,0 +1,12 @@
+// 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.errors;
+
+import com.android.tools.r8.KeepForSubclassing;
+
+/** Common interface type for all diagnostics related to interface-method desugaring. */
+@KeepForSubclassing
+public interface InterfaceDesugarDiagnostic extends DesugarDiagnostic {
+
+}
diff --git a/src/main/java/com/android/tools/r8/errors/InterfaceDesugarMissingTypeDiagnostic.java b/src/main/java/com/android/tools/r8/errors/InterfaceDesugarMissingTypeDiagnostic.java
new file mode 100644
index 0000000..b3f3fd6
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/errors/InterfaceDesugarMissingTypeDiagnostic.java
@@ -0,0 +1,88 @@
+// 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.errors;
+
+import com.android.tools.r8.Keep;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.references.ClassReference;
+
+/**
+ * Diagnostic for missing types needed for correct desugaring of default/static interface methods.
+ */
+@Keep
+public class InterfaceDesugarMissingTypeDiagnostic implements DesugarDiagnostic {
+
+ private final Origin origin;
+ private final Position position;
+ private final ClassReference missingType;
+ private final ClassReference contextType;
+
+ // Note: the implementing context is not yet made part of the public API as the context could be
+ // both in the implements clause or from a lambda class in a member.
+ private final ClassReference implementingContextType;
+
+ public InterfaceDesugarMissingTypeDiagnostic(
+ Origin origin,
+ Position position,
+ ClassReference missingType,
+ ClassReference contextType,
+ ClassReference implementingContextType) {
+ assert origin != null;
+ assert position != null;
+ assert missingType != null;
+ assert contextType != null;
+ this.origin = origin;
+ this.position = position;
+ this.missingType = missingType;
+ this.contextType = contextType;
+ // The implementing context is optional.
+ this.implementingContextType = implementingContextType;
+ }
+
+ /** Get the origin of a class leading to this warning. */
+ @Override
+ public Origin getOrigin() {
+ return origin;
+ }
+
+ /** Get additional position information about the context leading to this warning. */
+ @Override
+ public Position getPosition() {
+ return position;
+ }
+
+ /** Get the type that is missing. */
+ public ClassReference getMissingType() {
+ return missingType;
+ }
+
+ /** Get the type that requires knowledge of the missing type. */
+ public ClassReference getContextType() {
+ return contextType;
+ }
+
+ @Override
+ public String getDiagnosticMessage() {
+ StringBuilder builder =
+ new StringBuilder()
+ .append("Type `")
+ .append(missingType.getTypeName())
+ .append("` was not found, ")
+ .append("it is required for default or static interface methods desugaring of `");
+ if (position != Position.UNKNOWN) {
+ builder.append(position.getDescription());
+ } else {
+ builder.append(contextType.getTypeName());
+ }
+ builder.append("`");
+ if (implementingContextType != null) {
+ builder
+ .append(" This missing interface is declared in the direct hierarchy of `")
+ .append(implementingContextType)
+ .append("`");
+ }
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index b949b72..3bec073 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexLibraryClass;
import com.android.tools.r8.graph.DexMethod;
@@ -32,8 +31,8 @@
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.desugar.DefaultMethodsHelper.Collection;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.Sets;
import java.util.ListIterator;
import java.util.Map;
@@ -95,11 +94,6 @@
new ConcurrentHashMap<>();
/**
- * A set of dexitems we have reported missing to dedupe warnings.
- */
- private final Set<DexItem> reportedMissing = Sets.newConcurrentHashSet();
-
- /**
* Defines a minor variation in desugaring.
*/
public enum Flavor {
@@ -490,44 +484,14 @@
public void warnMissingInterface(
DexClass classToDesugar, DexClass implementing, DexType missing) {
- // TODO think about using a common deduplicating mechanic with Enqueuer
- if (!reportedMissing.add(missing)) {
- return;
- }
- StringBuilder builder = new StringBuilder();
- builder
- .append("Interface `")
- .append(missing.toSourceString())
- .append("` not found. It's needed to make sure desugaring of `")
- .append(classToDesugar.toSourceString())
- .append("` is correct. Desugaring will assume that this interface has no default method.");
- if (classToDesugar != implementing) {
- builder
- .append(" This missing interface is declared in the direct hierarchy of `")
- .append(implementing)
- .append("`");
- }
- options.reporter.warning(
- new StringDiagnostic(builder.toString(), classToDesugar.getOrigin()));
+ options.warningMissingInterfaceForDesugar(classToDesugar, implementing, missing);
}
private void warnMissingType(DexMethod referencedFrom, DexType missing) {
- // TODO think about using a common deduplicating mechanic with Enqueuer
- if (!reportedMissing.add(missing)) {
- return;
- }
- DexMethod originalReferencedFrom =
- appView.graphLense().getOriginalMethodSignature(referencedFrom);
- StringBuilder builder = new StringBuilder();
- builder
- .append("Type `")
- .append(missing.toSourceString())
- .append("` was not found, ")
- .append("it is required for default or static interface methods desugaring of `")
- .append(originalReferencedFrom.toSourceString())
- .append("`");
- options.reporter.warning(
- new StringDiagnostic(builder.toString(), getMethodOrigin(originalReferencedFrom)));
+ DexMethod method = appView.graphLense().getOriginalMethodSignature(referencedFrom);
+ Origin origin = getMethodOrigin(method);
+ MethodPosition position = new MethodPosition(method);
+ options.warningMissingTypeForDesugar(origin, position, missing, method.holder);
}
private Origin getMethodOrigin(DexMethod method) {
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 022a58d..ef1fb01 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -13,9 +13,12 @@
import com.android.tools.r8.Version;
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
import com.android.tools.r8.errors.InvalidDebugInfoException;
import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
@@ -23,6 +26,8 @@
import com.android.tools.r8.ir.optimize.Inliner;
import com.android.tools.r8.naming.InterfaceMethodNameMinifier;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.references.Reference;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.utils.IROrdering.IdentityIROrdering;
@@ -30,6 +35,7 @@
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
@@ -446,6 +452,37 @@
return assertionsEnabled;
}
+ /** A set of dexitems we have reported missing to dedupe warnings. */
+ private final Set<DexItem> reportedMissingForDesugaring = Sets.newConcurrentHashSet();
+
+ public void warningMissingTypeForDesugar(
+ Origin origin, Position position, DexType missingType, DexType contextType) {
+ if (reportedMissingForDesugaring.add(missingType)) {
+ reporter.warning(
+ new InterfaceDesugarMissingTypeDiagnostic(
+ origin,
+ position,
+ Reference.classFromDescriptor(missingType.toDescriptorString()),
+ Reference.classFromDescriptor(contextType.toDescriptorString()),
+ null));
+ }
+ }
+
+ public void warningMissingInterfaceForDesugar(
+ DexClass classToDesugar, DexClass implementing, DexType missing) {
+ if (reportedMissingForDesugaring.add(missing)) {
+ reporter.warning(
+ new InterfaceDesugarMissingTypeDiagnostic(
+ classToDesugar.getOrigin(),
+ Position.UNKNOWN,
+ Reference.classFromDescriptor(missing.toDescriptorString()),
+ Reference.classFromDescriptor(classToDesugar.getType().toDescriptorString()),
+ classToDesugar == implementing
+ ? null
+ : Reference.classFromDescriptor(implementing.getType().toDescriptorString())));
+ }
+ }
+
public void warningMissingEnclosingMember(DexType clazz, Origin origin, int version) {
TypeVersionPair pair = new TypeVersionPair(version, clazz);
synchronized (missingEnclosingMembers) {
diff --git a/src/test/java/com/android/tools/r8/TestCompileResult.java b/src/test/java/com/android/tools/r8/TestCompileResult.java
index 45b369a..fb68429 100644
--- a/src/test/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/TestCompileResult.java
@@ -117,6 +117,7 @@
}
public CR addRunClasspathClasses(List<Class<?>> classpath) {
+ assert getBackend() == Backend.CF;
try {
Path path = state.getNewTempFolder().resolve("runtime-classes.jar");
ArchiveConsumer consumer = new ArchiveConsumer(path);
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeClassTest.java b/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeClassTest.java
new file mode 100644
index 0000000..1269b34
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeClassTest.java
@@ -0,0 +1,113 @@
+// 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.D8TestBuilder;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessages;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.DesugarDiagnostic;
+import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DesugarMissingTypeClassTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello, world");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevels().build();
+ }
+
+ public DesugarMissingTypeClassTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ boolean supportsDefaultInterfaceMethods() {
+ return parameters.getRuntime().isCf()
+ || AndroidApiLevel.N.getLevel() <= parameters.getApiLevel().getLevel();
+ }
+
+ @Test
+ public void test() throws Exception {
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addProgramClasses(TestClass.class, MyClass.class, MissingInterface.class)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ } else {
+ D8TestBuilder builder =
+ testForD8()
+ .addProgramClasses(TestClass.class, MyClass.class)
+ .setMinApi(parameters.getApiLevel());
+ TestDiagnosticMessages messages = builder.getState().getDiagnosticsMessages();
+ D8TestCompileResult compileResult = builder.compile();
+ if (supportsDefaultInterfaceMethods()) {
+ messages.assertNoMessages();
+ compileResult
+ .addRunClasspathFiles(
+ testForD8()
+ .setMinApi(parameters.getApiLevel())
+ .addProgramClasses(MissingInterface.class)
+ .compile()
+ .writeToZip())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ } else {
+ messages.assertOnlyWarnings();
+ assertEquals(1, messages.getWarnings().size());
+ Diagnostic diagnostic = messages.getWarnings().get(0);
+ assertTrue(diagnostic instanceof DesugarDiagnostic);
+ assertTrue(diagnostic instanceof InterfaceDesugarMissingTypeDiagnostic);
+ InterfaceDesugarMissingTypeDiagnostic desugarWarning = (InterfaceDesugarMissingTypeDiagnostic) diagnostic;
+ assertEquals(
+ Reference.classFromClass(MissingInterface.class), desugarWarning.getMissingType());
+ assertEquals(Reference.classFromClass(MyClass.class), desugarWarning.getContextType());
+ assertEquals(Position.UNKNOWN, desugarWarning.getPosition());
+ }
+ }
+ }
+
+ public interface MissingInterface {
+ void foo();
+
+ default void bar() {
+ foo();
+ }
+ }
+
+ public static class MyClass implements MissingInterface {
+
+ @Override
+ public void foo() {
+ System.out.println("Hello, world");
+ }
+ }
+
+ static class TestClass {
+
+ public static void baz(MissingInterface fn) {
+ fn.bar();
+ }
+
+ public static void main(String[] args) {
+ baz(new MyClass());
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeLambdaTest.java b/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeLambdaTest.java
new file mode 100644
index 0000000..8f304c6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeLambdaTest.java
@@ -0,0 +1,107 @@
+// 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;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.D8TestBuilder;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessages;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.DesugarDiagnostic;
+import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DesugarMissingTypeLambdaTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello, world");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevels().build();
+ }
+
+ public DesugarMissingTypeLambdaTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ boolean supportsDefaultInterfaceMethods() {
+ return parameters.getRuntime().isCf()
+ || AndroidApiLevel.N.getLevel() <= parameters.getApiLevel().getLevel();
+ }
+
+ @Test
+ public void test() throws Exception {
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addProgramClasses(TestClass.class, MissingInterface.class)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ } else {
+ D8TestBuilder builder =
+ testForD8().addProgramClasses(TestClass.class).setMinApi(parameters.getApiLevel());
+ TestDiagnosticMessages messages = builder.getState().getDiagnosticsMessages();
+ D8TestCompileResult compileResult = builder.compile();
+ if (supportsDefaultInterfaceMethods()) {
+ messages.assertNoMessages();
+ compileResult
+ .addRunClasspathFiles(
+ testForD8()
+ .setMinApi(parameters.getApiLevel())
+ .addProgramClasses(MissingInterface.class)
+ .compile()
+ .writeToZip())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ } else {
+ messages.assertOnlyWarnings();
+ assertEquals(1, messages.getWarnings().size());
+ Diagnostic diagnostic = messages.getWarnings().get(0);
+ assertTrue(diagnostic instanceof DesugarDiagnostic);
+ assertTrue(diagnostic instanceof InterfaceDesugarMissingTypeDiagnostic);
+ InterfaceDesugarMissingTypeDiagnostic desugarWarning = (InterfaceDesugarMissingTypeDiagnostic) diagnostic;
+ assertEquals(
+ Reference.classFromClass(MissingInterface.class), desugarWarning.getMissingType());
+ // TODO(b/132671303): The context class should not be the synthesized lambda class.
+ assertThat(desugarWarning.getContextType().getDescriptor(), containsString("$$Lambda"));
+ // TODO(b/132671303): The position info should be the method context.
+ assertEquals(Position.UNKNOWN, desugarWarning.getPosition());
+ }
+ }
+ }
+
+ public interface MissingInterface {
+ void foo();
+
+ default void bar() {
+ foo();
+ }
+ }
+
+ static class TestClass {
+
+ public static void baz(MissingInterface fn) {
+ fn.bar();
+ }
+
+ public static void main(String[] args) {
+ baz(() -> System.out.println("Hello, world"));
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeStaticInvokeTest.java b/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeStaticInvokeTest.java
new file mode 100644
index 0000000..7422eb8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeStaticInvokeTest.java
@@ -0,0 +1,100 @@
+// 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;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.D8TestBuilder;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessages;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.DesugarDiagnostic;
+import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DesugarMissingTypeStaticInvokeTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello, world");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevels().build();
+ }
+
+ public DesugarMissingTypeStaticInvokeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ boolean supportsDefaultInterfaceMethods() {
+ return parameters.getRuntime().isCf()
+ || AndroidApiLevel.N.getLevel() <= parameters.getApiLevel().getLevel();
+ }
+
+ @Test
+ public void test() throws Exception {
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addProgramClasses(TestClass.class, MissingInterface.class)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ } else {
+ D8TestBuilder builder =
+ testForD8().addProgramClasses(TestClass.class).setMinApi(parameters.getApiLevel());
+ TestDiagnosticMessages messages = builder.getState().getDiagnosticsMessages();
+ D8TestCompileResult compileResult = builder.compile();
+ if (supportsDefaultInterfaceMethods()) {
+ messages.assertNoMessages();
+ compileResult
+ .addRunClasspathFiles(
+ testForD8()
+ .setMinApi(parameters.getApiLevel())
+ .addProgramClasses(MissingInterface.class)
+ .compile()
+ .writeToZip())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ } else {
+ messages.assertOnlyWarnings();
+ assertEquals(1, messages.getWarnings().size());
+ Diagnostic diagnostic = messages.getWarnings().get(0);
+ assertTrue(diagnostic instanceof DesugarDiagnostic);
+ assertTrue(diagnostic instanceof InterfaceDesugarMissingTypeDiagnostic);
+ InterfaceDesugarMissingTypeDiagnostic desugarWarning = (InterfaceDesugarMissingTypeDiagnostic) diagnostic;
+ assertEquals(
+ Reference.classFromClass(MissingInterface.class), desugarWarning.getMissingType());
+ assertEquals(Reference.classFromClass(TestClass.class), desugarWarning.getContextType());
+ assertThat(
+ desugarWarning.getPosition().getDescription(),
+ containsString(TestClass.class.getTypeName() + ".main"));
+ }
+ }
+ }
+
+ public interface MissingInterface {
+ static void foo() {
+ System.out.println("Hello, world");
+ }
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ MissingInterface.foo();
+ }
+ }
+}