Provide more information on the MissingDefinitionsDiagnostic
Add access to the references for the missing items.
Bug: 169127026
Change-Id: I5bf5f05b341dd53e43755a87f122ec999e7e0e15
diff --git a/src/main/java/com/android/tools/r8/tracereferences/MissingDefinitionsDiagnostic.java b/src/main/java/com/android/tools/r8/tracereferences/MissingDefinitionsDiagnostic.java
index 8fd9edb..12a2462 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/MissingDefinitionsDiagnostic.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/MissingDefinitionsDiagnostic.java
@@ -7,10 +7,9 @@
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.tracereferences.Tracer.TracedClassImpl;
-import com.android.tools.r8.tracereferences.Tracer.TracedFieldImpl;
-import com.android.tools.r8.tracereferences.Tracer.TracedMethodImpl;
-import com.android.tools.r8.tracereferences.Tracer.TracedReferenceBase;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.FieldReference;
+import com.android.tools.r8.references.MethodReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -18,14 +17,14 @@
@Keep
public class MissingDefinitionsDiagnostic implements Diagnostic {
- private final Set<TracedClassImpl> missingClasses;
- private final Set<TracedFieldImpl> missingFields;
- private final Set<TracedMethodImpl> missingMethods;
+ private final Set<ClassReference> missingClasses;
+ private final Set<FieldReference> missingFields;
+ private final Set<MethodReference> missingMethods;
MissingDefinitionsDiagnostic(
- Set<TracedClassImpl> missingClasses,
- Set<TracedFieldImpl> missingFields,
- Set<TracedMethodImpl> missingMethods) {
+ Set<ClassReference> missingClasses,
+ Set<FieldReference> missingFields,
+ Set<MethodReference> missingMethods) {
this.missingClasses = missingClasses;
this.missingFields = missingFields;
this.missingMethods = missingMethods;
@@ -41,15 +40,25 @@
return Position.UNKNOWN;
}
- private <T extends TracedReferenceBase<?, ?>> void appendSorted(
- StringBuilder builder, Set<T> missing) {
+ private <T> void appendSorted(StringBuilder builder, Set<T> missing) {
missing.stream()
- .map(element -> element.getReference())
.map(Object::toString)
.sorted()
.forEach(item -> builder.append(" ").append(item).append(System.lineSeparator()));
}
+ public Set<ClassReference> getMissingClasses() {
+ return missingClasses;
+ }
+
+ public Set<FieldReference> getMissingFields() {
+ return missingFields;
+ }
+
+ public Set<MethodReference> getMissingMethods() {
+ return missingMethods;
+ }
+
@Override
public String getDiagnosticMessage() {
StringBuilder builder = new StringBuilder("Tracereferences found ");
diff --git a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
index 8b571a8..539ac24 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
@@ -259,9 +259,9 @@
private final TraceReferencesConsumer consumer;
private DexProgramClass context;
private final DiagnosticsHandler diagnostics;
- private final Set<TracedClassImpl> missingClasses = new HashSet<>();
- private final Set<TracedFieldImpl> missingFields = new HashSet<>();
- private final Set<TracedMethodImpl> missingMethods = new HashSet<>();
+ private final Set<ClassReference> missingClasses = new HashSet<>();
+ private final Set<FieldReference> missingFields = new HashSet<>();
+ private final Set<MethodReference> missingMethods = new HashSet<>();
UseCollector(
DexItemFactory factory, TraceReferencesConsumer consumer, DiagnosticsHandler diagnostics) {
@@ -347,10 +347,10 @@
collectMissing(tracedMethod, missingMethods);
}
- private <T extends TracedReferenceBase<?, ?>> void collectMissing(
- T tracedReference, Set<T> missingCollection) {
+ private <R, T extends TracedReferenceBase<R, ?>> void collectMissing(
+ T tracedReference, Set<R> missingCollection) {
if (tracedReference.isMissingDefinition()) {
- missingCollection.add(tracedReference);
+ missingCollection.add(tracedReference.getReference());
}
}
diff --git a/src/test/java/com/android/tools/r8/DiagnosticsChecker.java b/src/test/java/com/android/tools/r8/DiagnosticsChecker.java
index 09e32da..bda7fe1 100644
--- a/src/test/java/com/android/tools/r8/DiagnosticsChecker.java
+++ b/src/test/java/com/android/tools/r8/DiagnosticsChecker.java
@@ -48,7 +48,7 @@
void run(DiagnosticsHandler handler) throws CompilationFailedException;
}
- private static void checkContains(String snippet, List<Diagnostic> diagnostics) {
+ public static void checkContains(String snippet, List<Diagnostic> diagnostics) {
List<String> messages = ListUtils.map(diagnostics, Diagnostic::getDiagnosticMessage);
System.out.println("Expecting match for '" + snippet + "'");
System.out.println("StdErr:\n" + messages);
@@ -60,6 +60,10 @@
diagnostics.stream().anyMatch(d -> d.getDiagnosticMessage().contains(snippet)));
}
+ public static void checkContains(Collection<String> snippets, List<Diagnostic> diagnostics) {
+ snippets.forEach(snippet -> checkContains(snippet, diagnostics));
+ }
+
public void checkErrorsContains(String snippet) {
checkContains(snippet, errors);
}
@@ -84,7 +88,20 @@
runner.run(handler);
fail("Failure expected");
} catch (CompilationFailedException e) {
- snippets.forEach(snippet -> checkContains(snippet, handler.errors));
+ checkContains(snippets, handler.errors);
+ throw e;
+ }
+ }
+
+ public static void checkErrorDiagnostics(
+ Consumer<DiagnosticsChecker> checker, FailingRunner runner)
+ throws CompilationFailedException {
+ DiagnosticsChecker handler = new DiagnosticsChecker();
+ try {
+ runner.run(handler);
+ fail("Failure expected");
+ } catch (CompilationFailedException e) {
+ checker.accept(handler);
throw e;
}
}
diff --git a/src/test/java/com/android/tools/r8/tracereferences/TraceReferencesDiagnosticTest.java b/src/test/java/com/android/tools/r8/tracereferences/TraceReferencesDiagnosticTest.java
index 551c8a1..cad4538 100644
--- a/src/test/java/com/android/tools/r8/tracereferences/TraceReferencesDiagnosticTest.java
+++ b/src/test/java/com/android/tools/r8/tracereferences/TraceReferencesDiagnosticTest.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.tracereferences;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.android.tools.r8.CompilationFailedException;
@@ -12,13 +14,16 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import java.nio.file.Path;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -60,25 +65,55 @@
.build();
String prefix = " Lcom/android/tools/r8/tracereferences/TraceReferencesDiagnosticTest$";
+ List<String> snippets =
+ ImmutableList.of(
+ "Tracereferences found 3 classe(s), 2 field(s) and 4 method(s) without definition",
+ StringUtils.lines(
+ "Classe(s) without definition:",
+ prefix + "Target1;",
+ prefix + "Target2;",
+ prefix + "Target3;"),
+ StringUtils.lines(
+ "Field(s) without definition:",
+ prefix + "Target;missingField1:I",
+ prefix + "Target;missingField2:I"),
+ StringUtils.lines(
+ "Method(s) without definition:",
+ prefix + "Target1;<init>()V",
+ prefix + "Target2;<init>()V",
+ prefix + "Target3;<init>()V",
+ prefix + "Target;missingMethod()V"));
try {
- DiagnosticsChecker.checkErrorsContains(
- ImmutableList.of(
- "Tracereferences found 3 classe(s), 2 field(s) and 4 method(s) without definition",
- StringUtils.lines(
- "Classe(s) without definition:",
- prefix + "Target1;",
- prefix + "Target2;",
- prefix + "Target3;"),
- StringUtils.lines(
- "Field(s) without definition:",
- prefix + "Target;missingField1:I",
- prefix + "Target;missingField2:I"),
- StringUtils.lines(
- "Method(s) without definition:",
- prefix + "Target1;<init>()V",
- prefix + "Target2;<init>()V",
- prefix + "Target3;<init>()V",
- prefix + "Target;missingMethod()V")),
+ DiagnosticsChecker.checkErrorDiagnostics(
+ checker -> {
+ DiagnosticsChecker.checkContains(snippets, checker.errors);
+ try {
+ assertEquals(1, checker.errors.size());
+ assertTrue(checker.errors.get(0) instanceof MissingDefinitionsDiagnostic);
+ MissingDefinitionsDiagnostic diagnostic =
+ (MissingDefinitionsDiagnostic) checker.errors.get(0);
+ assertEquals(
+ diagnostic.getMissingClasses(),
+ ImmutableSet.of(
+ Reference.classFromClass(Target1.class),
+ Reference.classFromClass(Target2.class),
+ Reference.classFromClass(Target3.class)));
+ assertEquals(
+ diagnostic.getMissingFields(),
+ ImmutableSet.of(
+ Reference.fieldFromField(Target.class.getField("missingField1")),
+ Reference.fieldFromField(Target.class.getField("missingField2"))));
+ assertEquals(
+ diagnostic.getMissingMethods(),
+ ImmutableSet.of(
+ Reference.methodFromMethod(Target1.class.getDeclaredConstructor()),
+ Reference.methodFromMethod(Target2.class.getDeclaredConstructor()),
+ Reference.methodFromMethod(Target3.class.getDeclaredConstructor()),
+ Reference.methodFromMethod(Target.class.getMethod("missingMethod"))));
+ } catch (ReflectiveOperationException e) {
+ fail("Unexpected exception");
+ }
+ },
handler ->
TraceReferences.run(
TraceReferencesCommand.builder(handler)
@@ -125,16 +160,37 @@
.build();
String prefix = " Lcom/android/tools/r8/tracereferences/TraceReferencesDiagnosticTest$";
+ List<String> snippets =
+ ImmutableList.of(
+ "Tracereferences found 2 field(s) and 1 method(s) without definition",
+ StringUtils.lines(
+ "Field(s) without definition:",
+ prefix + "Target;missingField1:I",
+ prefix + "Target;missingField2:I"),
+ StringUtils.lines("Method(s) without definition:", prefix + "Target;missingMethod()V"));
try {
- DiagnosticsChecker.checkErrorsContains(
- ImmutableList.of(
- "Tracereferences found 2 field(s) and 1 method(s) without definition",
- StringUtils.lines(
- "Field(s) without definition:",
- prefix + "Target;missingField1:I",
- prefix + "Target;missingField2:I"),
- StringUtils.lines(
- "Method(s) without definition:", prefix + "Target;missingMethod()V")),
+ DiagnosticsChecker.checkErrorDiagnostics(
+ checker -> {
+ DiagnosticsChecker.checkContains(snippets, checker.errors);
+ try {
+ assertEquals(1, checker.errors.size());
+ assertTrue(checker.errors.get(0) instanceof MissingDefinitionsDiagnostic);
+ MissingDefinitionsDiagnostic diagnostic =
+ (MissingDefinitionsDiagnostic) checker.errors.get(0);
+ assertEquals(diagnostic.getMissingClasses(), ImmutableSet.of());
+ assertEquals(
+ diagnostic.getMissingFields(),
+ ImmutableSet.of(
+ Reference.fieldFromField(Target.class.getField("missingField1")),
+ Reference.fieldFromField(Target.class.getField("missingField2"))));
+ assertEquals(
+ diagnostic.getMissingMethods(),
+ ImmutableSet.of(
+ Reference.methodFromMethod(Target.class.getMethod("missingMethod"))));
+ } catch (ReflectiveOperationException e) {
+ fail("Unexpected exception");
+ }
+ },
handler ->
TraceReferences.run(
TraceReferencesCommand.builder(handler)
@@ -175,12 +231,29 @@
.build();
String prefix = " Lcom/android/tools/r8/tracereferences/TraceReferencesDiagnosticTest$";
+ List<String> snippets =
+ ImmutableList.of(
+ "Tracereferences found 1 method(s) without definition",
+ StringUtils.lines("Method(s) without definition:", prefix + "Target;missingMethod()V"));
try {
- DiagnosticsChecker.checkErrorsContains(
- ImmutableList.of(
- "Tracereferences found 1 method(s) without definition",
- StringUtils.lines(
- "Method(s) without definition:", prefix + "Target;missingMethod()V")),
+ DiagnosticsChecker.checkErrorDiagnostics(
+ checker -> {
+ DiagnosticsChecker.checkContains(snippets, checker.errors);
+ try {
+ assertEquals(1, checker.errors.size());
+ assertTrue(checker.errors.get(0) instanceof MissingDefinitionsDiagnostic);
+ MissingDefinitionsDiagnostic diagnostic =
+ (MissingDefinitionsDiagnostic) checker.errors.get(0);
+ assertEquals(diagnostic.getMissingClasses(), ImmutableSet.of());
+ assertEquals(diagnostic.getMissingFields(), ImmutableSet.of());
+ assertEquals(
+ diagnostic.getMissingMethods(),
+ ImmutableSet.of(
+ Reference.methodFromMethod(Target.class.getMethod("missingMethod"))));
+ } catch (ReflectiveOperationException e) {
+ fail("Unexpected exception");
+ }
+ },
handler ->
TraceReferences.run(
TraceReferencesCommand.builder(handler)