Revert "Introduce ApiLevelException as a checked exception"

This reverts commit cf3e316ac5b5c545b7360d1914ed3986123756ec.

Change-Id: I32463c9224666bec5716ea679a90f9106f4dabc1
diff --git a/src/main/java/com/android/tools/r8/ApiLevelException.java b/src/main/java/com/android/tools/r8/ApiLevelException.java
deleted file mode 100644
index 0087086..0000000
--- a/src/main/java/com/android/tools/r8/ApiLevelException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2017, 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;
-
-/**
- * Exception to signal features that are not supported until a given API level.
- */
-public class ApiLevelException extends CompilationException {
-
-  private final int minApiLevel;
-  private final String minApiLevelString;
-  private final String unsupportedFeatures;
-  private final String sourceString;
-
-  public ApiLevelException(
-      int minApiLevel, String minApiLevelString, String unsupportedFeatures, String sourceString) {
-    super("");
-    assert minApiLevel > 0;
-    assert minApiLevelString != null;
-    assert unsupportedFeatures != null;
-    this.minApiLevel = minApiLevel;
-    this.minApiLevelString = minApiLevelString;
-    this.unsupportedFeatures = unsupportedFeatures;
-    this.sourceString = sourceString;
-  }
-
-  @Override
-  public String getMessage() {
-    String message =
-        unsupportedFeatures
-            + " are only supported starting with "
-            + minApiLevelString
-            + " (--min-api "
-            + minApiLevel
-            + ")";
-    message = (sourceString != null) ? message + ": " + sourceString : message;
-    return message;
-  }
-}
\ No newline at end of file
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index cbbec9e..6988b06 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -62,7 +62,7 @@
    * @param command D8 command.
    * @return the compilation result.
    */
-  public static D8Output run(D8Command command) throws IOException, CompilationException {
+  public static D8Output run(D8Command command) throws IOException {
     InternalOptions options = command.getInternalOptions();
     CompilationResult result = runForTesting(command.getInputApp(), options);
     assert result != null;
@@ -83,8 +83,7 @@
    * @param executor executor service from which to get threads for multi-threaded processing.
    * @return the compilation result.
    */
-  public static D8Output run(D8Command command, ExecutorService executor)
-      throws IOException, CompilationException {
+  public static D8Output run(D8Command command, ExecutorService executor) throws IOException {
     InternalOptions options = command.getInternalOptions();
     CompilationResult result = runForTesting(
         command.getInputApp(), options, executor);
@@ -143,7 +142,7 @@
   }
 
   static CompilationResult runForTesting(AndroidApp inputApp, InternalOptions options)
-      throws IOException, CompilationException {
+      throws IOException {
     ExecutorService executor = ThreadUtils.getExecutorService(options);
     try {
       return runForTesting(inputApp, options, executor);
@@ -153,8 +152,7 @@
   }
 
   static CompilationResult runForTesting(
-      AndroidApp inputApp, InternalOptions options, ExecutorService executor)
-      throws IOException, CompilationException {
+      AndroidApp inputApp, InternalOptions options, ExecutorService executor) throws IOException {
     try {
       assert !inputApp.hasPackageDistribution();
 
@@ -189,8 +187,6 @@
     } catch (ExecutionException e) {
       if (e.getCause() instanceof CompilationError) {
         throw (CompilationError) e.getCause();
-      } else if (e.getCause() instanceof CompilationException) {
-        throw (CompilationException) e.getCause();
       } else {
         throw new RuntimeException(e.getMessage(), e.getCause());
       }
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 76d434c..6586a57 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.dex;
 
-import com.android.tools.r8.ApiLevelException;
 import com.android.tools.r8.dex.VirtualFile.FilePerClassDistributor;
 import com.android.tools.r8.dex.VirtualFile.FillFilesDistributor;
 import com.android.tools.r8.dex.VirtualFile.PackageMapDistributor;
@@ -197,7 +196,7 @@
     }
   }
 
-  private byte[] writeDexFile(VirtualFile vfile) throws ApiLevelException {
+  private byte[] writeDexFile(VirtualFile vfile) {
     FileWriter fileWriter =
         new FileWriter(
             vfile.computeMapping(application), application, appInfo, options, namingLens);
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 90a5dcf..332f292 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -7,7 +7,6 @@
 
 import com.google.common.collect.Sets;
 
-import com.android.tools.r8.ApiLevelException;
 import com.android.tools.r8.code.Instruction;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.AppInfo;
@@ -187,7 +186,7 @@
     return this;
   }
 
-  public byte[] generate() throws ApiLevelException {
+  public byte[] generate() {
     // Check restrictions on interface methods.
     checkInterfaceMethods();
 
@@ -272,15 +271,10 @@
     Arrays.sort(methods, (DexEncodedMethod a, DexEncodedMethod b) -> a.method.compareTo(b.method));
   }
 
-  private void checkInterfaceMethods() throws ApiLevelException {
+  private void checkInterfaceMethods() {
     for (DexProgramClass clazz : mapping.getClasses()) {
       if (clazz.isInterface()) {
-        for (DexEncodedMethod method : clazz.directMethods()) {
-          checkInterfaceMethod(method);
-        }
-        for (DexEncodedMethod method : clazz.virtualMethods()) {
-          checkInterfaceMethod(method);
-        }
+        clazz.forEachMethod(this::checkInterfaceMethod);
       }
     }
   }
@@ -291,18 +285,15 @@
   //  -- starting with N interfaces may also have public or private
   //     static methods, as well as public non-abstract (default)
   //     and private instance methods.
-  private void checkInterfaceMethod(DexEncodedMethod method)
-      throws ApiLevelException {
+  private void checkInterfaceMethod(DexEncodedMethod method) {
     if (application.dexItemFactory.isClassConstructor(method.method)) {
       return; // Class constructor is always OK.
     }
     if (method.accessFlags.isStatic()) {
       if (!options.canUseDefaultAndStaticInterfaceMethods()) {
-        throw new ApiLevelException(
-            Constants.ANDROID_N_API,
-            "Android N",
-            "Static interface methods",
-            method.method.toSourceString());
+        throw new CompilationError("Static interface methods are only supported "
+            + "starting with Android N (--min-api " + Constants.ANDROID_N_API + "): "
+            + method.method.toSourceString());
       }
 
     } else {
@@ -312,11 +303,9 @@
       }
       if (!method.accessFlags.isAbstract() && !method.accessFlags.isPrivate() &&
           !options.canUseDefaultAndStaticInterfaceMethods()) {
-        throw new ApiLevelException(
-            Constants.ANDROID_N_API,
-            "Android N",
-            "Default interface methods",
-            method.method.toSourceString());
+        throw new CompilationError("Default interface methods are only supported "
+            + "starting with Android N (--min-api " + Constants.ANDROID_N_API + "): "
+            + method.method.toSourceString());
       }
     }
 
@@ -324,11 +313,9 @@
       if (options.canUsePrivateInterfaceMethods()) {
         return;
       }
-      throw new ApiLevelException(
-          Constants.ANDROID_N_API,
-          "Android N",
-          "Private interface methods",
-          method.method.toSourceString());
+      throw new CompilationError("Private interface methods are only supported "
+          + "starting with Android N (--min-api " + Constants.ANDROID_N_API + "): "
+          + method.method.toSourceString());
     }
 
     if (!method.accessFlags.isPublic()) {
@@ -369,21 +356,13 @@
   }
 
   private <T extends DexItem> void writeFixedSectionItems(T[] items, int offset,
-      ItemWriter<T> writer) throws ApiLevelException {
+      Consumer<T> writer) {
     assert dest.position() == offset;
     for (T item : items) {
       writer.accept(item);
     }
   }
 
-  /**
-   * Similar to a {@link Consumer} but throws an {@link ApiLevelException}.
-   */
-  @FunctionalInterface
-  private interface ItemWriter<T> {
-    void accept(T t) throws ApiLevelException;
-  }
-
   private <T extends DexItem> void writeItems(Collection<T> items, Consumer<Integer> offsetSetter,
       Consumer<T> writer) {
     writeItems(items, offsetSetter, writer, 1);
@@ -684,7 +663,7 @@
     }
   }
 
-  private void writeMethodHandle(DexMethodHandle methodHandle) throws ApiLevelException {
+  private void writeMethodHandle(DexMethodHandle methodHandle) {
     checkThatInvokeCustomIsAllowed();
     MethodHandleType methodHandleDexType;
     switch (methodHandle.type) {
@@ -713,7 +692,7 @@
     dest.putShort((short) 0); // unused
   }
 
-  private void writeCallSite(DexCallSite callSite) throws ApiLevelException {
+  private void writeCallSite(DexCallSite callSite) {
     checkThatInvokeCustomIsAllowed();
     assert dest.isAligned(4);
     dest.putInt(mixedSectionOffsets.getOffsetFor(callSite.getEncodedArray()));
@@ -1363,13 +1342,10 @@
     }
   }
 
-  private void checkThatInvokeCustomIsAllowed() throws ApiLevelException {
+  private void checkThatInvokeCustomIsAllowed() {
     if (!options.canUseInvokeCustom()) {
-      throw new ApiLevelException(
-          Constants.ANDROID_O_API,
-          "Android O",
-          "Invoke-customs",
-          null /* sourceString */);
+      throw new CompilationError("Invoke-custom is unsupported before Android O (--min-api "
+          + Constants.ANDROID_O_API + ")");
     }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 1e5c073..d0032cd 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -505,12 +505,12 @@
     return runD8(D8Command.builder(app).build(), optionsConsumer);
   }
 
-  public static AndroidApp runD8(D8Command command) throws IOException, CompilationException {
+  public static AndroidApp runD8(D8Command command) throws IOException {
     return runD8(command, null);
   }
 
   public static AndroidApp runD8(D8Command command, Consumer<InternalOptions> optionsConsumer)
-      throws IOException, CompilationException {
+      throws IOException {
     InternalOptions options = command.getInternalOptions();
     if (optionsConsumer != null) {
       optionsConsumer.accept(options);
diff --git a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
index 46f2fd3..4b2ee49 100644
--- a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
@@ -49,7 +49,7 @@
   }
 
   public AndroidApp runAndCheckVerification(D8Command command, String referenceApk)
-      throws IOException, ExecutionException, CompilationException {
+      throws IOException, ExecutionException {
     return checkVerification(ToolHelper.runD8(command), referenceApk);
   }