[Retrace] Modify StringRetrace to ease reading lines that can throw

Change-Id: I6a3c6227237945e321aa5b096769871a8feb44bc
diff --git a/src/main/java/com/android/tools/r8/retrace/ResultWithContext.java b/src/main/java/com/android/tools/r8/retrace/ResultWithContext.java
index 03988a9..4949aec 100644
--- a/src/main/java/com/android/tools/r8/retrace/ResultWithContext.java
+++ b/src/main/java/com/android/tools/r8/retrace/ResultWithContext.java
@@ -5,11 +5,17 @@
 package com.android.tools.r8.retrace;
 
 import com.android.tools.r8.Keep;
+import java.util.List;
+import java.util.function.Consumer;
 
 @Keep
 public interface ResultWithContext<T> {
 
   RetraceStackTraceContext getContext();
 
-  T getResult();
+  List<T> getLines();
+
+  void forEach(Consumer<T> consumer);
+
+  boolean isEmpty();
 }
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 8cc063e..29b68ab 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -181,7 +181,7 @@
    * @param context The context to retrace the stack trace in
    * @return list of potentially ambiguous stack traces.
    */
-  public ResultWithContext<List<List<List<T>>>> retraceStackTrace(
+  public ResultWithContext<List<List<T>>> retraceStackTrace(
       List<T> stackTrace, RetraceStackTraceContext context) {
     ListUtils.forEachWithIndex(
         stackTrace,
@@ -203,7 +203,7 @@
    * @param context The context to retrace the stack trace in
    * @return list of potentially ambiguous stack traces.
    */
-  public ResultWithContext<List<List<List<T>>>> retraceStackTraceParsed(
+  public ResultWithContext<List<List<T>>> retraceStackTraceParsed(
       List<ST> stackTrace, RetraceStackTraceContext context) {
     RetraceStackTraceElementProxyEquivalence<T, ST> equivalence =
         new RetraceStackTraceElementProxyEquivalence<>(isVerbose);
@@ -255,7 +255,7 @@
    * @param context The context to retrace the stack trace in
    * @return A collection of retraced frame where each entry in the outer list is ambiguous
    */
-  public ResultWithContext<List<List<T>>> retraceFrame(
+  public ResultWithContext<List<T>> retraceFrame(
       T stackTraceFrame, RetraceStackTraceContext context) {
     Map<RetraceStackTraceElementProxy<T, ST>, List<T>> ambiguousBlocks = new HashMap<>();
     List<RetraceStackTraceElementProxy<T, ST>> ambiguousKeys = new ArrayList<>();
@@ -287,8 +287,7 @@
    * @param context The context to retrace the stack trace in
    * @return the retraced stack trace line
    */
-  public ResultWithContext<List<T>> retraceLine(
-      T stackTraceLine, RetraceStackTraceContext context) {
+  public ResultWithContext<T> retraceLine(T stackTraceLine, RetraceStackTraceContext context) {
     ST parsedLine = stackTraceLineParser.parse(stackTraceLine);
     Box<RetraceStackTraceContext> contextBox = new Box<>(context);
     List<T> result =
@@ -376,14 +375,12 @@
               }
             });
         timing.begin("Retracing");
-        ResultWithContext<List<String>> listResultWithContext =
-            stringRetracer.retraceParsed(parsedStackTrace, context);
+        ResultWithContext<String> result = stringRetracer.retraceParsed(parsedStackTrace, context);
         timing.end();
         timing.begin("Report result");
-        context = listResultWithContext.getContext();
-        List<String> result = listResultWithContext.getResult();
+        context = result.getContext();
         if (!result.isEmpty() || currentStackTrace.isEmpty()) {
-          command.getRetracedStackTraceConsumer().accept(result);
+          command.getRetracedStackTraceConsumer().accept(result.getLines());
         }
         timing.end();
       }
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceOptions.java b/src/main/java/com/android/tools/r8/retrace/RetraceOptions.java
index 7c00ed2..513b39f 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceOptions.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceOptions.java
@@ -20,12 +20,12 @@
   private final boolean verifyMappingFileHash;
   private final String regularExpression;
   private final DiagnosticsHandler diagnosticsHandler;
-  private final MappingSupplier mappingSupplier;
+  private final MappingSupplier<?> mappingSupplier;
 
   private RetraceOptions(
       String regularExpression,
       DiagnosticsHandler diagnosticsHandler,
-      MappingSupplier mappingSupplier,
+      MappingSupplier<?> mappingSupplier,
       boolean isVerbose,
       boolean verifyMappingFileHash) {
     this.regularExpression = regularExpression;
@@ -54,7 +54,7 @@
     return diagnosticsHandler;
   }
 
-  public MappingSupplier getMappingSupplier() {
+  public MappingSupplier<?> getMappingSupplier() {
     return mappingSupplier;
   }
 
@@ -78,7 +78,7 @@
     private boolean isVerbose;
     private boolean verifyMappingFileHash;
     private final DiagnosticsHandler diagnosticsHandler;
-    private MappingSupplier mappingSupplier;
+    private MappingSupplier<?> mappingSupplier;
     private String regularExpression = defaultRegularExpression();
 
     Builder(DiagnosticsHandler diagnosticsHandler) {
@@ -98,11 +98,17 @@
     }
 
     /** Set a mapping supplier for providing mapping contents. */
-    public Builder setMappingSupplier(MappingSupplier producer) {
-      this.mappingSupplier = producer;
+    public Builder setMappingSupplier(MappingSupplier<?> supplier) {
+      this.mappingSupplier = supplier;
       return this;
     }
 
+    /** Helper method to set a ProguardMapSupplier from a ProguardMapProducer */
+    public Builder setProguardMapProducer(ProguardMapProducer producer) {
+      return setMappingSupplier(
+          ProguardMappingSupplier.builder().setProguardMapProducer(producer).build());
+    }
+
     /**
      * Set a regular expression for parsing the incoming text. The Regular expression must not use
      * naming groups and has special wild cards according to proguard retrace. Note, this will
diff --git a/src/main/java/com/android/tools/r8/retrace/StreamSupplier.java b/src/main/java/com/android/tools/r8/retrace/StreamSupplier.java
new file mode 100644
index 0000000..4a51497
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/StreamSupplier.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2022, 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;
+
+import com.android.tools.r8.Keep;
+
+/**
+ * Supplier of input lines to be retraced.
+ *
+ * @param <E> the type of the {@link Throwable}
+ */
+@FunctionalInterface
+@Keep
+public interface StreamSupplier<E extends Throwable> {
+
+  String getNext() throws E;
+}
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 09f30ca..164a208 100644
--- a/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
@@ -18,7 +18,6 @@
 import java.util.List;
 import java.util.Set;
 import java.util.function.Consumer;
-import java.util.function.Supplier;
 
 /**
  * Specialized Retrace class for retracing string retraces, with special handling for appending
@@ -82,12 +81,12 @@
    * @param context The context to retrace the stack trace in
    * @return the retraced stack trace
    */
-  public ResultWithContext<List<String>> retrace(
+  public ResultWithContext<String> retrace(
       List<String> stackTrace, RetraceStackTraceContext context) {
-    ResultWithContext<List<List<List<String>>>> listResultWithContext =
+    ResultWithContext<List<List<String>>> listResultWithContext =
         retraceStackTrace(stackTrace, context);
     List<String> retracedStrings = new ArrayList<>();
-    for (List<List<String>> newLines : listResultWithContext.getResult()) {
+    for (List<List<String>> newLines : listResultWithContext.getLines()) {
       ListUtils.forEachWithIndex(
           newLines,
           (inlineFrames, ambiguousIndex) -> {
@@ -122,12 +121,12 @@
    * @param context The context to retrace the stack trace in
    * @return the retraced stack trace
    */
-  public ResultWithContext<List<String>> retraceParsed(
+  public ResultWithContext<String> retraceParsed(
       List<StackTraceElementStringProxy> stackTrace, RetraceStackTraceContext context) {
-    ResultWithContext<List<List<List<String>>>> listResultWithContext =
+    ResultWithContext<List<List<String>>> listResultWithContext =
         retraceStackTraceParsed(stackTrace, context);
     List<String> retracedStrings = new ArrayList<>();
-    for (List<List<String>> newLines : listResultWithContext.getResult()) {
+    for (List<List<String>> newLines : listResultWithContext.getLines()) {
       ListUtils.forEachWithIndex(
           newLines,
           (inlineFrames, ambiguousIndex) -> {
@@ -161,12 +160,11 @@
    * @param context The context to retrace the stack trace in
    * @return the retraced frames
    */
-  public ResultWithContext<List<String>> retrace(
+  public ResultWithContext<String> retrace(
       String stackTraceLine, RetraceStackTraceContext context) {
-    ResultWithContext<List<List<String>>> listResultWithContext =
-        retraceFrame(stackTraceLine, context);
+    ResultWithContext<List<String>> listResultWithContext = retraceFrame(stackTraceLine, context);
     List<String> result = new ArrayList<>();
-    joinAmbiguousLines(listResultWithContext.getResult(), result::add);
+    joinAmbiguousLines(listResultWithContext.getLines(), result::add);
     return ResultWithContextImpl.create(result, listResultWithContext.getContext());
   }
 
@@ -176,13 +174,14 @@
    * @param lineSupplier the supplier of strings with returning null as terminator
    * @param lineConsumer the consumer of retraced strings
    */
-  public void retrace(Supplier<String> lineSupplier, Consumer<String> lineConsumer) {
+  public <E extends Throwable> void retraceSupplier(
+      StreamSupplier<E> lineSupplier, Consumer<String> lineConsumer) throws E {
     RetraceStackTraceContext context = RetraceStackTraceContext.empty();
     String retraceLine;
-    while ((retraceLine = lineSupplier.get()) != null) {
-      ResultWithContext<List<String>> result = retrace(retraceLine, context);
+    while ((retraceLine = lineSupplier.getNext()) != null) {
+      ResultWithContext<String> result = retrace(retraceLine, context);
       context = result.getContext();
-      result.getResult().forEach(lineConsumer);
+      result.forEach(lineConsumer);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/ResultWithContextImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/ResultWithContextImpl.java
index ab92a65..e65ecd5 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/ResultWithContextImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/ResultWithContextImpl.java
@@ -6,18 +6,20 @@
 
 import com.android.tools.r8.retrace.ResultWithContext;
 import com.android.tools.r8.retrace.RetraceStackTraceContext;
+import java.util.List;
+import java.util.function.Consumer;
 
 public class ResultWithContextImpl<T> implements ResultWithContext<T> {
 
-  private final T result;
+  private final List<T> result;
   private final RetraceStackTraceContext context;
 
-  private ResultWithContextImpl(T result, RetraceStackTraceContext context) {
+  private ResultWithContextImpl(List<T> result, RetraceStackTraceContext context) {
     this.result = result;
     this.context = context;
   }
 
-  public static <T> ResultWithContext<T> create(T result, RetraceStackTraceContext context) {
+  public static <T> ResultWithContext<T> create(List<T> result, RetraceStackTraceContext context) {
     return new ResultWithContextImpl<>(result, context);
   }
 
@@ -27,7 +29,17 @@
   }
 
   @Override
-  public T getResult() {
+  public List<T> getLines() {
     return result;
   }
+
+  @Override
+  public void forEach(Consumer<T> consumer) {
+    result.forEach(consumer);
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return result.isEmpty();
+  }
 }