[Retrace] Retrace single positions lines if no stack trace position
Bug: 191513686
Change-Id: If602b7cad667c270544a453bc59355dd9e5ac14f
diff --git a/src/main/java/com/android/tools/r8/retrace/StringRetrace.java b/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
index f6636c1..4bdb42c 100644
--- a/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.Keep;
import com.android.tools.r8.retrace.internal.StackTraceElementStringProxy;
+import com.android.tools.r8.utils.ListUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -97,28 +98,29 @@
// The result is empty, likely it maps to compiler synthesized items.
return;
}
- List<String> initialResult = retracedResult.get(0);
- initialResult.forEach(joinedConsumer);
- if (retracedResult.size() <= 1) {
- // The result is not ambiguous.
- return;
- }
- Set<String> reportedFrames = new HashSet<>(initialResult);
- for (int i = 1; i < retracedResult.size(); i++) {
- List<String> ambiguousResult = retracedResult.get(i);
- assert !ambiguousResult.isEmpty();
- String topFrame = ambiguousResult.get(0);
- if (reportedFrames.add(topFrame)) {
- ambiguousResult.forEach(
- retracedString -> {
- int firstCharIndex = firstNonWhiteSpaceCharacterFromIndex(retracedString, 0);
- retracedString =
- retracedString.substring(0, firstCharIndex)
- + "<OR> "
- + retracedString.substring(firstCharIndex);
- joinedConsumer.accept(retracedString);
- });
- }
- }
+ Set<String> reportedFrames = new HashSet<>();
+ ListUtils.forEachWithIndex(
+ retracedResult,
+ (potentialResults, index) -> {
+ assert !potentialResults.isEmpty();
+ // Check if we already reported position.
+ if (reportedFrames.add(potentialResults.get(0))) {
+ boolean isAmbiguous = potentialResults != retracedResult.get(0);
+ potentialResults.forEach(
+ retracedString -> {
+ if (isAmbiguous) {
+ int firstCharIndex = firstNonWhiteSpaceCharacterFromIndex(retracedString, 0);
+ joinedConsumer.accept(
+ retracedString.substring(0, firstCharIndex)
+ + "<OR #"
+ + (index)
+ + "> "
+ + retracedString.substring(firstCharIndex));
+ } else {
+ joinedConsumer.accept(retracedString);
+ }
+ });
+ }
+ });
}
}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
index 82717b1..edde5ab 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.retrace.Retracer;
import com.android.tools.r8.retrace.internal.RetraceClassResultImpl.RetraceClassElementImpl;
import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.Pair;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -34,6 +35,8 @@
private final List<Pair<RetraceClassElementImpl, List<MappedRange>>> mappedRanges;
private final Retracer retracer;
+ private OptionalBool isAmbiguousCache = OptionalBool.UNKNOWN;
+
public RetraceFrameResultImpl(
RetraceClassResultImpl classResult,
List<Pair<RetraceClassElementImpl, List<MappedRange>>> mappedRanges,
@@ -49,22 +52,27 @@
@Override
public boolean isAmbiguous() {
- if (mappedRanges.size() > 1) {
- return true;
- }
- List<MappedRange> methodRanges = mappedRanges.get(0).getSecond();
- if (methodRanges == null || methodRanges.isEmpty()) {
- return false;
- }
- MappedRange lastRange = methodRanges.get(0);
- for (MappedRange mappedRange : methodRanges) {
- if (mappedRange != lastRange
- && (mappedRange.minifiedRange == null
- || !mappedRange.minifiedRange.equals(lastRange.minifiedRange))) {
+ if (isAmbiguousCache.isUnknown()) {
+ if (mappedRanges.size() > 1) {
+ isAmbiguousCache = OptionalBool.TRUE;
return true;
}
+ List<MappedRange> methodRanges = mappedRanges.get(0).getSecond();
+ if (methodRanges != null && !methodRanges.isEmpty()) {
+ MappedRange lastRange = methodRanges.get(0);
+ for (MappedRange mappedRange : methodRanges) {
+ if (mappedRange != lastRange
+ && (mappedRange.minifiedRange == null
+ || !mappedRange.minifiedRange.equals(lastRange.minifiedRange))) {
+ isAmbiguousCache = OptionalBool.TRUE;
+ return true;
+ }
+ }
+ }
+ isAmbiguousCache = OptionalBool.FALSE;
}
- return false;
+ assert !isAmbiguousCache.isUnknown();
+ return isAmbiguousCache.isTrue();
}
@Override
@@ -120,12 +128,12 @@
private RetracedMethodReferenceImpl getRetracedMethod(
MethodReference methodReference, MappedRange mappedRange, int obfuscatedPosition) {
- if (mappedRange.minifiedRange == null) {
+ if (mappedRange.minifiedRange == null || (obfuscatedPosition == -1 && !isAmbiguous())) {
int originalLineNumber = mappedRange.getFirstLineNumberOfOriginalRange();
return RetracedMethodReferenceImpl.create(
methodReference, originalLineNumber > 0 ? originalLineNumber : obfuscatedPosition);
}
- if (obfuscatedPosition == -1 || !mappedRange.minifiedRange.contains(obfuscatedPosition)) {
+ if (!mappedRange.minifiedRange.contains(obfuscatedPosition)) {
return RetracedMethodReferenceImpl.create(methodReference);
}
return RetracedMethodReferenceImpl.create(
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementStringProxy.java b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementStringProxy.java
index 33a0ea1..5f512f4 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementStringProxy.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementStringProxy.java
@@ -114,7 +114,11 @@
return -1;
}
try {
- return Integer.parseInt(getEntryInLine(lineNumber));
+ String lineNumberString = getEntryInLine(lineNumber);
+ if (lineNumberString.isEmpty()) {
+ return -1;
+ }
+ return Integer.parseInt(lineNumberString);
} catch (NumberFormatException nfe) {
return -1;
}
@@ -226,15 +230,16 @@
return this;
}
- public StackTraceElementStringProxyBuilder registerLineNumber(int startIndex, int endIndex) {
+ public StackTraceElementStringProxyBuilder registerLineNumber(
+ int startIndex, int endIndex, boolean insertSeparatorForRetraced) {
lineNumber =
new StringIndex(
startIndex,
endIndex,
(retraced, original, verbose) ->
- retraced.hasLineNumber()
- ? retraced.getLineNumber() + ""
- : original.lineNumberAsString());
+ (retraced.hasLineNumber()
+ ? ((insertSeparatorForRetraced ? ":" : "") + retraced.getLineNumber())
+ : original.lineNumberAsString()));
orderedIndices.add(lineNumber);
return this;
}
@@ -296,6 +301,9 @@
}
public StackTraceElementStringProxy build() {
+ if (!lineNumber.hasIndex() && sourceFile.hasIndex()) {
+ registerLineNumber(sourceFile.endIndex, sourceFile.endIndex, true);
+ }
return new StackTraceElementStringProxy(
line,
orderedIndices,
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceRegularExpressionParser.java b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceRegularExpressionParser.java
index fc8d5d9..e26e351 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceRegularExpressionParser.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceRegularExpressionParser.java
@@ -309,7 +309,7 @@
if (startOfGroup == NO_MATCH) {
return false;
}
- builder.registerLineNumber(startOfGroup, matcher.end(captureGroup));
+ builder.registerLineNumber(startOfGroup, matcher.end(captureGroup), false);
return true;
};
}
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 4506755..8cc0883 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
@@ -35,6 +35,7 @@
import com.android.tools.r8.retrace.stacktraces.InvalidStackTrace;
import com.android.tools.r8.retrace.stacktraces.MemberFieldOverlapStackTrace;
import com.android.tools.r8.retrace.stacktraces.MultipleDotsInFileNameStackTrace;
+import com.android.tools.r8.retrace.stacktraces.MultipleLinesNoLineNumberStackTrace;
import com.android.tools.r8.retrace.stacktraces.NamedModuleStackTrace;
import com.android.tools.r8.retrace.stacktraces.NoObfuscatedLineNumberWithOverrideTest;
import com.android.tools.r8.retrace.stacktraces.NoObfuscationRangeMappingWithStackTrace;
@@ -276,6 +277,11 @@
runRetraceTest(new SingleLineNoLineNumberStackTrace());
}
+ @Test
+ public void testMultipleLinesNoLineNumberStackTrace() throws Exception {
+ runRetraceTest(new MultipleLinesNoLineNumberStackTrace());
+ }
+
private void inspectRetraceTest(
StackTraceForTest stackTraceForTest, Consumer<Retracer> inspection) {
inspection.accept(
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMissingLineStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMissingLineStackTrace.java
index b92190e..310390c 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMissingLineStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMissingLineStackTrace.java
@@ -27,13 +27,13 @@
return Arrays.asList(
"com.android.tools.r8.CompilationException: foo[parens](Source:3)",
" at com.android.tools.r8.R8.bar(R8.java:7)",
- " <OR> at com.android.tools.r8.R8.foo(R8.java:7)",
+ " <OR #1> at com.android.tools.r8.R8.foo(R8.java:7)",
" at com.android.tools.r8.R8.bar(R8.java:8)",
- " <OR> at com.android.tools.r8.R8.foo(R8.java:8)",
+ " <OR #1> at com.android.tools.r8.R8.foo(R8.java:8)",
" at com.android.tools.r8.R8.main(Unknown Source)",
"Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
" at com.android.tools.r8.R8.bar(R8.java:9)",
- " <OR> at com.android.tools.r8.R8.foo(R8.java:9)",
+ " <OR #1> at com.android.tools.r8.R8.foo(R8.java:9)",
" ... 42 more");
}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousStackTrace.java
index 429ee6b..38fbb08 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousStackTrace.java
@@ -54,13 +54,13 @@
return Arrays.asList(
"com.android.tools.r8.CompilationException: foo[parens](Source:3)",
" at com.android.tools.r8.R8.bar(R8.java)",
- " <OR> at com.android.tools.r8.R8.foo(R8.java)",
+ " <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
" at com.android.tools.r8.R8.bar(R8.java)",
- " <OR> at com.android.tools.r8.R8.foo(R8.java)",
+ " <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
" at com.android.tools.r8.R8.main(Unknown Source)",
"Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
" at com.android.tools.r8.R8.bar(R8.java)",
- " <OR> at com.android.tools.r8.R8.foo(R8.java)",
+ " <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
" ... 42 more");
}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java
new file mode 100644
index 0000000..54ef0bf
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java
@@ -0,0 +1,42 @@
+// Copyright (c) 2021, 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.retrace.stacktraces;
+
+import com.android.tools.r8.utils.StringUtils;
+import java.util.Arrays;
+import java.util.List;
+
+public class MultipleLinesNoLineNumberStackTrace implements StackTraceForTest {
+
+ @Override
+ public List<String> obfuscatedStackTrace() {
+ return Arrays.asList(
+ "Exception in thread \"main\" java.lang.NullPointerException",
+ "\tat foo.a.a(Unknown Source)");
+ }
+
+ @Override
+ public String mapping() {
+ return StringUtils.lines(
+ "com.android.tools.r8.naming.retrace.Main -> foo.a:",
+ " 0:0:void method1(java.lang.String):42:42 -> a",
+ " 0:0:void main(java.lang.String[]):28 -> a",
+ " 1:1:void main(java.lang.String[]):153 -> a");
+ }
+
+ @Override
+ public List<String> retracedStackTrace() {
+ return Arrays.asList(
+ "Exception in thread \"main\" java.lang.NullPointerException",
+ "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java)",
+ "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.method1(Main.java)",
+ "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.main(Main.java)");
+ }
+
+ @Override
+ public int expectedWarnings() {
+ return 0;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscatedLineNumberWithOverrideTest.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscatedLineNumberWithOverrideTest.java
index 3f11112..23c5652 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscatedLineNumberWithOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscatedLineNumberWithOverrideTest.java
@@ -36,11 +36,11 @@
public List<String> retracedStackTrace() {
return Arrays.asList(
"Exception in thread \"main\" java.lang.NullPointerException",
- // TODO(b/191513686): Could be retrace to ...Main.main(Main.java:3)
- "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java)",
- "\tat com.android.tools.r8.naming.retrace.Main.overload1(Main.java)",
- "\t<OR> at com.android.tools.r8.naming.retrace.Main.overload2(Main.java)",
- "\tat com.android.tools.r8.naming.retrace.Main.definedOverload(Main.java)",
+ "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java:3)",
+ "\tat com.android.tools.r8.naming.retrace.Main.overload1(Main.java:7)",
+ "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.overload2(Main.java:11)",
+ "\tat com.android.tools.r8.naming.retrace.Main.definedOverload(Main.java:7)",
+ "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.definedOverload(Main.java:11)",
"\tat com.android.tools.r8.naming.retrace.Main.mainPC(Main.java:42)");
}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/OverloadSameLineTest.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/OverloadSameLineTest.java
index d1659cd..f1fbedb 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/OverloadSameLineTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/OverloadSameLineTest.java
@@ -32,8 +32,8 @@
"Exception in thread \"main\" java.lang.NullPointerException",
// TODO(b/199058242): Should be ambiguous and not inline frames
"\tat com.android.tools.r8.naming.retrace.Main.overload(Main.java:7)",
- "\t<OR> at com.android.tools.r8.naming.retrace.Main.overload(Main.java:15)",
- "\t<OR> at com.android.tools.r8.naming.retrace.Main.overload(Main.java:13)");
+ "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.overload(Main.java:15)",
+ "\t<OR #2> at com.android.tools.r8.naming.retrace.Main.overload(Main.java:13)");
}
@Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/SingleLineNoLineNumberStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/SingleLineNoLineNumberStackTrace.java
index 4f6ceb8..0b0c7ef 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/SingleLineNoLineNumberStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/SingleLineNoLineNumberStackTrace.java
@@ -16,7 +16,8 @@
"Exception in thread \"main\" java.lang.NullPointerException",
"\tat foo.a.a(Unknown Source)",
"\tat foo.a.b(Unknown Source)",
- "\tat foo.a.c(Unknown Source)");
+ "\tat foo.a.c(Unknown Source)",
+ "\tat foo.a.d(Unknown Source)");
}
@Override
@@ -26,20 +27,23 @@
" 0:0:void method1(java.lang.String):42:42 -> a",
" 0:0:void main(java.lang.String[]):28 -> a",
" 0:0:void method2(java.lang.String):42:48 -> b",
- " 0:0:void main2(java.lang.String[]):28 -> b",
- " void main3(java.lang.String[]):153 -> c");
+ " 0:0:void main2(java.lang.String[]):29 -> b",
+ " void method3(java.lang.String):72:72 -> c",
+ " void main3(java.lang.String[]):30 -> c",
+ " void main4(java.lang.String[]):153 -> d");
}
@Override
public List<String> retracedStackTrace() {
- // TODO(b/191513686): Should have line-numbers for main, method1, main2 and main3.
return Arrays.asList(
"Exception in thread \"main\" java.lang.NullPointerException",
- "\tat com.android.tools.r8.naming.retrace.Main.method1(Main.java)",
- "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java)",
- "\tat com.android.tools.r8.naming.retrace.Main.method2(Main.java)",
- "\tat com.android.tools.r8.naming.retrace.Main.main2(Main.java)",
- "\tat com.android.tools.r8.naming.retrace.Main.main3(Main.java)");
+ "\tat com.android.tools.r8.naming.retrace.Main.method1(Main.java:42)",
+ "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java:28)",
+ "\tat com.android.tools.r8.naming.retrace.Main.method2(Main.java:42)",
+ "\tat com.android.tools.r8.naming.retrace.Main.main2(Main.java:29)",
+ "\tat com.android.tools.r8.naming.retrace.Main.main3(Main.java:30)",
+ "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.method3(Main.java:72)",
+ "\tat com.android.tools.r8.naming.retrace.Main.main4(Main.java:153)");
}
@Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownSourceStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownSourceStackTrace.java
index 76b89e4..13b8bdd 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownSourceStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownSourceStackTrace.java
@@ -27,13 +27,13 @@
return Arrays.asList(
"com.android.tools.r8.CompilationException: foo[parens](Source:3)",
" at com.android.tools.r8.R8.bar(R8.java)",
- " <OR> at com.android.tools.r8.R8.foo(R8.java)",
+ " <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
" at com.android.tools.r8.R8.bar(R8.java)",
- " <OR> at com.android.tools.r8.R8.foo(R8.java)",
+ " <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
" at com.android.tools.r8.R8.main(Unknown Source)",
"Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
" at com.android.tools.r8.R8.bar(R8.java)",
- " <OR> at com.android.tools.r8.R8.foo(R8.java)",
+ " <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
" ... 42 more");
}