Use reporter for handling diagnostics in tracereferences

Bug: 169127026
BUg: 169546956
Change-Id: I5b467951517ec6653841d7eb4c0d386df3cf2bc8
diff --git a/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java b/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java
index 542a8a3..0f9c27e 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java
@@ -8,17 +8,18 @@
 import com.android.tools.r8.ProgramResource;
 import com.android.tools.r8.ProgramResource.Kind;
 import com.android.tools.r8.ProgramResourceProvider;
+import com.android.tools.r8.ResourceException;
 import com.android.tools.r8.Version;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.origin.CommandLineOrigin;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.ExceptionDiagnostic;
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.ImmutableList;
+import java.io.IOException;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -26,17 +27,11 @@
 public class TraceReferences {
 
   public static void run(TraceReferencesCommand command) throws CompilationFailedException {
-    try {
-      runInternal(command);
-    } catch (TraceReferencesAbortException e) {
-      throw new CompilationFailedException();
-    } catch (Exception e) {
-      command.getDiagnosticsHandler().error(new ExceptionDiagnostic(e));
-      throw new CompilationFailedException(e);
-    }
+    ExceptionUtils.withCompilationHandler(command.getReporter(), () -> runInternal(command));
   }
 
-  private static void runInternal(TraceReferencesCommand command) throws Exception {
+  private static void runInternal(TraceReferencesCommand command)
+      throws IOException, ResourceException {
     AndroidApp.Builder builder = AndroidApp.builder();
     command.getLibrary().forEach(builder::addLibraryResourceProvider);
     command.getTarget().forEach(builder::addLibraryResourceProvider);
@@ -48,9 +43,7 @@
     for (ProgramResourceProvider provider : command.getSource()) {
       for (ProgramResource programResource : provider.getProgramResources()) {
         if (programResource.getKind() == Kind.DEX) {
-          command
-              .getDiagnosticsHandler()
-              .warning(new StringDiagnostic("DEX files not fully supported"));
+          command.getReporter().warning(new StringDiagnostic("DEX files not fully supported"));
           assert programResource.getClassDescriptors() == null;
           for (DexProgramClass clazz :
               new ApplicationReader(
@@ -68,7 +61,7 @@
         }
       }
     }
-    Tracer tracer = new Tracer(tagetDescriptors, builder.build(), command.getDiagnosticsHandler());
+    Tracer tracer = new Tracer(tagetDescriptors, builder.build(), command.getReporter());
     tracer.run(command.getConsumer());
   }
 
@@ -86,7 +79,17 @@
     run(command);
   }
 
+  /**
+   * Command-line entry to tracereferences.
+   *
+   * <p>See {@link TraceReferencesCommandParser#USAGE_MESSAGE} or run {@code tracereferences --help}
+   * for usage information.
+   */
   public static void main(String[] args) {
+    if (args.length == 0) {
+      System.err.println(TraceReferencesCommandParser.USAGE_MESSAGE);
+      System.exit(ExceptionUtils.STATUS_ERROR);
+    }
     ExceptionUtils.withMainProgramHandler(() -> run(args));
   }
 }
diff --git a/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesCommand.java b/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesCommand.java
index 87dc818..6923654 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesCommand.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesCommand.java
@@ -12,11 +12,13 @@
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.Keep;
 import com.android.tools.r8.ProgramResourceProvider;
-import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.origin.PathOrigin;
 import com.android.tools.r8.utils.ArchiveResourceProvider;
+import com.android.tools.r8.utils.Box;
 import com.android.tools.r8.utils.ExceptionDiagnostic;
+import com.android.tools.r8.utils.ExceptionUtils;
+import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
@@ -31,7 +33,7 @@
 public class TraceReferencesCommand {
   private final boolean printHelp;
   private final boolean printVersion;
-  private final DiagnosticsHandler diagnosticsHandler;
+  private final Reporter reporter;
   private final ImmutableList<ClassFileResourceProvider> library;
   private final ImmutableList<ClassFileResourceProvider> traceTarget;
   private final ImmutableList<ProgramResourceProvider> traceSource;
@@ -40,20 +42,30 @@
   TraceReferencesCommand(
       boolean printHelp,
       boolean printVersion,
-      DiagnosticsHandler diagnosticsHandler,
+      Reporter reporter,
       ImmutableList<ClassFileResourceProvider> library,
       ImmutableList<ClassFileResourceProvider> traceTarget,
       ImmutableList<ProgramResourceProvider> traceSource,
       TraceReferencesConsumer consumer) {
     this.printHelp = printHelp;
     this.printVersion = printVersion;
-    this.diagnosticsHandler = diagnosticsHandler;
+    this.reporter = reporter;
     this.library = library;
     this.traceTarget = traceTarget;
     this.traceSource = traceSource;
     this.consumer = consumer;
   }
 
+  TraceReferencesCommand(boolean printHelp, boolean printVersion) {
+    this.printHelp = printHelp;
+    this.printVersion = printVersion;
+    this.reporter = null;
+    this.library = null;
+    this.traceTarget = null;
+    this.traceSource = null;
+    this.consumer = null;
+  }
+
   /**
    * Utility method for obtaining a <code>ReferenceTraceCommand.Builder</code>.
    *
@@ -68,7 +80,7 @@
    * diagnostics handler.
    */
   public static Builder builder() {
-    return new Builder(new DiagnosticsHandler() {});
+    return new Builder();
   }
 
   public static Builder parse(String[] args, Origin origin) {
@@ -89,10 +101,9 @@
 
   public static class Builder {
 
-    private boolean errors = false;
     private boolean printHelp = false;
     private boolean printVersion = false;
-    private final DiagnosticsHandler diagnosticsHandler;
+    private final Reporter reporter;
     private final ImmutableList.Builder<ClassFileResourceProvider> libraryBuilder =
         ImmutableList.builder();
     private final ImmutableList.Builder<ClassFileResourceProvider> traceTargetBuilder =
@@ -101,10 +112,24 @@
         ImmutableList.builder();
     private TraceReferencesConsumer consumer;
 
-    private Builder(DiagnosticsHandler diagnosticsHandler) {
-      this.diagnosticsHandler = diagnosticsHandler;
+    private Builder() {
+      this(new DiagnosticsHandler() {});
     }
 
+    private Builder(DiagnosticsHandler diagnosticsHandler) {
+      this.reporter = new Reporter(diagnosticsHandler);
+    }
+
+    Reporter getReporter() {
+      return reporter;
+    }
+
+    /** True if the print-help flag is enabled. */
+    public boolean isPrintHelp() {
+      return printHelp;
+    }
+
+    /** Set the value of the print-help flag. */
     public Builder setPrintHelp(boolean printHelp) {
       this.printHelp = printHelp;
       return this;
@@ -199,7 +224,11 @@
       return this;
     }
 
-    public final TraceReferencesCommand build() throws CompilationFailedException {
+    private TraceReferencesCommand makeCommand() {
+      if (isPrintHelp() || isPrintVersion()) {
+        return new TraceReferencesCommand(isPrintHelp(), isPrintVersion());
+      }
+
       ImmutableList<ClassFileResourceProvider> library = libraryBuilder.build();
       ImmutableList<ClassFileResourceProvider> traceTarget = traceTargetBuilder.build();
       ImmutableList<ProgramResourceProvider> traceSource = traceSourceBuilder.build();
@@ -216,22 +245,29 @@
       if (consumer == null) {
         error(new StringDiagnostic("No consumer specified"));
       }
-      if (errors) {
-        throw new CompilationFailedException(new CompilationError(""));
-      }
       return new TraceReferencesCommand(
-          printHelp, printVersion, diagnosticsHandler, library, traceTarget, traceSource, consumer);
+          printHelp, printVersion, reporter, library, traceTarget, traceSource, consumer);
+    }
+
+    public final TraceReferencesCommand build() throws CompilationFailedException {
+      Box<TraceReferencesCommand> box = new Box<>(null);
+      ExceptionUtils.withCompilationHandler(
+          reporter,
+          () -> {
+            box.set(makeCommand());
+            reporter.failIfPendingErrors();
+          });
+      return box.get();
     }
 
     void error(Diagnostic diagnostic) {
-      errors = true;
-      diagnosticsHandler.error(diagnostic);
+      reporter.error(diagnostic);
       // For now all errors are fatal.
     }
   }
 
-  DiagnosticsHandler getDiagnosticsHandler() {
-    return diagnosticsHandler;
+  Reporter getReporter() {
+    return reporter;
   }
 
   List<ClassFileResourceProvider> getLibrary() {
diff --git a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
index 4432530..4d44912 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
@@ -43,6 +43,7 @@
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.Timing;
+import java.io.IOException;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -226,12 +227,11 @@
   private final AppInfoWithClassHierarchy appInfo;
 
   Tracer(Set<String> descriptors, AndroidApp inputApp, DiagnosticsHandler diagnostics)
-      throws Exception {
+      throws IOException {
     this.descriptors = descriptors;
     this.diagnostics = diagnostics;
     InternalOptions options = new InternalOptions();
-    application =
-        new ApplicationReader(inputApp, options, new Timing("ReferenceTrace")).read().toDirect();
+    application = new ApplicationReader(inputApp, options, Timing.empty()).read().toDirect();
     appInfo =
         AppInfoWithClassHierarchy.createInitialAppInfoWithClassHierarchy(
             application,