[Retrace] Add comparison of ambiguous frame results
Bug: 170797525
Change-Id: I174c39f60bfe3f79bf8e1bb9e6704e38d5fb42a8
diff --git a/src/main/java/com/android/tools/r8/retrace/Retrace.java b/src/main/java/com/android/tools/r8/retrace/Retrace.java
index e64d8e0..d9dd386 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -18,7 +18,9 @@
import com.android.tools.r8.retrace.internal.RetraceRegularExpression;
import com.android.tools.r8.retrace.internal.RetracerImpl;
import com.android.tools.r8.retrace.internal.StackTraceElementProxyRetracerImpl;
+import com.android.tools.r8.retrace.internal.StackTraceElementProxyRetracerImpl.RetraceStackTraceProxyImpl;
import com.android.tools.r8.retrace.internal.StackTraceElementStringProxy;
+import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.OptionsParsing;
import com.android.tools.r8.utils.OptionsParsing.ParseContext;
@@ -35,7 +37,9 @@
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Scanner;
/**
@@ -186,20 +190,42 @@
List<String> retracedStrings = new ArrayList<>();
plainStackTraceVisitor.forEach(
stackTraceElement -> {
- List<String> retracedStringsForElement = new ArrayList<>();
+ Box<List<RetraceStackTraceProxyImpl<StackTraceElementStringProxy>>> currentList =
+ new Box<>();
+ Map<
+ RetraceStackTraceProxyImpl<StackTraceElementStringProxy>,
+ List<RetraceStackTraceProxyImpl<StackTraceElementStringProxy>>>
+ ambiguousBlocks = new HashMap<>();
proxyRetracer
.retrace(stackTraceElement)
.forEach(
retracedElement -> {
- StackTraceElementStringProxy originalItem =
- retracedElement.getOriginalItem();
- retracedStringsForElement.add(
- originalItem.toRetracedItem(
- retracedElement,
- !retracedStringsForElement.isEmpty(),
- command.isVerbose));
+ if (retracedElement.isTopFrame() || !retracedElement.hasRetracedClass()) {
+ List<RetraceStackTraceProxyImpl<StackTraceElementStringProxy>> block =
+ new ArrayList<>();
+ ambiguousBlocks.put(retracedElement, block);
+ currentList.set(block);
+ }
+ currentList.get().add(retracedElement);
});
- retracedStrings.addAll(retracedStringsForElement);
+ ambiguousBlocks.keySet().stream()
+ .sorted()
+ .forEach(
+ topFrame -> {
+ ambiguousBlocks
+ .get(topFrame)
+ .forEach(
+ frame -> {
+ StackTraceElementStringProxy originalItem =
+ frame.getOriginalItem();
+ retracedStrings.add(
+ originalItem.toRetracedItem(
+ frame, !currentList.isSet(), command.isVerbose));
+ // Use the current list as indicator for us seeing the first
+ // sorted element.
+ currentList.set(null);
+ });
+ });
});
result = new RetraceCommandLineResult(retracedStrings);
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceProxy.java b/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceProxy.java
index b69c237..ebae15c 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceProxy.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceProxy.java
@@ -7,10 +7,13 @@
import com.android.tools.r8.Keep;
@Keep
-public interface RetraceStackTraceProxy<T extends StackTraceElementProxy<?>> {
+public interface RetraceStackTraceProxy<T extends StackTraceElementProxy<?>>
+ extends Comparable<RetraceStackTraceProxy<T>> {
boolean isAmbiguous();
+ boolean isTopFrame();
+
boolean hasRetracedClass();
boolean hasRetracedMethod();
diff --git a/src/main/java/com/android/tools/r8/retrace/RetracedMethod.java b/src/main/java/com/android/tools/r8/retrace/RetracedMethod.java
index bfc95e9..936ea3e 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetracedMethod.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetracedMethod.java
@@ -10,7 +10,7 @@
import java.util.List;
@Keep
-public interface RetracedMethod extends RetracedClassMember {
+public interface RetracedMethod extends RetracedClassMember, Comparable<RetracedMethod> {
boolean isUnknown();
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetracedMethodImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetracedMethodImpl.java
index 998fe7d..1f4ad68 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetracedMethodImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetracedMethodImpl.java
@@ -8,6 +8,8 @@
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.retrace.RetracedMethod;
+import com.android.tools.r8.utils.ComparatorUtils;
+import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -34,6 +36,27 @@
return null;
}
+ @Override
+ public int compareTo(RetracedMethod other) {
+ return Comparator.comparing(RetracedMethod::getMethodName)
+ .thenComparing(RetracedMethod::isKnown)
+ .thenComparing(
+ RetracedMethod::asKnown,
+ Comparator.nullsFirst(
+ Comparator.comparing(
+ (KnownRetracedMethod m) -> {
+ if (m == null) {
+ return null;
+ }
+ return m.isVoid() ? "void" : m.getReturnType().getTypeName();
+ }))
+ .thenComparing(
+ KnownRetracedMethod::getFormalTypes,
+ ComparatorUtils.listComparator(
+ Comparator.comparing(TypeReference::getTypeName))))
+ .compare(this, other);
+ }
+
public static final class KnownRetracedMethodImpl extends RetracedMethodImpl
implements KnownRetracedMethod {
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java
index c21b92d..458978d 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java
@@ -37,7 +37,8 @@
RetraceStackTraceProxyImpl.Builder<T> proxy =
RetraceStackTraceProxyImpl.builder(element)
.setRetracedClassElement(classElement.getRetracedClass())
- .setAmbiguous(classResult.isAmbiguous());
+ .setAmbiguous(classResult.isAmbiguous())
+ .setTopFrame(true);
if (element.hasFileName()) {
proxy.setSourceFile(classElement.retraceSourceFile(element.fileName()).getFilename());
}
@@ -56,7 +57,8 @@
RetraceStackTraceProxyImpl.builder(element)
.setRetracedClassElement(frame.getHolderClass())
.setRetracedMethodElement(frame)
- .setAmbiguous(frameResult.isAmbiguous() && index == 0);
+ .setAmbiguous(frameResult.isAmbiguous() && index == 0)
+ .setTopFrame(index == 0);
if (element.hasLineNumber()) {
proxy.setLineNumber(frame.getOriginalPositionOrDefault(element.lineNumber()));
}
@@ -80,6 +82,7 @@
private final String sourceFile;
private final int lineNumber;
private final boolean isAmbiguous;
+ private final boolean isTopFrame;
private RetraceStackTraceProxyImpl(
T originalItem,
@@ -87,7 +90,8 @@
RetracedMethod retracedMethod,
String sourceFile,
int lineNumber,
- boolean isAmbiguous) {
+ boolean isAmbiguous,
+ boolean isTopFrame) {
assert originalItem != null;
this.originalItem = originalItem;
this.retracedClass = retracedClass;
@@ -95,6 +99,7 @@
this.sourceFile = sourceFile;
this.lineNumber = lineNumber;
this.isAmbiguous = isAmbiguous;
+ this.isTopFrame = isTopFrame;
}
@Override
@@ -103,6 +108,11 @@
}
@Override
+ public boolean isTopFrame() {
+ return isTopFrame;
+ }
+
+ @Override
public boolean hasRetracedClass() {
return retracedClass != null;
}
@@ -151,6 +161,49 @@
return lineNumber;
}
+ @Override
+ public int compareTo(RetraceStackTraceProxy<T> other) {
+ int classCompare = Boolean.compare(hasRetracedClass(), other.hasRetracedClass());
+ if (classCompare != 0) {
+ return classCompare;
+ }
+ if (hasRetracedClass()) {
+ classCompare =
+ getRetracedClass().getTypeName().compareTo(other.getRetracedClass().getTypeName());
+ if (classCompare != 0) {
+ return classCompare;
+ }
+ }
+ int methodCompare = Boolean.compare(hasRetracedMethod(), other.hasRetracedMethod());
+ if (methodCompare != 0) {
+ return methodCompare;
+ }
+ if (hasRetracedMethod()) {
+ methodCompare = getRetracedMethod().compareTo(other.getRetracedMethod());
+ if (methodCompare != 0) {
+ return methodCompare;
+ }
+ }
+ int sourceFileCompare = Boolean.compare(hasSourceFile(), other.hasSourceFile());
+ if (sourceFileCompare != 0) {
+ return sourceFileCompare;
+ }
+ if (hasSourceFile()) {
+ sourceFileCompare = getSourceFile().compareTo(other.getSourceFile());
+ if (sourceFileCompare != 0) {
+ return sourceFileCompare;
+ }
+ }
+ int lineNumberCompare = Boolean.compare(hasLineNumber(), other.hasLineNumber());
+ if (lineNumberCompare != 0) {
+ return lineNumberCompare;
+ }
+ if (hasLineNumber()) {
+ return Integer.compare(lineNumber, other.getLineNumber());
+ }
+ return 0;
+ }
+
private static class Builder<T extends StackTraceElementProxy<?>> {
private final T originalElement;
@@ -159,6 +212,7 @@
private String sourceFile;
private int lineNumber = -1;
private boolean isAmbiguous;
+ private boolean isTopFrame;
private Builder(T originalElement) {
this.originalElement = originalElement;
@@ -189,6 +243,11 @@
return this;
}
+ private Builder<T> setTopFrame(boolean topFrame) {
+ isTopFrame = topFrame;
+ return this;
+ }
+
private RetraceStackTraceProxyImpl<T> build() {
RetracedClass retracedClass = classContext;
if (methodContext != null) {
@@ -200,7 +259,8 @@
methodContext,
sourceFile != null ? sourceFile : null,
lineNumber,
- isAmbiguous);
+ isAmbiguous,
+ isTopFrame);
}
}
}
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
index edcb118..82d3915 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
@@ -10,7 +10,6 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestDiagnosticMessagesImpl;
@@ -136,15 +135,11 @@
@Test
public void testAmbiguousStackTrace() {
- // TODO(b/170797525): Remove when we have a fixed ordering.
- assumeTrue(useRegExpParsing);
runRetraceTest(new AmbiguousStackTrace());
}
@Test
public void testAmbiguousMissingLineStackTrace() {
- // TODO(b/170797525): Remove when we have a fixed ordering.
- assumeTrue(useRegExpParsing);
runRetraceTest(new AmbiguousMissingLineStackTrace());
}
@@ -190,8 +185,6 @@
@Test
public void testUnknownSourceStackTrace() {
- // TODO(b/170797525): Remove when we have a fixed ordering.
- assumeTrue(useRegExpParsing);
runRetraceTest(new UnknownSourceStackTrace());
}
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceVerboseTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceVerboseTests.java
index fb65c1d..2e75b1d 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceVerboseTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceVerboseTests.java
@@ -6,6 +6,7 @@
import static com.android.tools.r8.retrace.Retrace.DEFAULT_REGULAR_EXPRESSION;
import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assume.assumeFalse;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestDiagnosticMessagesImpl;
@@ -53,6 +54,8 @@
@Test
public void testAmbiguousMissingLineVerbose() {
+ // TODO(b/169346455): Enable when separated parser.
+ assumeFalse(useRegExpParsing);
runRetraceTest(new AmbiguousWithSignatureVerboseStackTrace());
}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java
index 1dfb3c9..45c103f 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java
@@ -33,10 +33,10 @@
return Arrays.asList(
"java.lang.IndexOutOfBoundsException",
"\tat java.util.ArrayList.get(ArrayList.java:411)",
- "\tat com.android.tools.r8.Internal.void foo(int)(Internal.java)",
- "\t<OR> at com.android.tools.r8.Internal.void foo(int,int)(Internal.java)",
+ "\tat com.android.tools.r8.Internal.boolean foo(int,int)(Internal.java)",
+ "\t<OR> at com.android.tools.r8.Internal.void foo(int)(Internal.java)",
"\t<OR> at com.android.tools.r8.Internal.void foo(int,boolean)(Internal.java)",
- "\t<OR> at com.android.tools.r8.Internal.boolean foo(int,int)(Internal.java)");
+ "\t<OR> at com.android.tools.r8.Internal.void foo(int,int)(Internal.java)");
}
@Override