Refactor inline position to match on file name

This will also generalize the use such that it can be used for
matching on any StackTraceLine.

Change-Id: Ib9fe3bd54a1330b1844b203b45e41aee9df50746
diff --git a/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java
index b344944..9d9d386 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java
@@ -28,7 +28,7 @@
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
-import com.android.tools.r8.utils.codeinspector.Matchers.InlinePosition;
+import com.android.tools.r8.utils.codeinspector.Matchers.LinePosition;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
@@ -41,6 +41,7 @@
 @RunWith(Parameterized.class)
 public class DexPcWithDebugInfoForOverloadedMethodsTestRunner extends TestBase {
 
+  private static final String FILENAME_INLINE = "InlineFunction.kt";
   private static final Class<?> MAIN = DexPcWithDebugInfoForOverloadedMethodsTest.class;
   private static final int MINIFIED_LINE_POSITION = 6;
   private static final String EXPECTED = "java.lang.RuntimeException: overloaded(String)42";
@@ -86,18 +87,20 @@
               MethodSubject throwingSubject =
                   codeInspector.clazz(MAIN).method("void", "overloaded", "java.lang.String");
               assertThat(throwingSubject, isPresent());
-              InlinePosition inlineStack =
-                  InlinePosition.stack(
-                      InlinePosition.create(
+              LinePosition inlineStack =
+                  LinePosition.stack(
+                      LinePosition.create(
                           Reference.methodFromMethod(
                               MAIN.getDeclaredMethod("inlinee", String.class)),
                           MINIFIED_LINE_POSITION,
-                          11),
-                      InlinePosition.create(
+                          11,
+                          FILENAME_INLINE),
+                      LinePosition.create(
                           Reference.methodFromMethod(
                               MAIN.getDeclaredMethod("overloaded", String.class)),
                           MINIFIED_LINE_POSITION,
-                          20));
+                          20,
+                          FILENAME_INLINE));
               RetraceMethodResult retraceResult =
                   throwingSubject
                       .streamInstructions()
diff --git a/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
index c47f16f..ae533a4 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
@@ -22,7 +22,7 @@
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
-import com.android.tools.r8.utils.codeinspector.Matchers.InlinePosition;
+import com.android.tools.r8.utils.codeinspector.Matchers.LinePosition;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
@@ -35,6 +35,7 @@
 @RunWith(Parameterized.class)
 public class EnsureNoDebugInfoEmittedForPcOnlyTestRunner extends TestBase {
 
+  private static final String FILENAME_MAIN = "EnsureNoDebugInfoEmittedForPcOnlyTest.java";
   private static final Class<?> MAIN = EnsureNoDebugInfoEmittedForPcOnlyTest.class;
   private static final int INLINED_DEX_PC = 32;
 
@@ -75,20 +76,23 @@
         .inspectStackTrace(
             (stackTrace, codeInspector) -> {
               MethodSubject mainSubject = codeInspector.clazz(MAIN).uniqueMethodWithName("main");
-              InlinePosition inlineStack =
-                  InlinePosition.stack(
-                      InlinePosition.create(
+              LinePosition inlineStack =
+                  LinePosition.stack(
+                      LinePosition.create(
                           Reference.methodFromMethod(MAIN.getDeclaredMethod("a")),
                           INLINED_DEX_PC,
-                          11),
-                      InlinePosition.create(
+                          11,
+                          FILENAME_MAIN),
+                      LinePosition.create(
                           Reference.methodFromMethod(MAIN.getDeclaredMethod("b")),
                           INLINED_DEX_PC,
-                          18),
-                      InlinePosition.create(
+                          18,
+                          FILENAME_MAIN),
+                      LinePosition.create(
                           mainSubject.asFoundMethodSubject().asMethodReference(),
                           INLINED_DEX_PC,
-                          23));
+                          23,
+                          FILENAME_MAIN));
               RetraceMethodResult retraceResult =
                   mainSubject
                       .streamInstructions()
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java b/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java
index d4b758e..2d5e31b 100644
--- a/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java
+++ b/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java
@@ -205,6 +205,10 @@
     return originalStderr;
   }
 
+  public List<StackTraceLine> getStackTraceLines() {
+    return stackTraceLines;
+  }
+
   public static StackTrace extractFromArt(String stderr, DexVm vm) {
     List<StackTraceLine> stackTraceLines = new ArrayList<>();
     List<String> stderrLines = StringUtils.splitLines(stderr);
diff --git a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java
index d70f22b..1fa811a 100644
--- a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java
@@ -6,7 +6,7 @@
 import static com.android.tools.r8.Collectors.toSingle;
 import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
 import static com.android.tools.r8.ToolHelper.getFilesInTestFolderRelativeToClass;
-import static com.android.tools.r8.utils.codeinspector.Matchers.containsInlinePosition;
+import static com.android.tools.r8.utils.codeinspector.Matchers.containsLinePositions;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isInlineFrame;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isInlineStack;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
@@ -26,7 +26,7 @@
 import com.android.tools.r8.naming.retrace.StackTrace;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
-import com.android.tools.r8.utils.codeinspector.Matchers.InlinePosition;
+import com.android.tools.r8.utils.codeinspector.Matchers.LinePosition;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -40,6 +40,7 @@
 @RunWith(Parameterized.class)
 public class KotlinInlineFunctionInSameFileRetraceTests extends TestBase {
 
+  private static final String FILENAME_INLINE = "InlineFunctionsInSameFile.kt";
   private static final String MAIN = "retrace.InlineFunctionsInSameFileKt";
 
   private final TestParameters parameters;
@@ -97,16 +98,18 @@
         .inspectStackTrace(
             (stackTrace, codeInspector) -> {
               MethodSubject mainSubject = codeInspector.clazz(MAIN).uniqueMethodWithName("main");
-              InlinePosition inlineStack =
-                  InlinePosition.stack(
-                      InlinePosition.create(
+              LinePosition inlineStack =
+                  LinePosition.stack(
+                      LinePosition.create(
                           kotlinInspector
                               .clazz("retrace.InlineFunctionsInSameFileKt")
                               .uniqueMethodWithName("foo")
                               .asFoundMethodSubject(),
                           1,
-                          8),
-                      InlinePosition.create(mainSubject.asFoundMethodSubject(), 1, 43));
+                          8,
+                          FILENAME_INLINE),
+                      LinePosition.create(
+                          mainSubject.asFoundMethodSubject(), 1, 43, FILENAME_INLINE));
               checkInlineInformation(stackTrace, codeInspector, mainSubject, inlineStack);
             });
   }
@@ -115,7 +118,7 @@
       StackTrace stackTrace,
       CodeInspector codeInspector,
       MethodSubject mainSubject,
-      InlinePosition inlineStack) {
+      LinePosition inlineStack) {
     assertThat(mainSubject, isPresent());
     RetraceMethodResult retraceResult =
         mainSubject
@@ -125,6 +128,6 @@
             .retraceLinePosition(codeInspector.retrace());
     assertThat(retraceResult, isInlineFrame());
     assertThat(retraceResult, isInlineStack(inlineStack));
-    assertThat(stackTrace, containsInlinePosition(inlineStack));
+    assertThat(stackTrace, containsLinePositions(inlineStack));
   }
 }
diff --git a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java
index b4d302b..05b028a 100644
--- a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java
@@ -7,7 +7,7 @@
 import static com.android.tools.r8.Collectors.toSingle;
 import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
 import static com.android.tools.r8.ToolHelper.getFilesInTestFolderRelativeToClass;
-import static com.android.tools.r8.utils.codeinspector.Matchers.containsInlinePosition;
+import static com.android.tools.r8.utils.codeinspector.Matchers.containsLinePositions;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isInlineFrame;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isInlineStack;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
@@ -28,7 +28,7 @@
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
-import com.android.tools.r8.utils.codeinspector.Matchers.InlinePosition;
+import com.android.tools.r8.utils.codeinspector.Matchers.LinePosition;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -43,6 +43,9 @@
 public class KotlinInlineFunctionRetraceTest extends TestBase {
 
   private final TestParameters parameters;
+  // TODO(b/151132660): Fix filename
+  private static final String FILENAME_INLINE_STATIC = "InlineFunctionKt.kt";
+  private static final String FILENAME_INLINE_INSTANCE = "InlineFunction.kt";
 
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
@@ -93,6 +96,7 @@
   public void testRetraceKotlinInlineStaticFunction()
       throws ExecutionException, CompilationFailedException, IOException {
     String main = "retrace.MainKt";
+    String mainFileName = "Main.kt";
     Path kotlinSources = compilationResults.apply(parameters.getRuntime());
     CodeInspector kotlinInspector = new CodeInspector(kotlinSources);
     testForR8(parameters.getBackend())
@@ -109,10 +113,11 @@
         .inspectStackTrace(
             (stackTrace, codeInspector) -> {
               MethodSubject mainSubject = codeInspector.clazz(main).uniqueMethodWithName("main");
-              InlinePosition inlineStack =
-                  InlinePosition.stack(
-                      InlinePosition.create(inlineExceptionStatic(kotlinInspector), 2, 8),
-                      InlinePosition.create(mainSubject.asFoundMethodSubject(), 2, 15));
+              LinePosition inlineStack =
+                  LinePosition.stack(
+                      LinePosition.create(
+                          inlineExceptionStatic(kotlinInspector), 2, 8, FILENAME_INLINE_STATIC),
+                      LinePosition.create(mainSubject.asFoundMethodSubject(), 2, 15, mainFileName));
               checkInlineInformation(stackTrace, codeInspector, mainSubject, inlineStack);
             });
   }
@@ -121,6 +126,7 @@
   public void testRetraceKotlinInlineInstanceFunction()
       throws ExecutionException, CompilationFailedException, IOException {
     String main = "retrace.MainInstanceKt";
+    String mainFileName = "MainInstance.kt";
     Path kotlinSources = compilationResults.apply(parameters.getRuntime());
     CodeInspector kotlinInspector = new CodeInspector(kotlinSources);
     testForR8(parameters.getBackend())
@@ -137,10 +143,14 @@
         .inspectStackTrace(
             (stackTrace, codeInspector) -> {
               MethodSubject mainSubject = codeInspector.clazz(main).uniqueMethodWithName("main");
-              InlinePosition inlineStack =
-                  InlinePosition.stack(
-                      InlinePosition.create(inlineExceptionInstance(kotlinInspector), 2, 15),
-                      InlinePosition.create(mainSubject.asFoundMethodSubject(), 2, 13));
+              LinePosition inlineStack =
+                  LinePosition.stack(
+                      LinePosition.create(
+                          inlineExceptionInstance(kotlinInspector),
+                          2,
+                          15,
+                          FILENAME_INLINE_INSTANCE),
+                      LinePosition.create(mainSubject.asFoundMethodSubject(), 2, 13, mainFileName));
               checkInlineInformation(stackTrace, codeInspector, mainSubject, inlineStack);
             });
   }
@@ -149,6 +159,7 @@
   public void testRetraceKotlinNestedInlineFunction()
       throws ExecutionException, CompilationFailedException, IOException {
     String main = "retrace.MainNestedKt";
+    String mainFileName = "MainNested.kt";
     Path kotlinSources = compilationResults.apply(parameters.getRuntime());
     CodeInspector kotlinInspector = new CodeInspector(kotlinSources);
     testForR8(parameters.getBackend())
@@ -165,12 +176,13 @@
         .inspectStackTrace(
             (stackTrace, codeInspector) -> {
               MethodSubject mainSubject = codeInspector.clazz(main).uniqueMethodWithName("main");
-              InlinePosition inlineStack =
-                  InlinePosition.stack(
-                      InlinePosition.create(inlineExceptionStatic(kotlinInspector), 3, 8),
+              LinePosition inlineStack =
+                  LinePosition.stack(
+                      LinePosition.create(
+                          inlineExceptionStatic(kotlinInspector), 3, 8, FILENAME_INLINE_STATIC),
                       // TODO(b/146399675): There should be a nested frame on
                       //  retrace.NestedInlineFunctionKt.nestedInline(line 10).
-                      InlinePosition.create(mainSubject.asFoundMethodSubject(), 3, 19));
+                      LinePosition.create(mainSubject.asFoundMethodSubject(), 3, 19, mainFileName));
               checkInlineInformation(stackTrace, codeInspector, mainSubject, inlineStack);
             });
   }
@@ -179,6 +191,7 @@
   public void testRetraceKotlinNestedInlineFunctionOnFirstLine()
       throws ExecutionException, CompilationFailedException, IOException {
     String main = "retrace.MainNestedFirstLineKt";
+    String mainFileName = "MainNestedFirstLine.kt";
     Path kotlinSources = compilationResults.apply(parameters.getRuntime());
     CodeInspector kotlinInspector = new CodeInspector(kotlinSources);
     testForR8(parameters.getBackend())
@@ -195,12 +208,13 @@
         .inspectStackTrace(
             (stackTrace, codeInspector) -> {
               MethodSubject mainSubject = codeInspector.clazz(main).uniqueMethodWithName("main");
-              InlinePosition inlineStack =
-                  InlinePosition.stack(
-                      InlinePosition.create(inlineExceptionStatic(kotlinInspector), 2, 8),
+              LinePosition inlineStack =
+                  LinePosition.stack(
+                      LinePosition.create(
+                          inlineExceptionStatic(kotlinInspector), 2, 8, FILENAME_INLINE_STATIC),
                       // TODO(b/146399675): There should be a nested frame on
                       //  retrace.NestedInlineFunctionKt.nestedInlineOnFirstLine(line 15).
-                      InlinePosition.create(mainSubject.asFoundMethodSubject(), 2, 20));
+                      LinePosition.create(mainSubject.asFoundMethodSubject(), 2, 20, mainFileName));
               checkInlineInformation(stackTrace, codeInspector, mainSubject, inlineStack);
             });
   }
@@ -209,7 +223,7 @@
       StackTrace stackTrace,
       CodeInspector codeInspector,
       MethodSubject mainSubject,
-      InlinePosition inlineStack) {
+      LinePosition inlineStack) {
     assertThat(mainSubject, isPresent());
     RetraceMethodResult retraceResult =
         mainSubject
@@ -219,6 +233,6 @@
             .retraceLinePosition(codeInspector.retrace());
     assertThat(retraceResult, isInlineFrame());
     assertThat(retraceResult, isInlineStack(inlineStack));
-    assertThat(stackTrace, containsInlinePosition(inlineStack));
+    assertThat(stackTrace, containsLinePositions(inlineStack));
   }
 }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
index 3fb684f..a360336 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
@@ -428,16 +428,16 @@
     };
   }
 
-  public static Matcher<RetraceMethodResult> isInlineStack(InlinePosition startPosition) {
+  public static Matcher<RetraceMethodResult> isInlineStack(LinePosition startPosition) {
     return new TypeSafeMatcher<RetraceMethodResult>() {
       @Override
       protected boolean matchesSafely(RetraceMethodResult item) {
-        Box<InlinePosition> currentPosition = new Box<>(startPosition);
+        Box<LinePosition> currentPosition = new Box<>(startPosition);
         Box<Boolean> returnValue = new Box<>();
         item.forEach(
             element -> {
               boolean sameMethod;
-              InlinePosition currentInline = currentPosition.get();
+              LinePosition currentInline = currentPosition.get();
               if (currentInline == null) {
                 returnValue.set(false);
                 return;
@@ -492,70 +492,100 @@
     };
   }
 
-  public static Matcher<StackTrace> containsInlinePosition(InlinePosition inlinePosition) {
+  public static Matcher<StackTrace> containsLinePositions(LinePosition linePosition) {
     return new TypeSafeMatcher<StackTrace>() {
       @Override
       protected boolean matchesSafely(StackTrace item) {
-        return containsInlineStack(item, 0, inlinePosition);
+        return containsLinePosition(item, 0, linePosition);
       }
 
       @Override
       public void describeTo(Description description) {
-        description.appendText("cannot be found in stack trace");
+        description.appendText(linePosition + " cannot be found in stack trace");
       }
 
-      private boolean containsInlineStack(
-          StackTrace stackTrace, int index, InlinePosition currentPosition) {
-        if (currentPosition == null) {
+      private boolean containsLinePosition(
+          StackTrace stackTrace, int index, LinePosition linePosition) {
+        if (linePosition == null) {
           return true;
         }
-        if (index >= stackTrace.size()) {
-          return false;
+        Matcher<StackTraceLine> lineMatcher = Matchers.matchesLinePosition(linePosition);
+        for (int i = index; i < stackTrace.getStackTraceLines().size(); i++) {
+          StackTraceLine stackTraceLine = stackTrace.get(i);
+          if (lineMatcher.matches(stackTraceLine)) {
+            return containsLinePosition(stackTrace, index + 1, linePosition.caller);
+          }
         }
-        StackTraceLine stackTraceLine = stackTrace.get(index);
-        boolean resultHere =
-            stackTraceLine.className.equals(currentPosition.getClassName())
-                && stackTraceLine.methodName.equals(currentPosition.getMethodName())
-                && stackTraceLine.lineNumber == currentPosition.originalPosition;
-        if (resultHere && containsInlineStack(stackTrace, index + 1, currentPosition.caller)) {
-          return true;
-        }
-        // Maybe the inline position starts from the top on the next position.
-        return containsInlineStack(stackTrace, index + 1, inlinePosition);
+        return false;
       }
     };
   }
 
-  public static class InlinePosition {
+  public static Matcher<StackTraceLine> matchesLinePosition(LinePosition linePosition) {
+    return new TypeSafeMatcher<StackTraceLine>() {
+
+      @Override
+      protected boolean matchesSafely(StackTraceLine item) {
+        return containsLinePosition(item, linePosition);
+      }
+
+      @Override
+      public void describeTo(Description description) {
+        description.appendText(linePosition + " cannot be found in stack trace");
+      }
+
+      private boolean containsLinePosition(
+          StackTraceLine stackTraceLine, LinePosition currentPosition) {
+        return stackTraceLine.className.equals(currentPosition.getClassName())
+            && stackTraceLine.methodName.equals(currentPosition.getMethodName())
+            && stackTraceLine.lineNumber == currentPosition.originalPosition
+            && stackTraceLine.fileName.equals(currentPosition.filename);
+      }
+    };
+  }
+
+  public static class LinePosition {
     private final MethodReference methodReference;
     private final int minifiedPosition;
     private final int originalPosition;
+    private final String filename;
 
-    private InlinePosition caller;
+    private LinePosition caller;
 
-    private InlinePosition(
-        MethodReference methodReference, int minifiedPosition, int originalPosition) {
+    private LinePosition(
+        MethodReference methodReference,
+        int minifiedPosition,
+        int originalPosition,
+        String filename) {
       this.methodReference = methodReference;
       this.minifiedPosition = minifiedPosition;
       this.originalPosition = originalPosition;
+      this.filename = filename;
     }
 
-    public static InlinePosition create(
-        MethodReference methodReference, int minifiedPosition, int originalPosition) {
-      return new InlinePosition(methodReference, minifiedPosition, originalPosition);
+    public static LinePosition create(
+        MethodReference methodReference,
+        int minifiedPosition,
+        int originalPosition,
+        String filename) {
+      return new LinePosition(methodReference, minifiedPosition, originalPosition, filename);
     }
 
-    public static InlinePosition create(
-        FoundMethodSubject methodSubject, int minifiedPosition, int originalPosition) {
-      return create(methodSubject.asMethodReference(), minifiedPosition, originalPosition);
+    public static LinePosition create(
+        FoundMethodSubject methodSubject,
+        int minifiedPosition,
+        int originalPosition,
+        String filename) {
+      return create(
+          methodSubject.asMethodReference(), minifiedPosition, originalPosition, filename);
     }
 
-    public static InlinePosition stack(InlinePosition... stack) {
+    public static LinePosition stack(LinePosition... stack) {
       setCaller(1, stack);
       return stack[0];
     }
 
-    private static void setCaller(int index, InlinePosition... stack) {
+    private static void setCaller(int index, LinePosition... stack) {
       assert index > 0;
       if (index >= stack.length) {
         return;
@@ -571,5 +601,10 @@
     String getClassName() {
       return methodReference.getHolderClass().getTypeName();
     }
+
+    @Override
+    public String toString() {
+      return getClassName() + "." + getMethodName() + "(" + filename + ":" + originalPosition + ")";
+    }
   }
 }