Add support for using colon in stack trace source files

This is needed since an internal regression was reported on Remapper

Change-Id: Ieadbb4a0ba4e9f6e6d163118f8506cf25d1ae8ad
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 45b0c28..90fedbd 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
@@ -167,8 +167,8 @@
               .registerClassName(classStartIndex, methodSeparator, ClassNameType.TYPENAME)
               .registerMethodName(methodSeparator + 1, parensStart);
       // Check if we have a filename and position.
-      int separatorIndex = firstCharFromIndex(line, parensStart, ':');
-      if (separatorIndex < parensEnd) {
+      int separatorIndex = line.lastIndexOf(':', parensEnd);
+      if (separatorIndex > -1 && separatorIndex < parensEnd) {
         builder.registerSourceFile(parensStart + 1, separatorIndex);
         builder.registerLineNumber(separatorIndex + 1, parensEnd);
       } else {
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 e5a2906..d475594 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
@@ -166,6 +166,8 @@
     }
   }
 
+  private static final String anyLetterWithMarkers = "\\p{L}\\p{M}*+";
+
   // TODO(b/145731185): Extend support for identifiers with strings inside back ticks.
   private static final String javaIdentifierSegment =
       "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";
@@ -273,7 +275,7 @@
 
     @Override
     String subExpression() {
-      return "(?:(\\w*[\\. ])?(\\w*)?)";
+      return "(?:([" + anyLetterWithMarkers + "_: \\.]*[" + anyLetterWithMarkers + "_\\.])?)";
     }
 
     @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
index 458f56c..0c7dd7a 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
@@ -23,6 +23,7 @@
 import com.android.tools.r8.retrace.stacktraces.AmbiguousWithMultipleLineMappingsStackTrace;
 import com.android.tools.r8.retrace.stacktraces.AmbiguousWithSignatureNonVerboseStackTrace;
 import com.android.tools.r8.retrace.stacktraces.CircularReferenceStackTrace;
+import com.android.tools.r8.retrace.stacktraces.ColonInFileNameStackTrace;
 import com.android.tools.r8.retrace.stacktraces.FileNameExtensionStackTrace;
 import com.android.tools.r8.retrace.stacktraces.InlineFileNameStackTrace;
 import com.android.tools.r8.retrace.stacktraces.InlineFileNameWithInnerClassesStackTrace;
@@ -31,6 +32,7 @@
 import com.android.tools.r8.retrace.stacktraces.InlineWithLineNumbersStackTrace;
 import com.android.tools.r8.retrace.stacktraces.InvalidStackTrace;
 import com.android.tools.r8.retrace.stacktraces.MemberFieldOverlapStackTrace;
+import com.android.tools.r8.retrace.stacktraces.MultipleDotsInFileNameStackTrace;
 import com.android.tools.r8.retrace.stacktraces.NamedModuleStackTrace;
 import com.android.tools.r8.retrace.stacktraces.NullStackTrace;
 import com.android.tools.r8.retrace.stacktraces.ObfucatedExceptionClassStackTrace;
@@ -38,6 +40,7 @@
 import com.android.tools.r8.retrace.stacktraces.RetraceAssertionErrorStackTrace;
 import com.android.tools.r8.retrace.stacktraces.StackTraceForTest;
 import com.android.tools.r8.retrace.stacktraces.SuppressedStackTrace;
+import com.android.tools.r8.retrace.stacktraces.UnicodeInFileNameStackTrace;
 import com.android.tools.r8.retrace.stacktraces.UnknownSourceStackTrace;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.google.common.collect.ImmutableList;
@@ -193,7 +196,22 @@
   }
 
   @Test
-  public void testMemberFieldOverlapStackTrace() throws Exception {
+  public void testColonInSourceFileNameStackTrace() {
+    runRetraceTest(new ColonInFileNameStackTrace());
+  }
+
+  @Test
+  public void testMultipleDotsInFileNameStackTrace() {
+    runRetraceTest(new MultipleDotsInFileNameStackTrace());
+  }
+
+  @Test
+  public void testUnicodeInFileNameStackTrace() {
+    runRetraceTest(new UnicodeInFileNameStackTrace());
+  }
+
+  @Test
+  public void testMemberFieldOverlapStackTrace() {
     MemberFieldOverlapStackTrace stackTraceForTest = new MemberFieldOverlapStackTrace();
     runRetraceTest(stackTraceForTest);
     inspectRetraceTest(stackTraceForTest, stackTraceForTest::inspectField);
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/ColonInFileNameStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/ColonInFileNameStackTrace.java
new file mode 100644
index 0000000..0bdb870
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/ColonInFileNameStackTrace.java
@@ -0,0 +1,35 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.stacktraces;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+public class ColonInFileNameStackTrace implements StackTraceForTest {
+
+  @Override
+  public List<String> obfuscatedStackTrace() {
+    return ImmutableList.of("  at a.s(:foo::bar:1)");
+  }
+
+  @Override
+  public String mapping() {
+    return "some.Class -> a:\n"
+        // Sourcefile metadata.
+        + "# {\"id\":\"sourceFile\",\"fileName\":\"Class.kt\"}\n"
+        + "    1:3:int strawberry(int):99:101 -> s\n"
+        + "    4:5:int mango(float):121:122 -> s\n";
+  }
+
+  @Override
+  public List<String> retracedStackTrace() {
+    return ImmutableList.of("  at some.Class.strawberry(Class.kt:99)");
+  }
+
+  @Override
+  public int expectedWarnings() {
+    return 0;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleDotsInFileNameStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleDotsInFileNameStackTrace.java
new file mode 100644
index 0000000..a67335f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleDotsInFileNameStackTrace.java
@@ -0,0 +1,35 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.stacktraces;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+public class MultipleDotsInFileNameStackTrace implements StackTraceForTest {
+
+  @Override
+  public List<String> obfuscatedStackTrace() {
+    return ImmutableList.of("  at a.s(foo.bar.baz:1)");
+  }
+
+  @Override
+  public String mapping() {
+    return "some.Class -> a:\n"
+        // Sourcefile metadata.
+        + "# {\"id\":\"sourceFile\",\"fileName\":\"Class.kt\"}\n"
+        + "    1:3:int strawberry(int):99:101 -> s\n"
+        + "    4:5:int mango(float):121:122 -> s\n";
+  }
+
+  @Override
+  public List<String> retracedStackTrace() {
+    return ImmutableList.of("  at some.Class.strawberry(Class.kt:99)");
+  }
+
+  @Override
+  public int expectedWarnings() {
+    return 0;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/UnicodeInFileNameStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/UnicodeInFileNameStackTrace.java
new file mode 100644
index 0000000..5090c39
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/UnicodeInFileNameStackTrace.java
@@ -0,0 +1,35 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.stacktraces;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+public class UnicodeInFileNameStackTrace implements StackTraceForTest {
+
+  @Override
+  public List<String> obfuscatedStackTrace() {
+    return ImmutableList.of("  at a.s(Blåbærgrød.jàvà:1)");
+  }
+
+  @Override
+  public String mapping() {
+    return "some.Class -> a:\n"
+        // Sourcefile metadata.
+        + "# {\"id\":\"sourceFile\",\"fileName\":\"Class.kt\"}\n"
+        + "    1:3:int strawberry(int):99:101 -> s\n"
+        + "    4:5:int mango(float):121:122 -> s\n";
+  }
+
+  @Override
+  public List<String> retracedStackTrace() {
+    return ImmutableList.of("  at some.Class.strawberry(Class.kt:99)");
+  }
+
+  @Override
+  public int expectedWarnings() {
+    return 0;
+  }
+}