[Retrace] Allow for numbers in file names unless they are after a colon

Bug: 175355636
Change-Id: I385778dfbb4642d8af018ed243293fa58ac4a818
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 d475594..fb79984 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,7 +166,8 @@
     }
   }
 
-  private static final String anyLetterWithMarkers = "\\p{L}\\p{M}*+";
+  private static final String anyNonDigitLetterCharWithMarkers = "\\p{L}\\p{M}*+";
+  private static final String anyDigit = "\\p{N}";
 
   // TODO(b/145731185): Extend support for identifiers with strings inside back ticks.
   private static final String javaIdentifierSegment =
@@ -275,7 +276,10 @@
 
     @Override
     String subExpression() {
-      return "(?:([" + anyLetterWithMarkers + "_: \\.]*[" + anyLetterWithMarkers + "_\\.])?)";
+      String anyNonDigitSourceFileChar = anyNonDigitLetterCharWithMarkers + "_ \\.";
+      String anyChar = anyNonDigitSourceFileChar + anyDigit;
+      String colonWithNonDigitSuffix = ":[" + anyNonDigitSourceFileChar + ":" + "]";
+      return "((?:(?:(?:" + colonWithNonDigitSuffix + "))|(?:[" + anyChar + "]))+)?";
     }
 
     @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 0c7dd7a..d23b24e 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
@@ -38,6 +38,7 @@
 import com.android.tools.r8.retrace.stacktraces.ObfucatedExceptionClassStackTrace;
 import com.android.tools.r8.retrace.stacktraces.ObfuscatedRangeToSingleLineStackTrace;
 import com.android.tools.r8.retrace.stacktraces.RetraceAssertionErrorStackTrace;
+import com.android.tools.r8.retrace.stacktraces.SourceFileWithNumberAndEmptyStackTrace;
 import com.android.tools.r8.retrace.stacktraces.StackTraceForTest;
 import com.android.tools.r8.retrace.stacktraces.SuppressedStackTrace;
 import com.android.tools.r8.retrace.stacktraces.UnicodeInFileNameStackTrace;
@@ -217,6 +218,11 @@
     inspectRetraceTest(stackTraceForTest, stackTraceForTest::inspectField);
   }
 
+  @Test
+  public void testSourceFileWithNumberAndEmptyStackTrace() {
+    runRetraceTest(new SourceFileWithNumberAndEmptyStackTrace());
+  }
+
   private void inspectRetraceTest(
       StackTraceForTest stackTraceForTest, Consumer<Retracer> inspection) {
     inspection.accept(
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/SourceFileWithNumberAndEmptyStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/SourceFileWithNumberAndEmptyStackTrace.java
new file mode 100644
index 0000000..8a94018
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/SourceFileWithNumberAndEmptyStackTrace.java
@@ -0,0 +1,45 @@
+// 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.android.tools.r8.utils.StringUtils;
+import java.util.Arrays;
+import java.util.List;
+
+public class SourceFileWithNumberAndEmptyStackTrace implements StackTraceForTest {
+
+  @Override
+  public List<String> obfuscatedStackTrace() {
+    return Arrays.asList(
+        "  at com.android.tools.r8.R8.a(R.java:34)", "  at com.android.tools.r8.R8.a(:34)");
+  }
+
+  @Override
+  public String mapping() {
+    return StringUtils.lines(
+        "com.android.tools.r8.R8 -> com.android.tools.r8.R8:",
+        "  34:34:void com.android.tools.r8.utils.ExceptionUtils.withR8CompilationHandler("
+            + "com.android.tools.r8.utils.Reporter,"
+            + "com.android.tools.r8.utils.ExceptionUtils$CompileAction):59:59 -> a",
+        "  34:34:void runForTesting(com.android.tools.r8.utils.AndroidApp,"
+            + "com.android.tools.r8.utils.InternalOptions):261 -> a");
+  }
+
+  @Override
+  public List<String> retracedStackTrace() {
+    return Arrays.asList(
+        "  at com.android.tools.r8.utils.ExceptionUtils.withR8CompilationHandler("
+            + "ExceptionUtils.java:59)",
+        "  at com.android.tools.r8.R8.runForTesting(R.java:261)",
+        "  at com.android.tools.r8.utils.ExceptionUtils.withR8CompilationHandler("
+            + "ExceptionUtils.java:59)",
+        "  at com.android.tools.r8.R8.runForTesting(R8.java:261)");
+  }
+
+  @Override
+  public int expectedWarnings() {
+    return 0;
+  }
+}
diff --git a/tools/retrace.py b/tools/retrace.py
index 70e3099..41b5a06 100755
--- a/tools/retrace.py
+++ b/tools/retrace.py
@@ -45,6 +45,11 @@
       default=None,
       action='store_true',
       help='Disables diagnostics printing to stdout.')
+  parser.add_argument(
+    '--debug-agent',
+    default=None,
+    action='store_true',
+    help='Attach a debug-agent to the retracer java process.')
   return parser.parse_args()
 
 
@@ -73,9 +78,11 @@
       args.stacktrace,
       args.commit_hash is not None,
       args.no_r8lib,
-      quiet=args.quiet)
+      quiet=args.quiet,
+      debug=args.debug_agent)
 
-def run(map_path, hash_or_version, stacktrace, is_hash, no_r8lib, quiet=False):
+def run(map_path, hash_or_version, stacktrace, is_hash, no_r8lib, quiet=False,
+        debug=False):
   if hash_or_version:
     download_path = archive.GetUploadDestination(
         hash_or_version,
@@ -88,8 +95,12 @@
       print('Could not find map file from argument: %s.' % hash_or_version)
       return 1
 
-  retrace_args = [
-    jdk.GetJavaExecutable(),
+  retrace_args = [jdk.GetJavaExecutable()]
+
+  if debug:
+    retrace_args.append('-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005')
+
+  retrace_args += [
     '-cp',
     utils.R8_JAR if no_r8lib else utils.R8LIB_JAR,
     'com.android.tools.r8.retrace.Retrace',