[Retrace] Use the same procedure for looking up frames

This CL removes the custom building of mapped frames such that
ClassResult.lookupFrame is equal to Retrace.retraceFrame.

Bug: 201397823
Change-Id: Ifb8184936873a84d9121e3fd9c5850baa8e3c1b5
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceMethodResult.java b/src/main/java/com/android/tools/r8/retrace/RetraceMethodResult.java
index 805443c..f06fad3 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceMethodResult.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceMethodResult.java
@@ -5,9 +5,10 @@
 package com.android.tools.r8.retrace;
 
 import com.android.tools.r8.Keep;
+import java.util.OptionalInt;
 
 @Keep
 public interface RetraceMethodResult extends RetraceResult<RetraceMethodElement> {
 
-  RetraceFrameResult narrowByPosition(RetraceStackTraceContext context, int position);
+  RetraceFrameResult narrowByPosition(RetraceStackTraceContext context, OptionalInt position);
 }
diff --git a/src/main/java/com/android/tools/r8/retrace/Retracer.java b/src/main/java/com/android/tools/r8/retrace/Retracer.java
index 34d413b..293ac8e 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retracer.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retracer.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.references.TypeReference;
 import com.android.tools.r8.retrace.internal.RetracerImpl;
+import java.util.OptionalInt;
 
 /** This is the main api interface for retrace. */
 @Keep
@@ -20,10 +21,10 @@
 
   RetraceMethodResult retraceMethod(MethodReference methodReference);
 
-  RetraceFrameResult retraceFrame(MethodReference methodReference, int position);
+  RetraceFrameResult retraceFrame(MethodReference methodReference, OptionalInt position);
 
   RetraceFrameResult retraceFrame(
-      MethodReference methodReference, int position, RetraceStackTraceContext context);
+      MethodReference methodReference, OptionalInt position, RetraceStackTraceContext context);
 
   RetraceFieldResult retraceField(FieldReference fieldReference);
 
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
index f94035b..f354bb3 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
@@ -6,7 +6,6 @@
 
 
 import com.android.tools.r8.naming.ClassNamingForNameMapper;
-import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
 import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRangesOfName;
 import com.android.tools.r8.naming.MemberNaming;
 import com.android.tools.r8.naming.mappinginformation.MappingInformation;
@@ -20,7 +19,6 @@
 import com.android.tools.r8.retrace.RetraceStackTraceContext;
 import com.android.tools.r8.retrace.RetraceUnknownJsonMappingInformationResult;
 import com.android.tools.r8.retrace.RetracedSourceFile;
-import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.Pair;
 import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
@@ -138,62 +136,17 @@
             Reference.method(obfuscatedReference, methodName, formalTypes, returnType)));
   }
 
+  private RetraceFrameResultImpl lookupFrame(
+      RetraceStackTraceContext context, OptionalInt position, MethodDefinition definition) {
+    return lookupMethod(definition).narrowByPosition(context, position);
+  }
+
   @Override
   public RetraceThrownExceptionResultImpl lookupThrownException(RetraceStackTraceContext context) {
     return new RetraceThrownExceptionResultImpl(
         (RetraceStackTraceContextImpl) context, obfuscatedReference, mapper);
   }
 
-  private RetraceFrameResultImpl lookupFrame(
-      RetraceStackTraceContext context, OptionalInt position, MethodDefinition definition) {
-    List<Pair<RetraceClassElementImpl, List<MappedRange>>> mappings = new ArrayList<>();
-    internalStream()
-        .forEach(
-            element -> {
-              getMappedRangesForFrame(element, definition, position)
-                  .forEach(
-                      mappedRanges -> {
-                        mappings.add(new Pair<>(element, mappedRanges));
-                      });
-            });
-    return new RetraceFrameResultImpl(
-        this, mappings, definition, position, retracer, (RetraceStackTraceContextImpl) context);
-  }
-
-  private List<List<MappedRange>> getMappedRangesForFrame(
-      RetraceClassElementImpl element, MethodDefinition definition, OptionalInt position) {
-    List<List<MappedRange>> overloadedRanges = new ArrayList<>();
-    if (mapper == null) {
-      overloadedRanges.add(null);
-      return overloadedRanges;
-    }
-    assert element.mapper != null;
-    MappedRangesOfName mappedRanges = mapper.mappedRangesByRenamedName.get(definition.getName());
-    if (mappedRanges == null || mappedRanges.getMappedRanges().isEmpty()) {
-      overloadedRanges.add(null);
-      return overloadedRanges;
-    }
-    List<MappedRange> mappedRangesForPosition = null;
-    if (position.isPresent() && position.getAsInt() >= 0) {
-      mappedRangesForPosition = mappedRanges.allRangesForLine(position.getAsInt(), false);
-    }
-    if (mappedRangesForPosition == null || mappedRangesForPosition.isEmpty()) {
-      mappedRangesForPosition = mappedRanges.getMappedRanges();
-    }
-    assert mappedRangesForPosition != null && !mappedRangesForPosition.isEmpty();
-    // Mapped ranges can have references to overloaded signatures. We distinguish those by looking
-    // at the cardinal mapping range.
-    for (MappedRange mappedRange : mappedRangesForPosition) {
-      if (overloadedRanges.isEmpty()
-          || mappedRange.originalRange == null
-          || !mappedRange.originalRange.isCardinal) {
-        overloadedRanges.add(new ArrayList<>());
-      }
-      ListUtils.last(overloadedRanges).add(mappedRange);
-    }
-    return overloadedRanges;
-  }
-
   @Override
   public boolean hasRetraceResult() {
     return mapper != null;
@@ -366,23 +319,7 @@
 
     private RetraceFrameResultImpl lookupFrame(
         RetraceStackTraceContext context, OptionalInt position, MethodDefinition definition) {
-      MethodDefinition methodDefinition =
-          MethodDefinition.create(classReference.getClassReference(), definition.getName());
-      ImmutableList.Builder<Pair<RetraceClassElementImpl, List<MappedRange>>> builder =
-          ImmutableList.builder();
-      classResult
-          .getMappedRangesForFrame(this, methodDefinition, position)
-          .forEach(
-              mappedRanges -> {
-                builder.add(new Pair<>(this, mappedRanges));
-              });
-      return new RetraceFrameResultImpl(
-          classResult,
-          builder.build(),
-          methodDefinition,
-          position,
-          classResult.retracer,
-          (RetraceStackTraceContextImpl) context);
+      return classResult.lookupFrame(context, position, definition);
     }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
index 978a933..178d359 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
@@ -14,8 +14,8 @@
 import com.android.tools.r8.retrace.RetracedMethodReference;
 import com.android.tools.r8.retrace.RetracedSourceFile;
 import com.android.tools.r8.retrace.internal.RetraceClassResultImpl.RetraceClassElementImpl;
+import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.Pair;
-import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.OptionalInt;
@@ -62,38 +62,40 @@
   }
 
   @Override
-  public RetraceFrameResultImpl narrowByPosition(RetraceStackTraceContext context, int position) {
+  public RetraceFrameResultImpl narrowByPosition(
+      RetraceStackTraceContext context, OptionalInt position) {
     List<Pair<RetraceClassElementImpl, List<MappedRange>>> narrowedRanges = new ArrayList<>();
-    List<Pair<RetraceClassElementImpl, List<MappedRange>>> noMappingRanges = new ArrayList<>();
     for (Pair<RetraceClassElementImpl, List<MappedRange>> mappedRange : mappedRanges) {
       if (mappedRange.getSecond() == null) {
-        noMappingRanges.add(new Pair<>(mappedRange.getFirst(), null));
+        narrowedRanges.add(new Pair<>(mappedRange.getFirst(), null));
         continue;
       }
-      List<MappedRange> ranges =
-          new MappedRangesOfName(mappedRange.getSecond()).allRangesForLine(position, false);
-      boolean hasAddedRanges = false;
-      if (!ranges.isEmpty()) {
-        narrowedRanges.add(new Pair<>(mappedRange.getFirst(), ranges));
-        hasAddedRanges = true;
-      } else {
-        narrowedRanges = new ArrayList<>();
-        for (MappedRange mapped : mappedRange.getSecond()) {
-          if (mapped.minifiedRange == null) {
-            narrowedRanges.add(new Pair<>(mappedRange.getFirst(), ImmutableList.of(mapped)));
-            hasAddedRanges = true;
-          }
-        }
+      MappedRangesOfName mappedRangesOfElement = new MappedRangesOfName(mappedRange.getSecond());
+      List<MappedRange> mappedRangesForPosition = null;
+      if (position.isPresent() && position.getAsInt() >= 0) {
+        mappedRangesForPosition =
+            mappedRangesOfElement.allRangesForLine(position.getAsInt(), false);
       }
-      if (!hasAddedRanges) {
-        narrowedRanges.add(new Pair<>(mappedRange.getFirst(), null));
+      if (mappedRangesForPosition == null || mappedRangesForPosition.isEmpty()) {
+        mappedRangesForPosition = mappedRangesOfElement.getMappedRanges();
+      }
+      assert mappedRangesForPosition != null && !mappedRangesForPosition.isEmpty();
+      // Mapped ranges can have references to overloaded signatures. We distinguish those by looking
+      // at the cardinal mapping range.
+      for (MappedRange mappedRangeForPosition : mappedRangesForPosition) {
+        if (narrowedRanges.isEmpty()
+            || mappedRangeForPosition.originalRange == null
+            || !mappedRangeForPosition.originalRange.isCardinal) {
+          narrowedRanges.add(new Pair<>(mappedRange.getFirst(), new ArrayList<>()));
+        }
+        ListUtils.last(narrowedRanges).getSecond().add(mappedRangeForPosition);
       }
     }
     return new RetraceFrameResultImpl(
         classResult,
-        narrowedRanges.isEmpty() ? noMappingRanges : narrowedRanges,
+        narrowedRanges,
         methodDefinition,
-        OptionalInt.of(position),
+        position,
         retracer,
         (RetraceStackTraceContextImpl) context);
   }
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
index 9aadbb3..563de26 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.retrace.RetraceStackTraceContext;
 import com.android.tools.r8.retrace.Retracer;
 import java.io.BufferedReader;
+import java.util.OptionalInt;
 
 /** A default implementation for the retrace api using the ClassNameMapper defined in R8. */
 public class RetracerImpl implements Retracer {
@@ -62,13 +63,13 @@
   }
 
   @Override
-  public RetraceFrameResult retraceFrame(MethodReference methodReference, int position) {
+  public RetraceFrameResult retraceFrame(MethodReference methodReference, OptionalInt position) {
     return retraceFrame(methodReference, position, RetraceStackTraceContext.empty());
   }
 
   @Override
   public RetraceFrameResult retraceFrame(
-      MethodReference methodReference, int position, RetraceStackTraceContext context) {
+      MethodReference methodReference, OptionalInt position, RetraceStackTraceContext context) {
     return retraceClass(methodReference.getHolderClass())
         .lookupMethod(methodReference.getMethodName())
         .narrowByPosition(context, position);
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiSingleFrameTest.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiSingleFrameTest.java
new file mode 100644
index 0000000..bec1a7f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiSingleFrameTest.java
@@ -0,0 +1,75 @@
+// 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.api;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.RetraceFrameElement;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
+import com.android.tools.r8.retrace.RetracedMethodReference;
+import com.android.tools.r8.retrace.Retracer;
+import java.util.List;
+import java.util.OptionalInt;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class RetraceApiSingleFrameTest extends RetraceApiTestBase {
+
+  public RetraceApiSingleFrameTest(TestParameters parameters) {
+    super(parameters);
+  }
+
+  @Override
+  protected Class<? extends RetraceApiBinaryTest> binaryTestClass() {
+    return ApiTest.class;
+  }
+
+  public static class ApiTest implements RetraceApiBinaryTest {
+
+    private final ClassReference originalClass = Reference.classFromTypeName("some.Class");
+    private final ClassReference renamedClass = Reference.classFromTypeName("a");
+
+    private final String mapping =
+        originalClass.getTypeName()
+            + " -> "
+            + renamedClass.getTypeName()
+            + ":\n"
+            + "  int strawberry(int):99:99 -> a\n";
+
+    @Test
+    public void testRetracingFrameEqualToNarrow() {
+      Retracer retracer =
+          Retracer.createDefault(
+              ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {});
+      checkResults(
+          retracer
+              .retraceFrame(
+                  Reference.methodFromDescriptor(renamedClass, "a", "()I"), OptionalInt.empty())
+              .stream()
+              .collect(Collectors.toList()));
+      checkResults(
+          retracer
+              .retraceClass(renamedClass)
+              .lookupFrame(RetraceStackTraceContext.empty(), OptionalInt.empty(), "a")
+              .stream()
+              .collect(Collectors.toList()));
+    }
+
+    private void checkResults(List<RetraceFrameElement> elements) {
+      assertEquals(1, elements.size());
+      RetracedMethodReference topFrame = elements.get(0).getTopFrame();
+      assertEquals("strawberry", topFrame.getMethodName());
+      assertEquals(99, topFrame.getOriginalPositionOrDefault(-1));
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
index 4e2b27d..cf9ce0a 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.retrace.RetraceMethodResult;
 import com.android.tools.r8.retrace.RetraceStackTraceContext;
 import com.android.tools.r8.retrace.Retracer;
+import java.util.OptionalInt;
 
 public interface InstructionSubject {
 
@@ -163,11 +164,13 @@
   }
 
   default RetraceFrameResult retraceLinePosition(Retracer retracer) {
-    return retrace(retracer).narrowByPosition(RetraceStackTraceContext.empty(), getLineNumber());
+    return retrace(retracer)
+        .narrowByPosition(RetraceStackTraceContext.empty(), OptionalInt.of(getLineNumber()));
   }
 
   default RetraceFrameResult retracePcPosition(Retracer retracer, MethodSubject methodSubject) {
     return retrace(retracer)
-        .narrowByPosition(RetraceStackTraceContext.empty(), getOffset(methodSubject).offset);
+        .narrowByPosition(
+            RetraceStackTraceContext.empty(), OptionalInt.of(getOffset(methodSubject).offset));
   }
 }
diff --git a/third_party/retrace/binary_compatibility.tar.gz.sha1 b/third_party/retrace/binary_compatibility.tar.gz.sha1
index 6b09100..1295509 100644
--- a/third_party/retrace/binary_compatibility.tar.gz.sha1
+++ b/third_party/retrace/binary_compatibility.tar.gz.sha1
@@ -1 +1 @@
-e7ea0fbb97ccfb2faa89b58d60f8b54f5bca0130
\ No newline at end of file
+e69bc2aa67c9ef4d89849a5554dd16383813a9ea
\ No newline at end of file