[Retrace] Print an error message on invalid input file

Bug: 169552658
Change-Id: I18af3de38821465b4c8b9c4743726b9c5689e609
diff --git a/src/main/java/com/android/tools/r8/retrace/DirectClassNameMapperProguardMapProducer.java b/src/main/java/com/android/tools/r8/retrace/DirectClassNameMapperProguardMapProducer.java
index 02dfec0..8efe05a 100644
--- a/src/main/java/com/android/tools/r8/retrace/DirectClassNameMapperProguardMapProducer.java
+++ b/src/main/java/com/android/tools/r8/retrace/DirectClassNameMapperProguardMapProducer.java
@@ -6,14 +6,13 @@
 
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.retrace.RetraceCommand.ProguardMapProducer;
-import java.io.IOException;
 
 public interface DirectClassNameMapperProguardMapProducer extends ProguardMapProducer {
 
   ClassNameMapper getClassNameMapper();
 
   @Override
-  default String get() throws IOException {
+  default String get() {
     throw new RuntimeException("Should not be called for DirectClassNameMapperProguardMapProducer");
   }
 }
diff --git a/src/main/java/com/android/tools/r8/retrace/InvalidMappingFileException.java b/src/main/java/com/android/tools/r8/retrace/InvalidMappingFileException.java
new file mode 100644
index 0000000..86e81e1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/InvalidMappingFileException.java
@@ -0,0 +1,20 @@
+// 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;
+
+import com.android.tools.r8.Keep;
+
+@Keep
+public final class InvalidMappingFileException extends RuntimeException {
+
+  public InvalidMappingFileException(Throwable throwable) {
+    super(throwable);
+  }
+
+  @Override
+  public String getMessage() {
+    return "Unable to parse mapping file";
+  }
+}
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 0e0af5a..d595892 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.Version;
 import com.android.tools.r8.retrace.RetraceCommand.Builder;
 import com.android.tools.r8.retrace.RetraceCommand.ProguardMapProducer;
+import com.android.tools.r8.utils.ExceptionDiagnostic;
 import com.android.tools.r8.utils.OptionsParsing;
 import com.android.tools.r8.utils.OptionsParsing.ParseContext;
 import com.android.tools.r8.utils.StringDiagnostic;
@@ -119,7 +120,15 @@
           new StringDiagnostic(String.format("Could not find mapping file '%s'.", mappingPath)));
       throw new RetraceAbortException();
     }
-    return () -> new String(Files.readAllBytes(path));
+    return () -> {
+      try {
+        return new String(Files.readAllBytes(path));
+      } catch (IOException e) {
+        diagnosticsHandler.error(
+            new StringDiagnostic(String.format("Could not open mapping file '%s'.", mappingPath)));
+        throw new RuntimeException(e);
+      }
+    };
   }
 
   private static List<String> getStackTraceFromFile(
@@ -172,6 +181,9 @@
       command.diagnosticsHandler.error(
           new StringDiagnostic("Could not open mapping input stream: " + ex.getMessage()));
       throw new RetraceAbortException();
+    } catch (InvalidMappingFileException e) {
+      command.diagnosticsHandler.error(new ExceptionDiagnostic(e));
+      throw e;
     }
   }
 
@@ -230,7 +242,7 @@
   }
 
   private static List<String> getStackTraceFromStandardInput() {
-    System.out.println("Waiting for stack-trace input on stdin...");
+    System.out.println("Waiting for stack-trace input...");
     Scanner sc = new Scanner(new InputStreamReader(System.in, Charsets.UTF_8));
     List<String> readLines = new ArrayList<>();
     while (sc.hasNext()) {
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java b/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java
index 9b6694f..b6247df 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java
@@ -6,7 +6,6 @@
 
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.Keep;
-import java.io.IOException;
 import java.util.List;
 import java.util.function.Consumer;
 
@@ -147,6 +146,6 @@
 
   @Keep
   public interface ProguardMapProducer {
-    String get() throws IOException;
+    String get();
   }
 }
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 88c845a..583ca7c 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retracer.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retracer.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.references.TypeReference;
 import com.android.tools.r8.retrace.RetraceCommand.ProguardMapProducer;
-import java.io.IOException;
 
 /** A default implementation for the retrace api using the ClassNameMapper defined in R8. */
 @Keep
@@ -26,15 +25,18 @@
   }
 
   public static RetraceApi create(
-      ProguardMapProducer proguardMapProducer, DiagnosticsHandler diagnosticsHandler)
-      throws IOException {
+      ProguardMapProducer proguardMapProducer, DiagnosticsHandler diagnosticsHandler) {
     if (proguardMapProducer instanceof DirectClassNameMapperProguardMapProducer) {
       return new Retracer(
           ((DirectClassNameMapperProguardMapProducer) proguardMapProducer).getClassNameMapper());
     }
-    ClassNameMapper classNameMapper =
-        ClassNameMapper.mapperFromString(proguardMapProducer.get(), diagnosticsHandler);
-    return new Retracer(classNameMapper);
+    try {
+      ClassNameMapper classNameMapper =
+          ClassNameMapper.mapperFromString(proguardMapProducer.get(), diagnosticsHandler);
+      return new Retracer(classNameMapper);
+    } catch (Throwable throwable) {
+      throw new InvalidMappingFileException(throwable);
+    }
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java
index b6451a5..16f4620 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java
@@ -67,6 +67,18 @@
   }
 
   @Test
+  public void testInvalidMappingFile() throws IOException {
+    Path mappingFile = folder.newFile("mapping.txt").toPath();
+    Files.write(mappingFile, "foo.bar.baz <- is invalid mapping".getBytes());
+    Path stackTraceFile = folder.newFile("stacktrace.txt").toPath();
+    Files.write(stackTraceFile, new byte[0]);
+    runAbortTest(
+        containsString("Unable to parse mapping file"),
+        mappingFile.toString(),
+        stackTraceFile.toString());
+  }
+
+  @Test
   public void testVerbose() throws IOException {
     FoundMethodVerboseStackTrace stackTrace = new FoundMethodVerboseStackTrace();
     runTest(