Ensure unique program-consumer type.

Change-Id: I3075bc56ca8e26af9880d25f5725408a8544d4ba
diff --git a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
index 4ed89d4..4ea102b 100644
--- a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
@@ -12,6 +12,8 @@
 import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.Reporter;
 import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Base class for commands and command builders for compiler applications/tools which besides an
@@ -297,8 +299,31 @@
 
     @Override
     protected void validate() {
-      assert mode != null;
+      if (mode == null) {
+        reporter.error("Expected valid compilation mode, was null");
+      }
       FileUtils.validateOutputFile(outputPath, reporter);
+      List<Class> programConsumerClasses = new ArrayList<>(3);
+      if (programConsumer instanceof DexIndexedConsumer) {
+        programConsumerClasses.add(DexIndexedConsumer.class);
+      }
+      if (programConsumer instanceof DexFilePerClassFileConsumer) {
+        programConsumerClasses.add(DexFilePerClassFileConsumer.class);
+      }
+      if (programConsumer instanceof ClassFileConsumer) {
+        programConsumerClasses.add(ClassFileConsumer.class);
+      }
+      if (programConsumerClasses.size() > 1) {
+        StringBuilder builder = new StringBuilder()
+            .append("Invalid program consumer.")
+            .append(" A program consumer can implement at most one consumer type but ")
+            .append(programConsumer.getClass().getName())
+            .append(" implements types:");
+        for (Class clazz : programConsumerClasses) {
+          builder.append(" ").append(clazz.getName());
+        }
+        reporter.error(builder.toString());
+      }
       super.validate();
     }
   }
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index 7eb73df..91e563a 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -23,6 +23,7 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
+import java.util.Set;
 import java.util.zip.ZipFile;
 import org.junit.Ignore;
 import org.junit.Rule;
@@ -294,6 +295,31 @@
     }
   }
 
+  @Test(expected = CompilationFailedException.class)
+  public void addMultiTypeProgramConsumer() throws CompilationFailedException {
+    class MultiTypeConsumer implements DexIndexedConsumer, DexFilePerClassFileConsumer {
+
+      @Override
+      public void accept(String primaryClassDescriptor, byte[] data, Set<String> descriptors,
+          DiagnosticsHandler handler) {
+
+      }
+
+      @Override
+      public void accept(int fileIndex, byte[] data, Set<String> descriptors,
+          DiagnosticsHandler handler) {
+
+      }
+
+      @Override
+      public void finished(DiagnosticsHandler handler) {
+
+      }
+    }
+
+    D8Command.builder().setProgramConsumer(new MultiTypeConsumer()).build();
+  }
+
   private D8Command parse(String... args) throws CompilationFailedException {
     return D8Command.parse(args, EmbeddedOrigin.INSTANCE).build();
   }