[Retrace] Separate regular expression retracer to new setup
Bug: 169346455
Change-Id: Ice4a7a49461abbc1553863245e9483b142f74134
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 d9dd386..bd537a6 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -20,6 +20,7 @@
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.retrace.internal.StackTraceVisitor;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.OptionsParsing;
@@ -173,62 +174,53 @@
timing.end();
RetraceCommandLineResult result;
timing.begin("Parse and Retrace");
- if (command.regularExpression != null) {
- result =
- new RetraceRegularExpression(
- retracer,
- command.stackTrace,
- command.diagnosticsHandler,
- command.regularExpression,
- command.isVerbose)
- .retrace();
- } else {
- PlainStackTraceVisitor plainStackTraceVisitor =
- new PlainStackTraceVisitor(command.stackTrace, command.diagnosticsHandler);
+ StackTraceVisitor<StackTraceElementStringProxy> stackTraceVisitor =
+ command.regularExpression != null
+ ? new RetraceRegularExpression(
+ retracer, command.stackTrace, command.regularExpression)
+ : new PlainStackTraceVisitor(command.stackTrace, command.diagnosticsHandler);
StackTraceElementProxyRetracer<StackTraceElementStringProxy> proxyRetracer =
new StackTraceElementProxyRetracerImpl<>(retracer);
List<String> retracedStrings = new ArrayList<>();
- plainStackTraceVisitor.forEach(
- stackTraceElement -> {
- Box<List<RetraceStackTraceProxyImpl<StackTraceElementStringProxy>>> currentList =
- new Box<>();
- Map<
- RetraceStackTraceProxyImpl<StackTraceElementStringProxy>,
- List<RetraceStackTraceProxyImpl<StackTraceElementStringProxy>>>
- ambiguousBlocks = new HashMap<>();
- proxyRetracer
- .retrace(stackTraceElement)
- .forEach(
- retracedElement -> {
- if (retracedElement.isTopFrame() || !retracedElement.hasRetracedClass()) {
- List<RetraceStackTraceProxyImpl<StackTraceElementStringProxy>> block =
- new ArrayList<>();
- ambiguousBlocks.put(retracedElement, block);
- currentList.set(block);
- }
- currentList.get().add(retracedElement);
- });
- 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);
- });
- });
- });
+ stackTraceVisitor.forEach(
+ stackTraceElement -> {
+ Box<List<RetraceStackTraceProxyImpl<StackTraceElementStringProxy>>> currentList =
+ new Box<>();
+ Map<
+ RetraceStackTraceProxyImpl<StackTraceElementStringProxy>,
+ List<RetraceStackTraceProxyImpl<StackTraceElementStringProxy>>>
+ ambiguousBlocks = new HashMap<>();
+ proxyRetracer
+ .retrace(stackTraceElement)
+ .forEach(
+ retracedElement -> {
+ if (retracedElement.isTopFrame() || !retracedElement.hasRetracedClass()) {
+ List<RetraceStackTraceProxyImpl<StackTraceElementStringProxy>> block =
+ new ArrayList<>();
+ ambiguousBlocks.put(retracedElement, block);
+ currentList.set(block);
+ }
+ currentList.get().add(retracedElement);
+ });
+ 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);
- }
timing.end();
timing.begin("Report result");
command.retracedStackTraceConsumer.accept(result.getNodes());
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceFieldResult.java b/src/main/java/com/android/tools/r8/retrace/RetraceFieldResult.java
index f141080..d3b6014 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceFieldResult.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceFieldResult.java
@@ -27,5 +27,7 @@
RetraceFieldResult getRetraceFieldResult();
RetraceClassResult.Element getClassElement();
+
+ RetraceSourceFileResult retraceSourceFile(String sourceFile);
}
}
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 ebae15c..d9d1375 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceProxy.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceProxy.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.retrace;
import com.android.tools.r8.Keep;
+import java.util.List;
@Keep
public interface RetraceStackTraceProxy<T extends StackTraceElementProxy<?>>
@@ -18,16 +19,28 @@
boolean hasRetracedMethod();
+ boolean hasRetracedField();
+
boolean hasSourceFile();
boolean hasLineNumber();
+ boolean hasFieldOrReturnType();
+
+ boolean hasMethodArguments();
+
T getOriginalItem();
RetracedClass getRetracedClass();
RetracedMethod getRetracedMethod();
+ RetracedField getRetracedField();
+
+ RetracedType getRetracedFieldOrReturnType();
+
+ List<RetracedType> getMethodArguments();
+
String getSourceFile();
int getLineNumber();
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceTypeResult.java b/src/main/java/com/android/tools/r8/retrace/RetraceTypeResult.java
index b9fa2d3..2c0c1fa 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceTypeResult.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceTypeResult.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.retrace;
import com.android.tools.r8.Keep;
-import com.android.tools.r8.retrace.internal.RetracedTypeImpl;
import java.util.function.Consumer;
import java.util.stream.Stream;
@@ -21,6 +20,6 @@
@Keep
interface Element {
- RetracedTypeImpl getType();
+ RetracedType getType();
}
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetracedClassMember.java b/src/main/java/com/android/tools/r8/retrace/RetracedClassMember.java
index 10aa77c..f28b87e 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetracedClassMember.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetracedClassMember.java
@@ -5,10 +5,9 @@
package com.android.tools.r8.retrace;
import com.android.tools.r8.Keep;
-import com.android.tools.r8.retrace.internal.RetracedClassImpl;
@Keep
public interface RetracedClassMember {
- RetracedClassImpl getHolderClass();
+ RetracedClass getHolderClass();
}
diff --git a/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxy.java b/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxy.java
index efaab05..09c1a8f 100644
--- a/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxy.java
+++ b/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxy.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.retrace;
import com.android.tools.r8.Keep;
+import com.android.tools.r8.references.ClassReference;
@Keep
public abstract class StackTraceElementProxy<T> {
@@ -17,11 +18,23 @@
public abstract boolean hasLineNumber();
- public abstract String className();
+ public abstract boolean hasFieldName();
- public abstract String methodName();
+ public abstract boolean hasFieldOrReturnType();
- public abstract String fileName();
+ public abstract boolean hasMethodArguments();
- public abstract int lineNumber();
+ public abstract ClassReference getClassReference();
+
+ public abstract String getMethodName();
+
+ public abstract String getFileName();
+
+ public abstract int getLineNumber();
+
+ public abstract String getFieldName();
+
+ public abstract String getFieldOrReturnType();
+
+ public abstract String getMethodArguments();
}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/FieldDefinition.java b/src/main/java/com/android/tools/r8/retrace/internal/FieldDefinition.java
index 4a3b93c..27d9a54 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/FieldDefinition.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/FieldDefinition.java
@@ -43,7 +43,7 @@
@Override
FieldDefinition substituteHolder(ClassReference newHolder) {
- return FieldDefinition.create(classReference, name);
+ return FieldDefinition.create(newHolder, name);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/PlainStackTraceVisitor.java b/src/main/java/com/android/tools/r8/retrace/internal/PlainStackTraceVisitor.java
index 0aac05f..7f7d7fc 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/PlainStackTraceVisitor.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/PlainStackTraceVisitor.java
@@ -7,6 +7,7 @@
import static com.google.common.base.Predicates.not;
import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.retrace.internal.StackTraceElementStringProxy.ClassNameType;
import com.android.tools.r8.retrace.internal.StackTraceElementStringProxy.StackTraceElementStringProxyBuilder;
import com.android.tools.r8.utils.DescriptorUtils;
import java.util.List;
@@ -92,7 +93,7 @@
return null;
}
return StackTraceElementStringProxy.builder(line)
- .registerClassName(exceptionStartIndex, messageStartIndex)
+ .registerClassName(exceptionStartIndex, messageStartIndex, ClassNameType.TYPENAME)
.build();
}
}
@@ -161,7 +162,7 @@
}
StackTraceElementStringProxyBuilder builder =
StackTraceElementStringProxy.builder(line)
- .registerClassName(classStartIndex, methodSeparator)
+ .registerClassName(classStartIndex, methodSeparator, ClassNameType.TYPENAME)
.registerMethodName(methodSeparator + 1, parensStart);
// Check if we have a filename and position.
int separatorIndex = firstCharFromIndex(line, parensStart, ':');
@@ -201,7 +202,7 @@
return null;
}
return StackTraceElementStringProxy.builder(line)
- .registerClassName(exceptionStartIndex, lastBracketPosition)
+ .registerClassName(exceptionStartIndex, lastBracketPosition, ClassNameType.TYPENAME)
.build();
}
}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
index 066b979..3a65b0a 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.retrace.RetraceFieldResult;
-import com.android.tools.r8.retrace.Retracer;
+import com.android.tools.r8.retrace.RetraceSourceFileResult;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Pair;
import java.util.List;
@@ -22,13 +22,13 @@
private final RetraceClassResultImpl classResult;
private final List<Pair<RetraceClassResultImpl.ElementImpl, List<MemberNaming>>> memberNamings;
private final FieldDefinition fieldDefinition;
- private final Retracer retracer;
+ private final RetracerImpl retracer;
RetraceFieldResultImpl(
RetraceClassResultImpl classResult,
List<Pair<RetraceClassResultImpl.ElementImpl, List<MemberNaming>>> memberNamings,
FieldDefinition fieldDefinition,
- Retracer retracer) {
+ RetracerImpl retracer) {
this.classResult = classResult;
this.memberNamings = memberNamings;
this.fieldDefinition = fieldDefinition;
@@ -131,5 +131,11 @@
public RetraceClassResultImpl.ElementImpl getClassElement() {
return classElement;
}
+
+ @Override
+ public RetraceSourceFileResult retraceSourceFile(String sourceFile) {
+ return RetraceUtils.getSourceFile(
+ classElement, fieldReference.getHolderClass(), sourceFile, retraceFieldResult.retracer);
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceRegularExpression.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceRegularExpression.java
index 6ba4d1a..ca9a2f8 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceRegularExpression.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceRegularExpression.java
@@ -4,42 +4,19 @@
package com.android.tools.r8.retrace.internal;
-import static com.android.tools.r8.retrace.internal.RetraceUtils.methodDescriptionFromRetraceMethod;
-
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.references.ClassReference;
-import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.references.TypeReference;
-import com.android.tools.r8.retrace.RetraceClassResult;
-import com.android.tools.r8.retrace.RetraceFieldResult;
-import com.android.tools.r8.retrace.RetraceFrameResult;
-import com.android.tools.r8.retrace.RetraceFrameResult.Element;
-import com.android.tools.r8.retrace.RetraceSourceFileResult;
-import com.android.tools.r8.retrace.RetracedClass;
-import com.android.tools.r8.retrace.RetracedField;
-import com.android.tools.r8.retrace.RetracedField.KnownRetracedField;
-import com.android.tools.r8.retrace.RetracedMethod;
-import com.android.tools.r8.retrace.internal.RetraceRegularExpression.ClassNameGroup.ClassNameGroupHandler;
-import com.android.tools.r8.utils.Box;
-import com.android.tools.r8.utils.DescriptorUtils;
-import com.android.tools.r8.utils.StringUtils;
-import com.google.common.collect.Lists;
+import com.android.tools.r8.retrace.internal.StackTraceElementStringProxy.ClassNameType;
+import com.android.tools.r8.retrace.internal.StackTraceElementStringProxy.StackTraceElementStringProxyBuilder;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
-import java.util.Objects;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-public class RetraceRegularExpression {
+public class RetraceRegularExpression implements StackTraceVisitor<StackTraceElementStringProxy> {
private final RetracerImpl retracer;
private final List<String> stackTrace;
- private final DiagnosticsHandler diagnosticsHandler;
private final String regularExpression;
private static final int NO_MATCH = -1;
@@ -52,28 +29,21 @@
private final LineNumberGroup lineNumberGroup = new LineNumberGroup();
private final FieldOrReturnTypeGroup fieldOrReturnTypeGroup = new FieldOrReturnTypeGroup();
private final MethodArgumentsGroup methodArgumentsGroup = new MethodArgumentsGroup();
-
- private final MethodNameGroup methodNameGroup;
- private final FieldNameGroup fieldNameGroup;
+ private final MethodNameGroup methodNameGroup = new MethodNameGroup();
+ private final FieldNameGroup fieldNameGroup = new FieldNameGroup();
private static final String CAPTURE_GROUP_PREFIX = "captureGroup";
private static final int FIRST_CAPTURE_GROUP_INDEX = 0;
public RetraceRegularExpression(
- RetracerImpl retracer,
- List<String> stackTrace,
- DiagnosticsHandler diagnosticsHandler,
- String regularExpression,
- boolean isVerbose) {
+ RetracerImpl retracer, List<String> stackTrace, String regularExpression) {
this.retracer = retracer;
this.stackTrace = stackTrace;
- this.diagnosticsHandler = diagnosticsHandler;
this.regularExpression = regularExpression;
- methodNameGroup = new MethodNameGroup(isVerbose);
- fieldNameGroup = new FieldNameGroup(isVerbose);
}
- public RetraceCommandLineResult retrace() {
+ @Override
+ public void forEach(Consumer<StackTraceElementStringProxy> consumer) {
List<RegularExpressionGroupHandler> handlers = new ArrayList<>();
StringBuilder refinedRegularExpressionBuilder = new StringBuilder();
registerGroups(
@@ -83,74 +53,22 @@
FIRST_CAPTURE_GROUP_INDEX);
String refinedRegularExpression = refinedRegularExpressionBuilder.toString();
Pattern compiledPattern = Pattern.compile(refinedRegularExpression);
- List<String> result = new ArrayList<>();
for (String string : stackTrace) {
+ StackTraceElementStringProxyBuilder proxyBuilder =
+ StackTraceElementStringProxy.builder(string);
Matcher matcher = compiledPattern.matcher(string);
- if (!matcher.matches()) {
- result.add(string);
- continue;
- }
- // Iterate through handlers to set contexts. That will allow us to process all handlers from
- // left to right.
- RetraceStringContext initialContext = RetraceStringContext.empty();
- for (RegularExpressionGroupHandler handler : handlers) {
- initialContext = handler.buildInitial(initialContext, matcher, retracer);
- }
- final RetraceString initialRetraceString = RetraceString.start(initialContext);
- List<RetraceString> retracedStrings = Lists.newArrayList(initialRetraceString);
- for (RegularExpressionGroupHandler handler : handlers) {
- retracedStrings = handler.handleMatch(string, retracedStrings, matcher, retracer);
- }
- if (retracedStrings.isEmpty()) {
- // We could not find a match. Output the identity.
- result.add(string);
- }
- boolean isAmbiguous = retracedStrings.size() > 1 && retracedStrings.get(0).isAmbiguous();
- if (isAmbiguous) {
- retracedStrings.sort(new RetraceLineComparator());
- }
- RetracedClass previousContext = null;
- for (RetraceString retracedString : retracedStrings) {
- String finalString = retracedString.builder.build(string);
- if (!isAmbiguous) {
- result.add(finalString);
- continue;
+ if (matcher.matches()) {
+ boolean seenMatchedClassHandler = false;
+ for (RegularExpressionGroupHandler handler : handlers) {
+ if (seenMatchedClassHandler && handler.isClassHandler()) {
+ continue;
+ }
+ if (handler.matchHandler(proxyBuilder, matcher)) {
+ seenMatchedClassHandler |= handler.isClassHandler();
+ }
}
- assert retracedString.getClassContext() != null;
- RetracedClass currentContext = retracedString.getClassContext().getRetracedClass();
- if (currentContext.equals(previousContext)) {
- int firstNonWhitespaceCharacter = StringUtils.firstNonWhitespaceCharacter(finalString);
- finalString =
- finalString.substring(0, firstNonWhitespaceCharacter)
- + "<OR> "
- + finalString.substring(firstNonWhitespaceCharacter);
- }
- previousContext = currentContext;
- result.add(finalString);
}
- }
- return new RetraceCommandLineResult(result);
- }
-
- static class RetraceLineComparator extends AmbiguousComparator<RetraceString> {
-
- RetraceLineComparator() {
- super(
- (line, t) -> {
- switch (t) {
- case CLASS:
- return line.getClassContext().getRetracedClass().getTypeName();
- case METHOD:
- return line.getMethodContext().getTopFrame().getMethodName();
- case SOURCE:
- return line.getSource();
- case LINE:
- return line.getLineNumber() + "";
- default:
- assert false;
- }
- throw new RuntimeException("Comparator key is unknown");
- });
+ consumer.accept(proxyBuilder.build());
}
}
@@ -160,7 +78,6 @@
List<RegularExpressionGroupHandler> handlers,
int captureGroupIndex) {
int lastCommittedIndex = 0;
- RegularExpressionGroupHandler lastHandler = null;
boolean seenPercentage = false;
boolean escaped = false;
for (int i = 0; i < regularExpression.length(); i++) {
@@ -180,23 +97,7 @@
.append(">")
.append(group.subExpression())
.append(")");
- final RegularExpressionGroupHandler handler = group.createHandler(captureGroupName);
- // If we see a pattern as %c.%m or %C/%m, then register the groups to allow delaying
- // writing of the class string until we have the fully qualified member.
- if (lastHandler != null
- && handler.isQualifiedHandler()
- && lastHandler.isClassNameGroupHandler()
- && lastCommittedIndex == i - 3
- && isTypeOrBinarySeparator(regularExpression, lastCommittedIndex, i - 2)) {
- final ClassNameGroupHandler classNameGroupHandler =
- lastHandler.asClassNameGroupHandler();
- final QualifiedRegularExpressionGroupHandler qualifiedHandler =
- handler.asQualifiedHandler();
- classNameGroupHandler.setQualifiedHandler(qualifiedHandler);
- qualifiedHandler.setClassNameGroupHandler(classNameGroupHandler);
- }
- lastHandler = handler;
- handlers.add(handler);
+ handlers.add(group.createHandler(captureGroupName));
}
lastCommittedIndex = i + 1;
seenPercentage = false;
@@ -247,250 +148,13 @@
}
}
- static class RetraceStringContext {
- private final RetraceClassResult.Element classContext;
- private final RetraceFrameResult.Element methodContext;
- private final RetracedClass qualifiedClassContext;
- private final RetracedMethod qualifiedMethodContext;
- private final String methodName;
- private final int minifiedLineNumber;
- private final int originalLineNumber;
- private final String source;
- private final boolean isAmbiguous;
-
- private RetraceStringContext(
- RetraceClassResult.Element classContext,
- RetraceFrameResult.Element methodContext,
- RetracedClass qualifiedClassContext,
- RetracedMethod qualifiedMethodContext,
- String methodName,
- int minifiedLineNumber,
- int originalLineNumber,
- String source,
- boolean isAmbiguous) {
- this.classContext = classContext;
- this.methodContext = methodContext;
- this.qualifiedClassContext = qualifiedClassContext;
- this.qualifiedMethodContext = qualifiedMethodContext;
- this.methodName = methodName;
- this.minifiedLineNumber = minifiedLineNumber;
- this.originalLineNumber = originalLineNumber;
- this.source = source;
- this.isAmbiguous = isAmbiguous;
- }
-
- private static RetraceStringContext empty() {
- return new RetraceStringContext(
- null, null, null, null, null, NO_MATCH, NO_MATCH, null, false);
- }
-
- private RetraceStringContext withClassContext(
- RetraceClassResult.Element classContext, RetracedClass qualifiedContext) {
- return new RetraceStringContext(
- classContext,
- methodContext,
- qualifiedContext,
- qualifiedMethodContext,
- methodName,
- minifiedLineNumber,
- originalLineNumber,
- source,
- isAmbiguous);
- }
-
- private RetraceStringContext withMethodName(String methodName) {
- return new RetraceStringContext(
- classContext,
- methodContext,
- qualifiedClassContext,
- qualifiedMethodContext,
- methodName,
- minifiedLineNumber,
- originalLineNumber,
- source,
- isAmbiguous);
- }
-
- private RetraceStringContext withMethodContext(Element methodContext, boolean isAmbiguous) {
- return new RetraceStringContext(
- classContext,
- methodContext,
- qualifiedClassContext,
- qualifiedMethodContext,
- methodName,
- minifiedLineNumber,
- originalLineNumber,
- source,
- isAmbiguous);
- }
-
- private RetraceStringContext withQualifiedClassContext(RetracedClass qualifiedContext) {
- return new RetraceStringContext(
- classContext,
- methodContext,
- qualifiedContext,
- qualifiedMethodContext,
- methodName,
- minifiedLineNumber,
- originalLineNumber,
- source,
- isAmbiguous);
- }
-
- private RetraceStringContext withQualifiedMethodContext(RetracedMethod qualifiedContext) {
- return new RetraceStringContext(
- classContext,
- methodContext,
- qualifiedContext.getHolderClass(),
- qualifiedContext,
- methodName,
- minifiedLineNumber,
- originalLineNumber,
- source,
- isAmbiguous);
- }
-
- public RetraceStringContext withSource(String source) {
- return new RetraceStringContext(
- classContext,
- methodContext,
- qualifiedClassContext,
- qualifiedMethodContext,
- methodName,
- minifiedLineNumber,
- originalLineNumber,
- source,
- isAmbiguous);
- }
-
- public RetraceStringContext withLineNumbers(int minifiedLineNumber, int originalLineNumber) {
- return new RetraceStringContext(
- classContext,
- methodContext,
- qualifiedClassContext,
- qualifiedMethodContext,
- methodName,
- minifiedLineNumber,
- originalLineNumber,
- source,
- isAmbiguous);
- }
- }
-
- static class RetraceStringBuilder {
-
- private final StringBuilder retracedString;
- private int lastCommittedIndex;
-
- private RetraceStringBuilder(String retracedString, int lastCommittedIndex) {
- this.retracedString = new StringBuilder(retracedString);
- this.lastCommittedIndex = lastCommittedIndex;
- }
-
- private void appendRetracedString(
- String source, String stringToAppend, int originalFromIndex, int originalToIndex) {
- retracedString.append(source, lastCommittedIndex, originalFromIndex);
- retracedString.append(stringToAppend);
- lastCommittedIndex = originalToIndex;
- }
-
- private String build(String source) {
- return retracedString.append(source, lastCommittedIndex, source.length()).toString();
- }
- }
-
- private static class RetraceString {
-
- private final RetraceStringBuilder builder;
- private final RetraceStringContext context;
-
- private RetraceString(RetraceStringBuilder builder, RetraceStringContext context) {
- this.builder = builder;
- this.context = context;
- }
-
- private RetraceClassResult.Element getClassContext() {
- return context.classContext;
- }
-
- private RetraceFrameResult.Element getMethodContext() {
- return context.methodContext;
- }
-
- private String getSource() {
- return context.source;
- }
-
- private int getLineNumber() {
- return context.originalLineNumber;
- }
-
- private boolean isAmbiguous() {
- return context.isAmbiguous;
- }
-
- private static RetraceString start(RetraceStringContext initialContext) {
- return new RetraceString(new RetraceStringBuilder("", 0), initialContext);
- }
-
- private RetraceString updateContext(
- Function<RetraceStringContext, RetraceStringContext> update) {
- return new RetraceString(builder, update.apply(context));
- }
-
- private RetraceString duplicate(RetraceStringContext newContext) {
- return new RetraceString(
- new RetraceStringBuilder(builder.retracedString.toString(), builder.lastCommittedIndex),
- newContext);
- }
-
- private RetraceString appendRetracedString(
- String source, String stringToAppend, int originalFromIndex, int originalToIndex) {
- builder.appendRetracedString(source, stringToAppend, originalFromIndex, originalToIndex);
- return this;
- }
- }
-
private interface RegularExpressionGroupHandler {
- List<RetraceString> handleMatch(
- String original, List<RetraceString> strings, Matcher matcher, RetracerImpl retracer);
+ boolean matchHandler(StackTraceElementStringProxyBuilder builder, Matcher matcher);
- default RetraceStringContext buildInitial(
- RetraceStringContext context, Matcher matcher, RetracerImpl retracer) {
- return context;
- }
-
- default boolean isClassNameGroupHandler() {
+ default boolean isClassHandler() {
return false;
}
-
- default ClassNameGroupHandler asClassNameGroupHandler() {
- return null;
- }
-
- default boolean isQualifiedHandler() {
- return false;
- }
-
- default QualifiedRegularExpressionGroupHandler asQualifiedHandler() {
- return null;
- }
- }
-
- private interface QualifiedRegularExpressionGroupHandler extends RegularExpressionGroupHandler {
-
- @Override
- default boolean isQualifiedHandler() {
- return true;
- }
-
- @Override
- default QualifiedRegularExpressionGroupHandler asQualifiedHandler() {
- return this;
- }
-
- void setClassNameGroupHandler(ClassNameGroupHandler handler);
}
private abstract static class RegularExpressionGroup {
@@ -513,107 +177,31 @@
abstract static class ClassNameGroup extends RegularExpressionGroup {
- abstract String getClassName(RetracedClass classReference);
-
- abstract ClassReference classFromMatch(String match);
+ abstract ClassNameType getClassNameType();
@Override
RegularExpressionGroupHandler createHandler(String captureGroup) {
- return new ClassNameGroupHandler(this, captureGroup);
- }
-
- static class ClassNameGroupHandler implements RegularExpressionGroupHandler {
-
- private RetraceClassResultImpl retraceClassResult = null;
- private final ClassNameGroup classNameGroup;
- private final String captureGroup;
- private RegularExpressionGroupHandler qualifiedHandler;
-
- public ClassNameGroupHandler(ClassNameGroup classNameGroup, String captureGroup) {
- this.classNameGroup = classNameGroup;
- this.captureGroup = captureGroup;
- }
-
- @Override
- public List<RetraceString> handleMatch(
- String original, List<RetraceString> strings, Matcher matcher, RetracerImpl retracer) {
- final int startOfGroup = matcher.start(captureGroup);
- if (startOfGroup == NO_MATCH) {
- return strings;
+ return new RegularExpressionGroupHandler() {
+ @Override
+ public boolean matchHandler(StackTraceElementStringProxyBuilder builder, Matcher matcher) {
+ int startOfGroup = matcher.start(captureGroup);
+ if (startOfGroup == NO_MATCH) {
+ return false;
+ }
+ String typeName = matcher.group(captureGroup);
+ if (typeName.equals("Suppressed")) {
+ // Ensure we do not map supressed.
+ return false;
+ }
+ builder.registerClassName(startOfGroup, matcher.end(captureGroup), getClassNameType());
+ return true;
}
- String typeName = matcher.group(captureGroup);
- RetraceClassResultImpl retraceResult =
- retraceClassResult == null
- ? retracer.retraceClass(classNameGroup.classFromMatch(typeName))
- : retraceClassResult;
- assert !retraceResult.isAmbiguous();
- List<RetraceString> retraceStrings = new ArrayList<>(strings.size());
- for (RetraceString retraceString : strings) {
- retraceResult.forEach(
- element -> {
- RetraceString newRetraceString =
- retraceString.updateContext(
- context -> context.withClassContext(element, element.getRetracedClass()));
- retraceStrings.add(newRetraceString);
- if (qualifiedHandler == null) {
- // If there is no qualified handler, commit right away.
- newRetraceString.builder.appendRetracedString(
- original,
- classNameGroup.getClassName(element.getRetracedClass()),
- startOfGroup,
- matcher.end(captureGroup));
- }
- });
+
+ @Override
+ public boolean isClassHandler() {
+ return true;
}
- return retraceStrings;
- }
-
- void commitClassName(
- String original,
- RetraceString retraceString,
- RetracedClass qualifiedContext,
- Matcher matcher) {
- if (matcher.start(captureGroup) == NO_MATCH) {
- return;
- }
- retraceString.builder.appendRetracedString(
- original,
- classNameGroup.getClassName(qualifiedContext),
- matcher.start(captureGroup),
- matcher.end(captureGroup));
- }
-
- @Override
- public RetraceStringContext buildInitial(
- RetraceStringContext context, Matcher matcher, RetracerImpl retracer) {
- // Reset the local class context since this the same handler is used for multiple lines.
- retraceClassResult = null;
- if (matcher.start(captureGroup) == NO_MATCH || context.classContext != null) {
- return context;
- }
- String typeName = matcher.group(captureGroup);
- retraceClassResult = retracer.retraceClass(classNameGroup.classFromMatch(typeName));
- assert !retraceClassResult.isAmbiguous();
- Box<RetraceStringContext> box = new Box<>();
- retraceClassResult.forEach(
- element -> box.set(context.withClassContext(element, element.getRetracedClass())));
- return box.get();
- }
-
- public void setQualifiedHandler(RegularExpressionGroupHandler handler) {
- assert handler.isQualifiedHandler();
- this.qualifiedHandler = handler;
- }
-
- @Override
- public boolean isClassNameGroupHandler() {
- return true;
- }
-
- @Override
- public ClassNameGroupHandler asClassNameGroupHandler() {
- return this;
- }
+ };
}
}
@@ -625,13 +213,8 @@
}
@Override
- String getClassName(RetracedClass classReference) {
- return classReference.getTypeName();
- }
-
- @Override
- ClassReference classFromMatch(String match) {
- return Reference.classFromTypeName(match);
+ ClassNameType getClassNameType() {
+ return ClassNameType.TYPENAME;
}
}
@@ -643,24 +226,13 @@
}
@Override
- String getClassName(RetracedClass classReference) {
- return classReference.getBinaryName();
- }
-
- @Override
- ClassReference classFromMatch(String match) {
- return Reference.classFromBinaryName(match);
+ ClassNameType getClassNameType() {
+ return ClassNameType.BINARY;
}
}
private static class MethodNameGroup extends RegularExpressionGroup {
- private final boolean printVerbose;
-
- public MethodNameGroup(boolean printVerbose) {
- this.printVerbose = printVerbose;
- }
-
@Override
String subExpression() {
return METHOD_NAME_REGULAR_EXPRESSION;
@@ -668,98 +240,19 @@
@Override
RegularExpressionGroupHandler createHandler(String captureGroup) {
- return new QualifiedRegularExpressionGroupHandler() {
-
- private ClassNameGroupHandler classNameGroupHandler;
-
- @Override
- public void setClassNameGroupHandler(ClassNameGroupHandler handler) {
- classNameGroupHandler = handler;
+ return (builder, matcher) -> {
+ int startOfGroup = matcher.start(captureGroup);
+ if (startOfGroup == NO_MATCH) {
+ return false;
}
-
- @Override
- public List<RetraceString> handleMatch(
- String original, List<RetraceString> strings, Matcher matcher, RetracerImpl retracer) {
- final int startOfGroup = matcher.start(captureGroup);
- if (startOfGroup == NO_MATCH) {
- if (classNameGroupHandler != null) {
- for (RetraceString string : strings) {
- classNameGroupHandler.commitClassName(
- original, string, string.context.qualifiedClassContext, matcher);
- }
- }
- return strings;
- }
- String methodName = matcher.group(captureGroup);
- List<RetraceString> retracedStrings = new ArrayList<>();
- for (RetraceString retraceString : strings) {
- retraceMethodForString(
- retraceString,
- methodName,
- (element, newContext) -> {
- element.visitFrames(
- (method, ignoredPosition) -> {
- RetraceString newRetraceString =
- retraceString.duplicate(newContext.withQualifiedMethodContext(method));
- if (classNameGroupHandler != null) {
- classNameGroupHandler.commitClassName(
- original, newRetraceString, method.getHolderClass(), matcher);
- }
- retracedStrings.add(
- newRetraceString.appendRetracedString(
- original,
- printVerbose
- ? methodDescriptionFromRetraceMethod(method, false, true)
- : method.getMethodName(),
- startOfGroup,
- matcher.end(captureGroup)));
- });
- });
- }
- return retracedStrings;
- }
-
- @Override
- public RetraceStringContext buildInitial(
- RetraceStringContext context, Matcher matcher, RetracerImpl retracer) {
- final int startOfGroup = matcher.start(captureGroup);
- if (startOfGroup == NO_MATCH || context.methodName != null) {
- return context;
- }
- return context.withMethodName(matcher.group(captureGroup));
- }
+ builder.registerMethodName(startOfGroup, matcher.end(captureGroup));
+ return true;
};
}
-
- private static void retraceMethodForString(
- RetraceString retraceString,
- String methodName,
- BiConsumer<Element, RetraceStringContext> process) {
- if (retraceString.context.classContext == null) {
- return;
- }
- RetraceClassResult.Element classContext = retraceString.getClassContext();
- RetraceFrameResult retraceFrameResult =
- retraceString.context.minifiedLineNumber > NO_MATCH
- ? classContext.lookupFrame(methodName, retraceString.context.minifiedLineNumber)
- : classContext.lookupFrame(methodName);
- retraceFrameResult.forEach(
- element -> {
- process.accept(
- element,
- retraceString.context.withMethodContext(element, retraceFrameResult.isAmbiguous()));
- });
- }
}
private static class FieldNameGroup extends RegularExpressionGroup {
- private final boolean printVerbose;
-
- public FieldNameGroup(boolean printVerbose) {
- this.printVerbose = printVerbose;
- }
-
@Override
String subExpression() {
return javaIdentifierSegment;
@@ -767,70 +260,15 @@
@Override
RegularExpressionGroupHandler createHandler(String captureGroup) {
- return new QualifiedRegularExpressionGroupHandler() {
-
- private ClassNameGroupHandler classNameGroupHandler;
-
- @Override
- public void setClassNameGroupHandler(ClassNameGroupHandler handler) {
- classNameGroupHandler = handler;
+ return (builder, matcher) -> {
+ int startOfGroup = matcher.start(captureGroup);
+ if (startOfGroup == NO_MATCH) {
+ return false;
}
-
- @Override
- public List<RetraceString> handleMatch(
- String original, List<RetraceString> strings, Matcher matcher, RetracerImpl retracer) {
- final int startOfGroup = matcher.start(captureGroup);
- if (startOfGroup == NO_MATCH) {
- if (classNameGroupHandler != null) {
- for (RetraceString string : strings) {
- classNameGroupHandler.commitClassName(
- original, string, string.context.qualifiedClassContext, matcher);
- }
- }
- return strings;
- }
- String fieldName = matcher.group(captureGroup);
- List<RetraceString> retracedStrings = new ArrayList<>();
- for (RetraceString retraceString : strings) {
- if (retraceString.getClassContext() == null) {
- assert classNameGroupHandler == null;
- return strings;
- }
- final RetraceFieldResult retraceFieldResult =
- retraceString.getClassContext().lookupField(fieldName);
- assert !retraceFieldResult.isAmbiguous();
- retraceFieldResult.forEach(
- element -> {
- if (classNameGroupHandler != null) {
- classNameGroupHandler.commitClassName(
- original, retraceString, element.getField().getHolderClass(), matcher);
- }
- retracedStrings.add(
- retraceString
- .updateContext(
- context ->
- context.withQualifiedClassContext(
- element.getField().getHolderClass()))
- .appendRetracedString(
- original,
- getFieldString(element.getField()),
- startOfGroup,
- matcher.end(captureGroup)));
- });
- }
- return retracedStrings;
- }
+ builder.registerFieldName(startOfGroup, matcher.end(captureGroup));
+ return true;
};
}
-
- private String getFieldString(RetracedField fieldReference) {
- if (!printVerbose || fieldReference.isUnknown()) {
- return fieldReference.getFieldName();
- }
- assert fieldReference.isKnown();
- KnownRetracedField knownRef = fieldReference.asKnown();
- return knownRef.getFieldType().getTypeName() + " " + fieldReference.getFieldName();
- }
}
private static class SourceFileGroup extends RegularExpressionGroup {
@@ -842,40 +280,13 @@
@Override
RegularExpressionGroupHandler createHandler(String captureGroup) {
- return (original, strings, matcher, retracer) -> {
- final int startOfGroup = matcher.start(captureGroup);
+ return (builder, matcher) -> {
+ int startOfGroup = matcher.start(captureGroup);
if (startOfGroup == NO_MATCH) {
- return strings;
+ return false;
}
- String fileName = matcher.group(captureGroup);
- List<RetraceString> retracedStrings = null;
- for (RetraceString retraceString : strings) {
- if (retraceString.context.classContext == null) {
- return strings;
- }
- if (retracedStrings == null) {
- retracedStrings = new ArrayList<>();
- }
- RetraceSourceFileResult sourceFileResult =
- retraceString.getMethodContext() != null
- ? retraceString
- .getMethodContext()
- .retraceSourceFile(retraceString.context.qualifiedMethodContext, fileName)
- : RetraceUtils.getSourceFile(
- retraceString.getClassContext(),
- retraceString.context.qualifiedClassContext,
- fileName,
- retracer);
- retracedStrings.add(
- retraceString
- .updateContext(context -> context.withSource(sourceFileResult.getFilename()))
- .appendRetracedString(
- original,
- sourceFileResult.getFilename(),
- startOfGroup,
- matcher.end(captureGroup)));
- }
- return retracedStrings;
+ builder.registerSourceFile(startOfGroup, matcher.end(captureGroup));
+ return true;
};
}
}
@@ -889,88 +300,13 @@
@Override
RegularExpressionGroupHandler createHandler(String captureGroup) {
- return new RegularExpressionGroupHandler() {
- @Override
- public List<RetraceString> handleMatch(
- String original, List<RetraceString> strings, Matcher matcher, RetracerImpl retracer) {
- final int startOfGroup = matcher.start(captureGroup);
- if (startOfGroup == NO_MATCH) {
- return strings;
- }
- String lineNumberAsString = matcher.group(captureGroup);
- if (lineNumberAsString.isEmpty()) {
- return strings;
- }
- int lineNumber = Integer.parseInt(lineNumberAsString);
- List<RetraceString> retracedStrings = new ArrayList<>();
- for (RetraceString retraceString : strings) {
- Element methodContext = retraceString.context.methodContext;
- if (methodContext == null) {
- if (retraceString.context.classContext == null
- || retraceString.context.methodName == null) {
- // We have no way of retracing the line number.
- retracedStrings.add(retraceString);
- continue;
- }
- // This situation arises when we have a matched pattern as %l..%c.%m where the
- // line number handler is defined before the methodname handler.
- MethodNameGroup.retraceMethodForString(
- retraceString,
- retraceString.context.methodName,
- (element, newContext) -> {
- // The same method can be represented multiple times if it has multiple
- // mappings.
- element.visitFrames(
- (method, ignoredPosition) -> {
- int originalPosition = method.getOriginalPositionOrDefault(lineNumber);
- retracedStrings.add(
- retraceString
- .duplicate(
- retraceString
- .context
- .withQualifiedMethodContext(method)
- .withLineNumbers(lineNumber, originalPosition))
- .appendRetracedString(
- original,
- originalPosition + "",
- startOfGroup,
- matcher.end(captureGroup)));
- });
- });
- continue;
- }
- // If the method context is unknown, do nothing.
- if (methodContext.isUnknown()) {
- retracedStrings.add(retraceString);
- continue;
- }
- int originalLineNumber =
- retraceString.context.qualifiedMethodContext.getOriginalPositionOrDefault(
- lineNumber);
- retracedStrings.add(
- retraceString
- .updateContext(
- context -> context.withLineNumbers(lineNumber, originalLineNumber))
- .appendRetracedString(
- original,
- originalLineNumber + "",
- startOfGroup,
- matcher.end(captureGroup)));
- }
- return retracedStrings;
+ return (builder, matcher) -> {
+ int startOfGroup = matcher.start(captureGroup);
+ if (startOfGroup == NO_MATCH) {
+ return false;
}
-
- @Override
- public RetraceStringContext buildInitial(
- RetraceStringContext context, Matcher matcher, RetracerImpl retracer) {
- if (matcher.start(captureGroup) == NO_MATCH || context.minifiedLineNumber > NO_MATCH) {
- return context;
- }
- String lineNumberAsString = matcher.group(captureGroup);
- return context.withLineNumbers(
- lineNumberAsString.isEmpty() ? NO_MATCH : Integer.parseInt(lineNumberAsString),
- NO_MATCH);
- }
+ builder.registerLineNumber(startOfGroup, matcher.end(captureGroup));
+ return true;
};
}
}
@@ -1005,31 +341,13 @@
@Override
RegularExpressionGroupHandler createHandler(String captureGroup) {
- return (original, strings, matcher, retracer) -> {
- final int startOfGroup = matcher.start(captureGroup);
+ return (builder, matcher) -> {
+ int startOfGroup = matcher.start(captureGroup);
if (startOfGroup == NO_MATCH) {
- return strings;
+ return false;
}
- String typeName = matcher.group(captureGroup);
- String descriptor = DescriptorUtils.javaTypeToDescriptor(typeName);
- if (!DescriptorUtils.isDescriptor(descriptor) && !"V".equals(descriptor)) {
- return strings;
- }
- TypeReference typeReference = Reference.returnTypeFromDescriptor(descriptor);
- RetraceTypeResultImpl retracedType = retracer.retraceType(typeReference);
- assert !retracedType.isAmbiguous();
- for (RetraceString retraceString : strings) {
- retracedType.forEach(
- element -> {
- RetracedTypeImpl retracedReference = element.getType();
- retraceString.appendRetracedString(
- original,
- retracedReference.isVoid() ? "void" : retracedReference.getTypeName(),
- startOfGroup,
- matcher.end(captureGroup));
- });
- }
- return strings;
+ builder.registerFieldOrReturnType(startOfGroup, matcher.end(captureGroup));
+ return true;
};
}
}
@@ -1043,37 +361,15 @@
@Override
RegularExpressionGroupHandler createHandler(String captureGroup) {
- return (original, strings, matcher, retracer) -> {
- final int startOfGroup = matcher.start(captureGroup);
+ return (builder, matcher) -> {
+ int startOfGroup = matcher.start(captureGroup);
if (startOfGroup == NO_MATCH) {
- return strings;
+ return false;
}
- final String formals =
- Arrays.stream(matcher.group(captureGroup).split(","))
- .map(
- typeName -> {
- typeName = typeName.trim();
- if (typeName.isEmpty()) {
- return null;
- }
- String descriptor = DescriptorUtils.javaTypeToDescriptor(typeName);
- if (!DescriptorUtils.isDescriptor(descriptor) && !"V".equals(descriptor)) {
- return typeName;
- }
- final RetraceTypeResultImpl retraceResult =
- retracer.retraceType(Reference.returnTypeFromDescriptor(descriptor));
- assert !retraceResult.isAmbiguous();
- final Box<RetracedTypeImpl> elementBox = new Box<>();
- retraceResult.forEach(element -> elementBox.set(element.getType()));
- return elementBox.get().getTypeName();
- })
- .filter(Objects::nonNull)
- .collect(Collectors.joining(","));
- for (RetraceString string : strings) {
- string.appendRetracedString(original, formals, startOfGroup, matcher.end(captureGroup));
- }
- return strings;
+ builder.registerMethodArguments(startOfGroup, matcher.end(captureGroup));
+ return true;
};
}
}
}
+
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetracedTypeImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetracedTypeImpl.java
index 8162e05..d467cc1 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetracedTypeImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetracedTypeImpl.java
@@ -23,6 +23,10 @@
return new RetracedTypeImpl(typeReference);
}
+ static RetracedType createVoid() {
+ return new RetracedTypeImpl(null);
+ }
+
@Override
public boolean isVoid() {
return typeReference == null;
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 458978d..a949fc1 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
@@ -5,13 +5,23 @@
package com.android.tools.r8.retrace.internal;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.references.TypeReference;
+import com.android.tools.r8.retrace.RetraceClassResult;
+import com.android.tools.r8.retrace.RetraceFieldResult;
import com.android.tools.r8.retrace.RetraceStackTraceProxy;
import com.android.tools.r8.retrace.RetracedClass;
+import com.android.tools.r8.retrace.RetracedField;
import com.android.tools.r8.retrace.RetracedMethod;
+import com.android.tools.r8.retrace.RetracedType;
import com.android.tools.r8.retrace.StackTraceElementProxy;
import com.android.tools.r8.retrace.StackTraceElementProxyRetracer;
+import com.android.tools.r8.utils.Box;
+import com.android.tools.r8.utils.ListUtils;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StackTraceElementProxyRetracerImpl<T extends StackTraceElementProxy<?>>
@@ -28,49 +38,188 @@
if (!element.hasClassName()) {
return Stream.of(RetraceStackTraceProxyImpl.builder(element).build());
}
- RetraceClassResultImpl classResult =
- retracer.retraceClass(Reference.classFromTypeName(element.className()));
- List<RetraceStackTraceProxyImpl<T>> retracedProxies = new ArrayList<>();
- if (!element.hasMethodName()) {
- classResult.forEach(
- classElement -> {
- RetraceStackTraceProxyImpl.Builder<T> proxy =
- RetraceStackTraceProxyImpl.builder(element)
- .setRetracedClassElement(classElement.getRetracedClass())
- .setAmbiguous(classResult.isAmbiguous())
- .setTopFrame(true);
- if (element.hasFileName()) {
- proxy.setSourceFile(classElement.retraceSourceFile(element.fileName()).getFilename());
- }
- retracedProxies.add(proxy.build());
- });
+ RetraceClassResultImpl classResult = retracer.retraceClass(element.getClassReference());
+ if (element.hasMethodName()) {
+ return retraceMethod(element, classResult);
+ } else if (element.hasFieldName()) {
+ return retraceField(element, classResult);
} else {
- RetraceFrameResultImpl frameResult =
- element.hasLineNumber()
- ? classResult.lookupFrame(element.methodName(), element.lineNumber())
- : classResult.lookupFrame(element.methodName());
- frameResult.forEach(
- frameElement -> {
- frameElement.visitFrames(
- (frame, index) -> {
- RetraceStackTraceProxyImpl.Builder<T> proxy =
- RetraceStackTraceProxyImpl.builder(element)
- .setRetracedClassElement(frame.getHolderClass())
- .setRetracedMethodElement(frame)
- .setAmbiguous(frameResult.isAmbiguous() && index == 0)
- .setTopFrame(index == 0);
- if (element.hasLineNumber()) {
- proxy.setLineNumber(frame.getOriginalPositionOrDefault(element.lineNumber()));
- }
- if (element.hasFileName()) {
- proxy.setSourceFile(
- frameElement.retraceSourceFile(frame, element.fileName()).getFilename());
- }
- retracedProxies.add(proxy.build());
- });
- });
+ return retraceClassOrType(element, classResult);
}
- return retracedProxies.stream();
+ }
+
+ private Stream<RetraceStackTraceProxyImpl<T>> retraceClassOrType(
+ T element, RetraceClassResult classResult) {
+ return classResult.stream()
+ .flatMap(
+ classElement ->
+ retraceFieldOrReturnType(element)
+ .flatMap(
+ fieldOrReturnTypeConsumer ->
+ retracedMethodArguments(element)
+ .map(
+ argumentsConsumer -> {
+ RetraceStackTraceProxyImpl.Builder<T> proxy =
+ RetraceStackTraceProxyImpl.builder(element)
+ .setRetracedClass(classElement.getRetracedClass())
+ .setAmbiguous(classResult.isAmbiguous())
+ .setTopFrame(true);
+ argumentsConsumer.accept(proxy);
+ fieldOrReturnTypeConsumer.accept(proxy);
+ if (element.hasFileName()) {
+ proxy.setSourceFile(
+ classElement
+ .retraceSourceFile(element.getFileName())
+ .getFilename());
+ }
+ return proxy.build();
+ })));
+ }
+
+ private Stream<RetraceStackTraceProxyImpl<T>> retraceMethod(
+ T element, RetraceClassResultImpl classResult) {
+ return retraceFieldOrReturnType(element)
+ .flatMap(
+ fieldOrReturnTypeConsumer ->
+ retracedMethodArguments(element)
+ .flatMap(
+ argumentsConsumer -> {
+ RetraceFrameResultImpl frameResult =
+ element.hasLineNumber()
+ ? classResult.lookupFrame(
+ element.getMethodName(), element.getLineNumber())
+ : classResult.lookupFrame(element.getMethodName());
+ return frameResult.stream()
+ .flatMap(
+ frameElement -> {
+ List<RetraceStackTraceProxyImpl<T>> retracedProxies =
+ new ArrayList<>();
+ frameElement.visitFrames(
+ (frame, index) -> {
+ RetraceStackTraceProxyImpl.Builder<T> proxy =
+ RetraceStackTraceProxyImpl.builder(element)
+ .setRetracedClass(frame.getHolderClass())
+ .setRetracedMethod(frame)
+ .setAmbiguous(
+ frameResult.isAmbiguous() && index == 0)
+ .setTopFrame(index == 0);
+ if (element.hasLineNumber()) {
+ proxy.setLineNumber(
+ frame.getOriginalPositionOrDefault(
+ element.getLineNumber()));
+ }
+ if (element.hasFileName()) {
+ proxy.setSourceFile(
+ frameElement
+ .retraceSourceFile(frame, element.getFileName())
+ .getFilename());
+ }
+ fieldOrReturnTypeConsumer.accept(proxy);
+ argumentsConsumer.accept(proxy);
+ retracedProxies.add(proxy.build());
+ });
+ return retracedProxies.stream();
+ });
+ }));
+ }
+
+ private Stream<RetraceStackTraceProxyImpl<T>> retraceField(
+ T element, RetraceClassResult classResult) {
+ return retraceFieldOrReturnType(element)
+ .flatMap(
+ fieldOrReturnTypeConsumer ->
+ retracedMethodArguments(element)
+ .flatMap(
+ argumentsConsumer -> {
+ RetraceFieldResult retraceFieldResult =
+ classResult.lookupField(element.getFieldName());
+ return retraceFieldResult.stream()
+ .map(
+ fieldElement -> {
+ RetraceStackTraceProxyImpl.Builder<T> proxy =
+ RetraceStackTraceProxyImpl.builder(element)
+ .setRetracedClass(
+ fieldElement.getField().getHolderClass())
+ .setRetracedField(fieldElement.getField())
+ .setAmbiguous(retraceFieldResult.isAmbiguous())
+ .setTopFrame(true);
+ if (element.hasFileName()) {
+ proxy.setSourceFile(
+ fieldElement
+ .retraceSourceFile(element.getFileName())
+ .getFilename());
+ }
+ fieldOrReturnTypeConsumer.accept(proxy);
+ argumentsConsumer.accept(proxy);
+ return proxy.build();
+ });
+ }));
+ }
+
+ private Stream<Consumer<RetraceStackTraceProxyImpl.Builder<T>>> retraceFieldOrReturnType(
+ T element) {
+ if (!element.hasFieldOrReturnType()) {
+ return Stream.of(noEffect -> {});
+ }
+ String elementOrReturnType = element.getFieldOrReturnType();
+ if (elementOrReturnType.equals("void")) {
+ return Stream.of(proxy -> proxy.setRetracedFieldOrReturnType(RetracedTypeImpl.createVoid()));
+ } else {
+ TypeReference typeReference = Reference.typeFromTypeName(elementOrReturnType);
+ RetraceTypeResultImpl retraceTypeResult = retracer.retraceType(typeReference);
+ return retraceTypeResult.stream()
+ .map(
+ type ->
+ (proxy -> {
+ proxy.setRetracedFieldOrReturnType(type.getType());
+ if (retraceTypeResult.isAmbiguous()) {
+ proxy.setAmbiguous(true);
+ }
+ }));
+ }
+ }
+
+ private Stream<Consumer<RetraceStackTraceProxyImpl.Builder<T>>> retracedMethodArguments(
+ T element) {
+ if (!element.hasMethodArguments()) {
+ return Stream.of(noEffect -> {});
+ }
+ List<RetraceTypeResultImpl> retracedResults =
+ Arrays.stream(element.getMethodArguments().split(","))
+ .map(typeName -> retracer.retraceType(Reference.typeFromTypeName(typeName)))
+ .collect(Collectors.toList());
+ List<List<RetracedType>> initial = new ArrayList<>();
+ initial.add(new ArrayList<>());
+ Box<Boolean> isAmbiguous = new Box<>(false);
+ List<List<RetracedType>> retracedArguments =
+ ListUtils.fold(
+ retracedResults,
+ initial,
+ (acc, retracedTypeResult) -> {
+ if (retracedTypeResult.isAmbiguous()) {
+ isAmbiguous.set(true);
+ }
+ List<List<RetracedType>> newResult = new ArrayList<>();
+ retracedTypeResult.forEach(
+ retracedElement -> {
+ acc.forEach(
+ oldResult -> {
+ List<RetracedType> newList = new ArrayList<>(oldResult);
+ newList.add(retracedElement.getType());
+ newResult.add(newList);
+ });
+ });
+ return newResult;
+ });
+ return retracedArguments.stream()
+ .map(
+ arguments ->
+ proxy -> {
+ proxy.setRetracedMethodArguments(arguments);
+ if (isAmbiguous.get()) {
+ proxy.setAmbiguous(true);
+ }
+ });
}
public static class RetraceStackTraceProxyImpl<T extends StackTraceElementProxy<?>>
@@ -79,6 +228,9 @@
private final T originalItem;
private final RetracedClass retracedClass;
private final RetracedMethod retracedMethod;
+ private final RetracedField retracedField;
+ private final RetracedType fieldOrReturnType;
+ private final List<RetracedType> methodArguments;
private final String sourceFile;
private final int lineNumber;
private final boolean isAmbiguous;
@@ -88,6 +240,9 @@
T originalItem,
RetracedClass retracedClass,
RetracedMethod retracedMethod,
+ RetracedField retracedField,
+ RetracedType fieldOrReturnType,
+ List<RetracedType> methodArguments,
String sourceFile,
int lineNumber,
boolean isAmbiguous,
@@ -96,6 +251,9 @@
this.originalItem = originalItem;
this.retracedClass = retracedClass;
this.retracedMethod = retracedMethod;
+ this.retracedField = retracedField;
+ this.fieldOrReturnType = fieldOrReturnType;
+ this.methodArguments = methodArguments;
this.sourceFile = sourceFile;
this.lineNumber = lineNumber;
this.isAmbiguous = isAmbiguous;
@@ -123,6 +281,11 @@
}
@Override
+ public boolean hasRetracedField() {
+ return retracedField != null;
+ }
+
+ @Override
public boolean hasSourceFile() {
return sourceFile != null;
}
@@ -133,6 +296,16 @@
}
@Override
+ public boolean hasFieldOrReturnType() {
+ return fieldOrReturnType != null;
+ }
+
+ @Override
+ public boolean hasMethodArguments() {
+ return methodArguments != null;
+ }
+
+ @Override
public T getOriginalItem() {
return originalItem;
}
@@ -148,6 +321,21 @@
}
@Override
+ public RetracedField getRetracedField() {
+ return retracedField;
+ }
+
+ @Override
+ public RetracedType getRetracedFieldOrReturnType() {
+ return fieldOrReturnType;
+ }
+
+ @Override
+ public List<RetracedType> getMethodArguments() {
+ return methodArguments;
+ }
+
+ @Override
public String getSourceFile() {
return sourceFile;
}
@@ -209,6 +397,9 @@
private final T originalElement;
private RetracedClass classContext;
private RetracedMethod methodContext;
+ private RetracedField retracedField;
+ private RetracedType fieldOrReturnType;
+ private List<RetracedType> methodArguments;
private String sourceFile;
private int lineNumber = -1;
private boolean isAmbiguous;
@@ -218,16 +409,31 @@
this.originalElement = originalElement;
}
- private Builder<T> setRetracedClassElement(RetracedClass retracedClass) {
+ private Builder<T> setRetracedClass(RetracedClass retracedClass) {
this.classContext = retracedClass;
return this;
}
- private Builder<T> setRetracedMethodElement(RetracedMethod methodElement) {
+ private Builder<T> setRetracedMethod(RetracedMethod methodElement) {
this.methodContext = methodElement;
return this;
}
+ private Builder<T> setRetracedField(RetracedField retracedField) {
+ this.retracedField = retracedField;
+ return this;
+ }
+
+ private Builder<T> setRetracedFieldOrReturnType(RetracedType retracedType) {
+ this.fieldOrReturnType = retracedType;
+ return this;
+ }
+
+ private Builder<T> setRetracedMethodArguments(List<RetracedType> arguments) {
+ this.methodArguments = arguments;
+ return this;
+ }
+
private Builder<T> setSourceFile(String sourceFile) {
this.sourceFile = sourceFile;
return this;
@@ -257,7 +463,10 @@
originalElement,
retracedClass,
methodContext,
- sourceFile != null ? sourceFile : null,
+ retracedField,
+ fieldOrReturnType,
+ methodArguments,
+ sourceFile,
lineNumber,
isAmbiguous,
isTopFrame);
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 15d62ad..f649598 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
@@ -8,8 +8,15 @@
import static com.android.tools.r8.retrace.internal.RetraceUtils.methodDescriptionFromRetraceMethod;
import static com.android.tools.r8.retrace.internal.StackTraceElementStringProxy.StringIndex.noIndex;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.RetracedClass;
+import com.android.tools.r8.retrace.RetracedField;
+import com.android.tools.r8.retrace.RetracedType;
import com.android.tools.r8.retrace.StackTraceElementProxy;
import com.android.tools.r8.retrace.internal.StackTraceElementProxyRetracerImpl.RetraceStackTraceProxyImpl;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.StringUtils.BraceType;
import com.android.tools.r8.utils.TriFunction;
import java.util.ArrayList;
import java.util.List;
@@ -18,24 +25,33 @@
private final String line;
private final List<StringIndex> orderedIndices;
- private final StringIndex className;
+ private final ClassStringIndex className;
private final StringIndex methodName;
private final StringIndex sourceFile;
private final StringIndex lineNumber;
+ private final StringIndex fieldName;
+ private final StringIndex fieldOrReturnType;
+ private final StringIndex methodArguments;
private StackTraceElementStringProxy(
String line,
List<StringIndex> orderedIndices,
- StringIndex className,
+ ClassStringIndex className,
StringIndex methodName,
StringIndex sourceFile,
- StringIndex lineNumber) {
+ StringIndex lineNumber,
+ StringIndex fieldName,
+ StringIndex fieldOrReturnType,
+ StringIndex methodArguments) {
this.line = line;
this.orderedIndices = orderedIndices;
this.className = className;
this.methodName = methodName;
this.sourceFile = sourceFile;
this.lineNumber = lineNumber;
+ this.fieldName = fieldName;
+ this.fieldOrReturnType = fieldOrReturnType;
+ this.methodArguments = methodArguments;
}
static StackTraceElementStringProxyBuilder builder(String line) {
@@ -63,22 +79,37 @@
}
@Override
- public String className() {
- return hasClassName() ? getEntryInLine(className) : null;
+ public boolean hasFieldName() {
+ return fieldName.hasIndex();
}
@Override
- public String methodName() {
+ public boolean hasFieldOrReturnType() {
+ return fieldOrReturnType.hasIndex();
+ }
+
+ @Override
+ public boolean hasMethodArguments() {
+ return methodArguments.hasIndex();
+ }
+
+ @Override
+ public ClassReference getClassReference() {
+ return hasClassName() ? className.getReference(line) : null;
+ }
+
+ @Override
+ public String getMethodName() {
return hasMethodName() ? getEntryInLine(methodName) : null;
}
@Override
- public String fileName() {
+ public String getFileName() {
return hasFileName() ? getEntryInLine(sourceFile) : null;
}
@Override
- public int lineNumber() {
+ public int getLineNumber() {
if (!hasLineNumber()) {
return -1;
}
@@ -89,6 +120,21 @@
}
}
+ @Override
+ public String getFieldName() {
+ return hasFieldName() ? getEntryInLine(fieldName) : null;
+ }
+
+ @Override
+ public String getFieldOrReturnType() {
+ return hasFieldOrReturnType() ? getEntryInLine(fieldOrReturnType) : null;
+ }
+
+ @Override
+ public String getMethodArguments() {
+ return hasMethodArguments() ? getEntryInLine(methodArguments) : null;
+ }
+
public String toRetracedItem(
RetraceStackTraceProxyImpl<StackTraceElementStringProxy> retracedProxy,
boolean printAmbiguous,
@@ -118,30 +164,43 @@
return line.substring(index.startIndex, index.endIndex);
}
+ public enum ClassNameType {
+ BINARY,
+ TYPENAME
+ }
+
public static class StackTraceElementStringProxyBuilder {
private final String line;
private final List<StringIndex> orderedIndices = new ArrayList<>();
- private StringIndex className = noIndex();
+ private ClassStringIndex className = noIndex();
private StringIndex methodName = noIndex();
private StringIndex sourceFile = noIndex();
private StringIndex lineNumber = noIndex();
+ private StringIndex fieldName = noIndex();
+ private StringIndex fieldOrReturnType = noIndex();
+ private StringIndex methodArguments = noIndex();
private int lastSeenStartIndex = -1;
private StackTraceElementStringProxyBuilder(String line) {
this.line = line;
}
- public StackTraceElementStringProxyBuilder registerClassName(int startIndex, int endIndex) {
+ public StackTraceElementStringProxyBuilder registerClassName(
+ int startIndex, int endIndex, ClassNameType classNameType) {
ensureLineIndexIncreases(startIndex);
className =
- new StringIndex(
+ new ClassStringIndex(
startIndex,
endIndex,
(retraced, original, verbose) -> {
assert retraced.hasRetracedClass();
- return retraced.getRetracedClass().getTypeName();
- });
+ RetracedClass retracedClass = retraced.getRetracedClass();
+ return classNameType == ClassNameType.BINARY
+ ? retracedClass.getBinaryName()
+ : retracedClass.getTypeName();
+ },
+ classNameType);
orderedIndices.add(className);
return this;
}
@@ -153,7 +212,7 @@
endIndex,
(retraced, original, verbose) -> {
if (!retraced.hasRetracedMethod()) {
- return original.methodName();
+ return original.getMethodName();
}
return methodDescriptionFromRetraceMethod(
retraced.getRetracedMethod(), false, verbose);
@@ -168,7 +227,7 @@
startIndex,
endIndex,
(retraced, original, verbose) ->
- retraced.hasSourceFile() ? retraced.getSourceFile() : original.fileName());
+ retraced.hasSourceFile() ? retraced.getSourceFile() : original.getFileName());
orderedIndices.add(sourceFile);
return this;
}
@@ -186,9 +245,73 @@
return this;
}
+ public StackTraceElementStringProxyBuilder registerFieldName(int startIndex, int endIndex) {
+ fieldName =
+ new StringIndex(
+ startIndex,
+ endIndex,
+ (retraced, original, verbose) -> {
+ if (!retraced.hasRetracedField()) {
+ return original.getFieldName();
+ }
+ RetracedField retracedField = retraced.getRetracedField();
+ if (!verbose || retracedField.isUnknown()) {
+ return retracedField.getFieldName();
+ }
+ return retracedField.asKnown().getFieldType().getTypeName()
+ + " "
+ + retracedField.getFieldName();
+ });
+ orderedIndices.add(fieldName);
+ return this;
+ }
+
+ public StackTraceElementStringProxyBuilder registerFieldOrReturnType(
+ int startIndex, int endIndex) {
+ fieldOrReturnType =
+ new StringIndex(
+ startIndex,
+ endIndex,
+ (retraced, original, verbose) -> {
+ if (!retraced.hasFieldOrReturnType()) {
+ return original.getFieldOrReturnType();
+ }
+ return retraced.getRetracedFieldOrReturnType().isVoid()
+ ? "void"
+ : retraced.getRetracedFieldOrReturnType().getTypeName();
+ });
+ orderedIndices.add(fieldOrReturnType);
+ return this;
+ }
+
+ public StackTraceElementStringProxyBuilder registerMethodArguments(
+ int startIndex, int endIndex) {
+ methodArguments =
+ new StringIndex(
+ startIndex,
+ endIndex,
+ (retraced, original, verbose) -> {
+ if (!retraced.hasMethodArguments()) {
+ return original.getMethodArguments();
+ }
+ return StringUtils.join(
+ retraced.getMethodArguments(), ",", BraceType.NONE, RetracedType::getTypeName);
+ });
+ orderedIndices.add(methodArguments);
+ return this;
+ }
+
public StackTraceElementStringProxy build() {
return new StackTraceElementStringProxy(
- line, orderedIndices, className, methodName, sourceFile, lineNumber);
+ line,
+ orderedIndices,
+ className,
+ methodName,
+ sourceFile,
+ lineNumber,
+ fieldName,
+ fieldOrReturnType,
+ methodArguments);
}
private void ensureLineIndexIncreases(int newStartIndex) {
@@ -199,16 +322,17 @@
}
}
- static final class StringIndex {
+ static class StringIndex {
- private static final StringIndex NO_INDEX = new StringIndex(-1, -1, null);
+ private static final ClassStringIndex NO_INDEX =
+ new ClassStringIndex(-1, -1, null, ClassNameType.TYPENAME);
- static StringIndex noIndex() {
+ static ClassStringIndex noIndex() {
return NO_INDEX;
}
- private final int startIndex;
- private final int endIndex;
+ protected final int startIndex;
+ protected final int endIndex;
private final TriFunction<
RetraceStackTraceProxyImpl<StackTraceElementStringProxy>,
StackTraceElementStringProxy,
@@ -234,4 +358,30 @@
return this != NO_INDEX;
}
}
+
+ static final class ClassStringIndex extends StringIndex {
+
+ private final ClassNameType classNameType;
+
+ private ClassStringIndex(
+ int startIndex,
+ int endIndex,
+ TriFunction<
+ RetraceStackTraceProxyImpl<StackTraceElementStringProxy>,
+ StackTraceElementStringProxy,
+ Boolean,
+ String>
+ retracedString,
+ ClassNameType classNameType) {
+ super(startIndex, endIndex, retracedString);
+ this.classNameType = classNameType;
+ }
+
+ ClassReference getReference(String line) {
+ String className = line.substring(startIndex, endIndex);
+ return classNameType == ClassNameType.BINARY
+ ? Reference.classFromBinaryName(className)
+ : Reference.classFromTypeName(className);
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/utils/ListUtils.java b/src/main/java/com/android/tools/r8/utils/ListUtils.java
index f941485..51821c0 100644
--- a/src/main/java/com/android/tools/r8/utils/ListUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ListUtils.java
@@ -7,6 +7,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -63,4 +64,12 @@
}
return true;
}
+
+ public static <T, R> R fold(Collection<T> items, R identity, BiFunction<R, T, R> acc) {
+ R result = identity;
+ for (T item : items) {
+ result = acc.apply(result, item);
+ }
+ return result;
+ }
}
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceRegularExpressionTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceRegularExpressionTests.java
index b8b1647..6c43c35 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceRegularExpressionTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceRegularExpressionTests.java
@@ -63,6 +63,7 @@
@Test
public void matchMultipleTypeNamesOnLine() {
+ // TODO(b/171691292): We are not supporting having multiple class matches for.
runRetraceTest(
"%c\\s%c\\s%c",
new StackTraceForTest() {
@@ -79,7 +80,7 @@
@Override
public List<String> retracedStackTrace() {
- return ImmutableList.of("AA.AA.AA BB.BB.BB CC.CC.CC");
+ return ImmutableList.of("AA.AA.AA b.b.b c.c.c");
}
@Override
@@ -91,6 +92,7 @@
@Test
public void matchMultipleSlashNamesOnLine() {
+ // TODO(b/171691292): We are not supporting having multiple class matches for.
runRetraceTest(
"%C\\s%C\\s%C",
new StackTraceForTest() {
@@ -106,7 +108,7 @@
@Override
public List<String> retracedStackTrace() {
- return ImmutableList.of("AA/AA BB/BB CC/CC");
+ return ImmutableList.of("AA/AA b/b/b c/c/c");
}
@Override