Change the API for assertion configuration

  * The AssertionConfiguration.Builder only builds one item
  * Split the transformation and scope on the the builder API
  * For multiple configuration items addAssertionsConfiguration
    has to be called multiple times

Bug: 139898386
Change-Id: Ife488d59b856e86ea06240cbd9e13b4507f0bc73
diff --git a/src/main/java/com/android/tools/r8/AssertionsConfiguration.java b/src/main/java/com/android/tools/r8/AssertionsConfiguration.java
index 15acd6f..7199b77 100644
--- a/src/main/java/com/android/tools/r8/AssertionsConfiguration.java
+++ b/src/main/java/com/android/tools/r8/AssertionsConfiguration.java
@@ -4,8 +4,7 @@
 
 package com.android.tools.r8;
 
-import java.util.ArrayList;
-import java.util.List;
+import com.android.tools.r8.utils.Reporter;
 
 @Keep
 public class AssertionsConfiguration {
@@ -24,55 +23,37 @@
     PASSTHROUGH
   }
 
-  public enum ConfigurationType {
+  public enum AssertionTransformationScope {
     ALL,
     PACKAGE,
     CLASS
   }
 
-  public static class ConfigurationEntry {
-    private final AssertionTransformation transformation;
-    private final ConfigurationType type;
-    private final String value;
+  private final AssertionTransformation transformation;
+  private final AssertionTransformationScope scope;
+  private final String value;
 
-    private ConfigurationEntry(
-        AssertionTransformation transformation, ConfigurationType type, String value) {
-      assert value != null || type == ConfigurationType.ALL;
-      this.transformation = transformation;
-      this.type = type;
-      this.value = value;
-    }
-
-    public AssertionTransformation getTransformation() {
-      return transformation;
-    }
-
-    public ConfigurationType getType() {
-      return type;
-    }
-
-    public String getValue() {
-      return value;
-    }
+  AssertionsConfiguration(
+      AssertionTransformation transformation, AssertionTransformationScope scope, String value) {
+    this.transformation = transformation;
+    this.scope = scope;
+    this.value = value;
   }
 
-  // Methods which need to be public.
-  public static class InternalAssertionConfiguration {
-
-    public static List<ConfigurationEntry> getConfiguration(AssertionsConfiguration configuration) {
-      return configuration.entries;
-    }
+  public AssertionTransformation getTransformation() {
+    return transformation;
   }
 
-  private final List<ConfigurationEntry> entries;
-
-  private AssertionsConfiguration(List<ConfigurationEntry> entries) {
-    this.entries = entries;
+  public AssertionTransformationScope getScope() {
+    return scope;
   }
 
-  static AssertionsConfiguration.Builder builder(AssertionsConfiguration previous) {
-    return new AssertionsConfiguration.Builder(
-        previous != null ? previous.entries : new ArrayList<>());
+  public String getValue() {
+    return value;
+  }
+
+  static AssertionsConfiguration.Builder builder(Reporter reporter) {
+    return new AssertionsConfiguration.Builder(reporter);
   }
 
   /**
@@ -83,33 +64,19 @@
    */
   @Keep
   public static class Builder {
-    private final List<ConfigurationEntry> entries;
+    Reporter reporter;
+    private AssertionTransformation transformation;
+    private AssertionTransformationScope scope;
+    private String value;
 
-    private Builder(List<ConfigurationEntry> previousEntries) {
-      assert previousEntries != null;
-      this.entries = previousEntries;
-    }
-
-    private void addEntry(
-        AssertionTransformation transformation, ConfigurationType type, String value) {
-      entries.add(new ConfigurationEntry(transformation, type, value));
+    private Builder(Reporter reporter) {
+      this.reporter = reporter;
     }
 
     /** Set how to handle javac generated assertion code. */
     public AssertionsConfiguration.Builder setTransformation(
         AssertionTransformation transformation) {
-      addEntry(transformation, ConfigurationType.ALL, null);
-      return this;
-    }
-
-    AssertionsConfiguration.Builder setDefault(AssertionTransformation transformation) {
-      // Add the default by inserting a transform all entry at the beginning of the list, if there
-      // isn't already one.
-      ConfigurationEntry defaultEntry =
-          new ConfigurationEntry(transformation, ConfigurationType.ALL, null);
-      if (entries.size() == 0 || entries.get(0).type != ConfigurationType.ALL) {
-        entries.listIterator().add(defaultEntry);
-      }
+      this.transformation = transformation;
       return this;
     }
 
@@ -117,7 +84,7 @@
      * Unconditionally enable javac generated assertion code in all packages and classes. This
      * corresponds to passing <code>-enableassertions</code> or <code>-ea</code> to the java CLI.
      */
-    public AssertionsConfiguration.Builder enable() {
+    public AssertionsConfiguration.Builder setEnable() {
       setTransformation(AssertionTransformation.ENABLE);
       return this;
     }
@@ -126,86 +93,145 @@
      * Disable the javac generated assertion code in all packages and classes. This corresponds to
      * passing <code>-disableassertions</code> or <code>-da</code> to the java CLI.
      */
-    public AssertionsConfiguration.Builder disable() {
+    public AssertionsConfiguration.Builder setDisable() {
       setTransformation(AssertionTransformation.DISABLE);
       return this;
     }
 
     /** Passthrough of the javac generated assertion code in all packages and classes. */
-    public AssertionsConfiguration.Builder passthrough() {
+    public AssertionsConfiguration.Builder setPassthrough() {
       setTransformation(AssertionTransformation.PASSTHROUGH);
       return this;
     }
 
-    /** Set how to handle javac generated assertion code in package and all subpackages. */
-    public AssertionsConfiguration.Builder setTransformationForPackage(
-        String packageName, AssertionTransformation transformation) {
-      addEntry(transformation, ConfigurationType.PACKAGE, packageName);
+    public AssertionsConfiguration.Builder setScopeAll() {
+      this.scope = AssertionTransformationScope.ALL;
+      this.value = null;
       return this;
     }
 
     /**
-     * Unconditionally enable javac generated assertion code in package <code>packageName</code> and
-     * all subpackages. This corresponds to passing <code>-enableassertions:packageName...</code> or
-     * <code>-ea:packageName...</code> to the java CLI.
+     * Apply the specified transformation in package <code>packageName</code> and all subpackages.
+     * If <code>packageName</code> is the empty string, this specifies that the transformation is
+     * applied ion the unnamed package.
      *
-     * <p>If <code>packageName</code> is the empty string, assertions are enabled in the unnamed
-     * package, which corresponds to passing <code>-enableassertions:...</code> or <code>-ea:...
-     * </code> to the java CLI.
-     */
-    public AssertionsConfiguration.Builder enableForPackage(String packageName) {
-      return setTransformationForPackage(packageName, AssertionTransformation.ENABLE);
-    }
-
-    /**
-     * Disable the javac generated assertion code in package <code>packageName</code> and all
-     * subpackages. This corresponds to passing <code>-disableassertions:packageName...</code> or
-     * <code>-da:packageName...</code> to the java CLI.
+     * <p>If the transformation is 'enable' this corresponds to passing <code>
+     * -enableassertions:packageName...</code> or <code>-ea:packageName...</code> to the java CLI.
      *
-     * <p>If <code>packageName</code> is the empty string assertions are disabled in the unnamed
-     * package, which corresponds to passing <code>-disableassertions:...</code> or <code>-da:...
-     * </code> to the java CLI.
+     * <p>If the transformation is 'disable' this corresponds to passing <code>
+     * -disableassertions:packageName...</code> or <code>-da:packageName...</code> to the java CLI.
      */
-    public AssertionsConfiguration.Builder disableForPackage(String packageName) {
-      return setTransformationForPackage(packageName, AssertionTransformation.DISABLE);
-    }
-
-    public AssertionsConfiguration.Builder passthroughForPackage(String packageName) {
-      return setTransformationForPackage(packageName, AssertionTransformation.PASSTHROUGH);
-    }
-
-    /** Set how to handle javac generated assertion code in class. */
-    public AssertionsConfiguration.Builder setTransformationForClass(
-        String className, AssertionTransformation transformation) {
-      addEntry(transformation, ConfigurationType.CLASS, className);
+    public AssertionsConfiguration.Builder setScopePackage(String packageName) {
+      this.scope = AssertionTransformationScope.PACKAGE;
+      this.value = packageName;
       return this;
     }
 
     /**
-     * Unconditionally enable javac generated assertion in class <code>className</code>. This
-     * corresponds to passing <code> -enableassertions:className</code> or <code>-ea:className
-     * </code> to the java CLI.
+     * Apply the specified transformation in class <code>className</code>.
+     *
+     * <p>If the transformation is 'enable' this corresponds to passing <code>
+     * -enableassertions:className</code> or <code>-ea:className...</code> to the java CLI.
+     *
+     * <p>If the transformation is 'disable' this corresponds to passing <code>
+     * -disableassertions:className</code> or <code>-da:className</code> to the java CLI.
      */
-    public AssertionsConfiguration.Builder enableForClass(String className) {
-      return setTransformationForClass(className, AssertionTransformation.ENABLE);
-    }
-
-    /**
-     * Disable the javac generated assertion code in class <code>className</code>. This corresponds
-     * to passing <code> -disableassertions:className</code> or <code>-da:className</code> to the
-     * java CLI.
-     */
-    public AssertionsConfiguration.Builder disableForClass(String className) {
-      return setTransformationForClass(className, AssertionTransformation.DISABLE);
-    }
-
-    public AssertionsConfiguration.Builder passthroughForClass(String className) {
-      return setTransformationForClass(className, AssertionTransformation.PASSTHROUGH);
+    public AssertionsConfiguration.Builder setScopeClass(String className) {
+      this.scope = AssertionTransformationScope.CLASS;
+      this.value = className;
+      return this;
     }
 
     /** Build and return the {@link AssertionsConfiguration}. */
     public AssertionsConfiguration build() {
-      return new AssertionsConfiguration(entries);
+      if (transformation == null) {
+        reporter.error("No transformation specified for building AccertionConfiguration");
+      }
+      if (scope == null) {
+        reporter.error("No scope specified for building AccertionConfiguration");
+      }
+      if (scope == AssertionTransformationScope.PACKAGE && value == null) {
+        reporter.error("No package name specified for building AccertionConfiguration");
+      }
+      if (scope == AssertionTransformationScope.CLASS && value == null) {
+        reporter.error("No class name specified for building AccertionConfiguration");
+      }
+      return new AssertionsConfiguration(transformation, scope, value);
+    }
+
+    /**
+     * Static helper to build an <code>AssertionConfiguration</code> which unconditionally enables
+     * javac generated assertion code in all packages and classes. To be used like this:
+     *
+     * <pre>
+     *   D8Command command = D8Command.builder()
+     *     .addAssertionsConfiguration(AssertionsConfiguration.Builder::enableAllAssertions)
+     *     ...
+     *     .build();
+     * </pre>
+     *
+     * which is a shorthand for:
+     *
+     * <pre>
+     *   D8Command command = D8Command.builder()
+     *     .addAssertionsConfiguration(builder -> builder.setEnabled().setScopeAll().build())
+     *     ...
+     *     .build();
+     * </pre>
+     */
+    public static AssertionsConfiguration enableAllAssertions(
+        AssertionsConfiguration.Builder builder) {
+      return builder.setEnable().setScopeAll().build();
+    }
+
+    /**
+     * Static helper to build an <code>AssertionConfiguration</code> which unconditionally disables
+     * javac generated assertion code in all packages and classes. To be used like this:
+     *
+     * <pre>
+     *   D8Command command = D8Command.builder()
+     *     .addAssertionsConfiguration(AssertionsConfiguration.Builder::disableAllAssertions)
+     *     ...
+     *     .build();
+     * </pre>
+     *
+     * which is a shorthand for:
+     *
+     * <pre>
+     *   D8Command command = D8Command.builder()
+     *     .addAssertionsConfiguration(builder -> builder.setDisabled().setScopeAll().build())
+     *     ...
+     *     .build();
+     * </pre>
+     */
+    public static AssertionsConfiguration disableAllAssertions(
+        AssertionsConfiguration.Builder builder) {
+      return builder.setDisable().setScopeAll().build();
+    }
+
+    /**
+     * Static helper to build an <code>AssertionConfiguration</code> which will passthrough javac
+     * generated assertion code in all packages and classes. To be used like this:
+     *
+     * <pre>
+     *   D8Command command = D8Command.builder()
+     *     .addAssertionsConfiguration(AssertionsConfiguration.Builder::passthroughAllAssertions)
+     *     ...
+     *     .build();
+     * </pre>
+     *
+     * which is a shorthand for:
+     *
+     * <pre>
+     *   D8Command command = D8Command.builder()
+     *     .addAssertionsConfiguration(builder -> builder.setPassthrough().setScopeAll().build())
+     *     ...
+     *     .build();
+     * </pre>
+     */
+    public static AssertionsConfiguration passthroughAllAssertions(
+        AssertionsConfiguration.Builder builder) {
+      return builder.setPassthrough().setScopeAll().build();
     }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
index 2b94a54..fd2ecb3 100644
--- a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8;
 
-import com.android.tools.r8.AssertionsConfiguration.AssertionTransformation;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -40,7 +39,7 @@
   private final boolean includeClassesChecksum;
   private final boolean optimizeMultidexForLinearAlloc;
   private final BiPredicate<String, Long> dexClassChecksumFilter;
-  private final AssertionsConfiguration assertionsConfiguration;
+  private final List<AssertionsConfiguration> assertionsConfiguration;
 
   BaseCompilerCommand(boolean printHelp, boolean printVersion) {
     super(printHelp, printVersion);
@@ -53,7 +52,7 @@
     includeClassesChecksum = false;
     optimizeMultidexForLinearAlloc = false;
     dexClassChecksumFilter = (name, checksum) -> true;
-    assertionsConfiguration = null;
+    assertionsConfiguration = new ArrayList<>();
   }
 
   BaseCompilerCommand(
@@ -67,7 +66,7 @@
       boolean optimizeMultidexForLinearAlloc,
       boolean includeClassesChecksum,
       BiPredicate<String, Long> dexClassChecksumFilter,
-      AssertionsConfiguration assertionsConfiguration) {
+      List<AssertionsConfiguration> assertionsConfiguration) {
     super(app);
     assert minApiLevel > 0;
     assert mode != null;
@@ -135,11 +134,8 @@
     return optimizeMultidexForLinearAlloc;
   }
 
-  AssertionsConfiguration getAssertionsConfiguration(
-      AssertionTransformation defaultTransformation) {
-    return AssertionsConfiguration.builder(assertionsConfiguration)
-        .setDefault(defaultTransformation)
-        .build();
+  public List<AssertionsConfiguration> getAssertionsConfiguration() {
+    return assertionsConfiguration;
   }
 
   Reporter getReporter() {
@@ -171,7 +167,7 @@
     private boolean lookupLibraryBeforeProgram = true;
     private boolean optimizeMultidexForLinearAlloc = false;
     private BiPredicate<String, Long> dexClassChecksumFilter = (name, checksum) -> true;
-    private AssertionsConfiguration assertionsConfiguration;
+    private List<AssertionsConfiguration> assertionsConfiguration = new ArrayList<>();
 
     abstract CompilationMode defaultCompilationMode();
 
@@ -490,20 +486,19 @@
       return includeClassesChecksum;
     }
 
+    List<AssertionsConfiguration> getAssertionsConfiguration() {
+      return assertionsConfiguration;
+    }
+
     /** Configure compile time assertion enabling through a {@link AssertionsConfiguration}. */
     public B addAssertionsConfiguration(
         Function<AssertionsConfiguration.Builder, AssertionsConfiguration>
             assertionsConfigurationGenerator) {
-      assertionsConfiguration =
-          assertionsConfigurationGenerator.apply(
-              AssertionsConfiguration.builder(assertionsConfiguration));
+      assertionsConfiguration.add(
+          assertionsConfigurationGenerator.apply(AssertionsConfiguration.builder(getReporter())));
       return self();
     }
 
-    public AssertionsConfiguration getAssertionsConfiguration() {
-      return assertionsConfiguration;
-    }
-
     @Override
     void validate() {
       Reporter reporter = getReporter();
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index d3ec378..cf5e6c8 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -159,7 +159,7 @@
 
       final CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
 
-      if (!AssertionsRewriter.isPassthroughAll(options.assertionsConfiguration)) {
+      if (AssertionsRewriter.isEnabled(options)) {
         // Run analysis to mark all <clinit> methods having the javac generated assertion
         // enabling code.
         ClassInitializerAssertionEnablingAnalysis analysis =
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 2401aa5..b76e6a7 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -10,11 +10,13 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AssertionConfigurationWithDefault;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
 import java.nio.file.Path;
 import java.util.Collection;
+import java.util.List;
 import java.util.function.BiPredicate;
 
 /**
@@ -287,7 +289,7 @@
       DesugarGraphConsumer desugarGraphConsumer,
       StringConsumer desugaredLibraryKeepRuleConsumer,
       DesugaredLibraryConfiguration libraryConfiguration,
-      AssertionsConfiguration assertionsConfiguration,
+      List<AssertionsConfiguration> assertionsConfiguration,
       DexItemFactory factory) {
     super(
         inputApp,
@@ -361,10 +363,11 @@
     internal.desugaredLibraryConfiguration = libraryConfiguration;
     internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
 
+    // Default is to remove all javac generated assertion code when generating dex.
     assert internal.assertionsConfiguration == null;
-    // Default, when no configuration is provided, is to remove all javac generated assertion
-    // code when generating dex.
-    internal.assertionsConfiguration = getAssertionsConfiguration(AssertionTransformation.DISABLE);
+    internal.assertionsConfiguration =
+        new AssertionConfigurationWithDefault(
+            AssertionTransformation.DISABLE, getAssertionsConfiguration());
 
     return internal;
   }
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 4a587aa..1ddd338 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -10,10 +10,12 @@
 import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AssertionConfigurationWithDefault;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Pair;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
+import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -92,7 +94,7 @@
         false,
         false,
         (name, checksum) -> true,
-        AssertionsConfiguration.builder(null).build());
+        ImmutableList.of());
     this.d8Command = d8Command;
     this.r8Command = r8Command;
     this.libraryConfiguration = libraryConfiguration;
@@ -171,10 +173,11 @@
     // TODO(134732760): This is still work in progress.
     internal.desugaredLibraryConfiguration = libraryConfiguration;
 
+    // Default is to remove all javac generated assertion code when generating dex.
     assert internal.assertionsConfiguration == null;
-    // Default, when no configuration is provided, is to remove all javac generated assertion
-    // code when generating dex.
-    internal.assertionsConfiguration = getAssertionsConfiguration(AssertionTransformation.DISABLE);
+    internal.assertionsConfiguration =
+        new AssertionConfigurationWithDefault(
+            AssertionTransformation.DISABLE, getAssertionsConfiguration());
 
     return internal;
   }
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 8c26650..dbe1572 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -807,7 +807,7 @@
     if (appView.options().enableInitializedClassesInInstanceMethodsAnalysis) {
       enqueuer.registerAnalysis(new InitializedClassesInInstanceMethodsAnalysis(appView));
     }
-    if (!AssertionsRewriter.isPassthroughAll(appView.options().assertionsConfiguration)) {
+    if (AssertionsRewriter.isEnabled(appView.options())) {
       enqueuer.registerAnalysis(
           new ClassInitializerAssertionEnablingAnalysis(
               appView.dexItemFactory(), OptimizationFeedbackSimple.getInstance()));
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 265fa38..187e095 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -21,6 +21,7 @@
 import com.android.tools.r8.shaking.ProguardConfigurationSourceStrings;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AssertionConfigurationWithDefault;
 import com.android.tools.r8.utils.ExceptionDiagnostic;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
@@ -720,7 +721,7 @@
       StringConsumer desugaredLibraryKeepRuleConsumer,
       DesugaredLibraryConfiguration libraryConfiguration,
       FeatureSplitConfiguration featureSplitConfiguration,
-      AssertionsConfiguration assertionsConfiguration) {
+      List<AssertionsConfiguration> assertionsConfiguration) {
     super(
         inputApp,
         mode,
@@ -870,14 +871,14 @@
 
     internal.syntheticProguardRulesConsumer = syntheticProguardRulesConsumer;
 
+    // Default is to remove all javac generated assertion code when generating dex.
     assert internal.assertionsConfiguration == null;
-    // Default, when no configuration is provided, is to remove all javac generated assertion
-    // code when generating dex and leave it when generating class files.
     internal.assertionsConfiguration =
-        getAssertionsConfiguration(
-            internal.isGeneratingClassFiles()
+        new AssertionConfigurationWithDefault(
+            getProgramConsumer() instanceof ClassFileConsumer
                 ? AssertionTransformation.PASSTHROUGH
-                : AssertionTransformation.DISABLE);
+                : AssertionTransformation.DISABLE,
+            getAssertionsConfiguration());
 
     // When generating class files the build is "intermediate" and we cannot pollute the namespace
     // with the a hard-coded outline class. Doing so would prohibit subsequent merging of two
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java
index 2292b0a..a344095 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java
@@ -6,9 +6,6 @@
 
 import com.android.tools.r8.AssertionsConfiguration;
 import com.android.tools.r8.AssertionsConfiguration.AssertionTransformation;
-import com.android.tools.r8.AssertionsConfiguration.ConfigurationEntry;
-import com.android.tools.r8.AssertionsConfiguration.ConfigurationType;
-import com.android.tools.r8.AssertionsConfiguration.InternalAssertionConfiguration;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
@@ -21,7 +18,9 @@
 import com.android.tools.r8.ir.code.InvokeMethod;
 import com.android.tools.r8.ir.code.StaticGet;
 import com.android.tools.r8.ir.code.StaticPut;
+import com.android.tools.r8.utils.AssertionConfigurationWithDefault;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.ThrowingCharIterator;
 import java.io.UTFDataFormatException;
 import java.util.List;
@@ -31,21 +30,21 @@
 
   private static class ConfigurationEntryWithDexString {
 
-    private ConfigurationEntry entry;
+    private AssertionsConfiguration entry;
     private final DexString value;
 
     private ConfigurationEntryWithDexString(
-        ConfigurationEntry entry, DexItemFactory dexItemFactory) {
-      this.entry = entry;
-      switch (entry.getType()) {
+        AssertionsConfiguration configuration, DexItemFactory dexItemFactory) {
+      this.entry = configuration;
+      switch (configuration.getScope()) {
         case PACKAGE:
-          if (entry.getValue().length() == 0) {
+          if (configuration.getValue().length() == 0) {
             value = dexItemFactory.createString("");
           } else {
             value =
                 dexItemFactory.createString(
                     "L"
-                        + entry
+                        + configuration
                             .getValue()
                             .replace(
                                 DescriptorUtils.JAVA_PACKAGE_SEPARATOR,
@@ -57,7 +56,7 @@
           value =
               dexItemFactory.createString(
                   "L"
-                      + entry
+                      + configuration
                           .getValue()
                           .replace(
                               DescriptorUtils.JAVA_PACKAGE_SEPARATOR,
@@ -75,39 +74,38 @@
 
   private final AppView<?> appView;
   private final DexItemFactory dexItemFactory;
+  private final AssertionTransformation defaultTransformation;
   private final List<ConfigurationEntryWithDexString> configuration;
   private final boolean enabled;
 
   public AssertionsRewriter(AppView<?> appView) {
     this.appView = appView;
     this.dexItemFactory = appView.dexItemFactory();
-    if (appView.options().assertionsConfiguration == null) {
-      this.configuration = null;
-      this.enabled = false;
-    } else {
-      List<ConfigurationEntry> configuration =
-          InternalAssertionConfiguration
-              .getConfiguration(appView.options().assertionsConfiguration);
-      this.configuration =
-          configuration.stream()
-              .map(entry -> new ConfigurationEntryWithDexString(entry, appView.dexItemFactory()))
-              .collect(Collectors.toList());
-      this.enabled = !isPassthroughAll(appView.options().assertionsConfiguration);
+    this.enabled = isEnabled(appView.options());
+    if (!enabled) {
+      defaultTransformation = null;
+      configuration = null;
+      return;
     }
+    // Convert the assertion transformation to the representation used for this rewriter.
+    this.defaultTransformation = appView.options().assertionsConfiguration.defautlTransformation;
+    this.configuration =
+        appView.options().assertionsConfiguration.assertionsConfigurations.stream()
+            .map(entry -> new ConfigurationEntryWithDexString(entry, appView.dexItemFactory()))
+            .collect(Collectors.toList());
   }
 
-  public static boolean isPassthroughAll(AssertionsConfiguration assertionsConfiguration) {
-    List<ConfigurationEntry> configuration =
-        InternalAssertionConfiguration.getConfiguration(assertionsConfiguration);
-    return configuration.size() == 1
-        && configuration.get(0).getTransformation() == AssertionTransformation.PASSTHROUGH
-        && configuration.get(0).getType() == ConfigurationType.ALL;
+  // Static method used by other analyses to see if additional analysis is required to support
+  // this rewriting.
+  public static boolean isEnabled(InternalOptions options) {
+    AssertionConfigurationWithDefault configuration = options.assertionsConfiguration;
+    return configuration != null && !configuration.isPassthroughAll();
   }
 
   private AssertionTransformation getTransformationForMethod(DexEncodedMethod method) {
-    AssertionTransformation transformation = null;
+    AssertionTransformation transformation = defaultTransformation;
     for (ConfigurationEntryWithDexString entry : configuration) {
-      switch (entry.entry.getType()) {
+      switch (entry.entry.getScope()) {
         case ALL:
           transformation = entry.entry.getTransformation();
           break;
@@ -132,7 +130,7 @@
           throw new Unreachable();
       }
     }
-    assert transformation != null; // Default transformation are always added.
+    assert transformation != null;
     return transformation;
   }
 
diff --git a/src/main/java/com/android/tools/r8/utils/AssertionConfigurationWithDefault.java b/src/main/java/com/android/tools/r8/utils/AssertionConfigurationWithDefault.java
new file mode 100644
index 0000000..7dc7b33
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/AssertionConfigurationWithDefault.java
@@ -0,0 +1,34 @@
+// 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.utils;
+
+import com.android.tools.r8.AssertionsConfiguration;
+import com.android.tools.r8.AssertionsConfiguration.AssertionTransformation;
+import com.android.tools.r8.AssertionsConfiguration.AssertionTransformationScope;
+import java.util.List;
+
+public class AssertionConfigurationWithDefault {
+
+  public final AssertionTransformation defautlTransformation;
+  public final List<AssertionsConfiguration> assertionsConfigurations;
+
+  public AssertionConfigurationWithDefault(
+      AssertionTransformation defautlTransformation,
+      List<AssertionsConfiguration> assertionsConfigurations) {
+    this.defautlTransformation = defautlTransformation;
+    assert assertionsConfigurations != null;
+    this.assertionsConfigurations = assertionsConfigurations;
+  }
+
+  public boolean isPassthroughAll() {
+    if (assertionsConfigurations.size() == 0) {
+      return defautlTransformation == AssertionTransformation.PASSTHROUGH;
+    }
+    return assertionsConfigurations.size() == 1
+        && assertionsConfigurations.get(0).getScope() == AssertionTransformationScope.ALL
+        && assertionsConfigurations.get(0).getTransformation()
+            == AssertionTransformation.PASSTHROUGH;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index cf2844f..114715a 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -5,7 +5,6 @@
 
 import static com.google.common.base.Predicates.not;
 
-import com.android.tools.r8.AssertionsConfiguration;
 import com.android.tools.r8.ClassFileConsumer;
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.DataResourceConsumer;
@@ -437,7 +436,7 @@
   public boolean ignoreMissingClasses = false;
   // EXPERIMENTAL flag to get behaviour as close to Proguard as possible.
   public boolean forceProguardCompatibility = false;
-  public AssertionsConfiguration assertionsConfiguration = null;
+  public AssertionConfigurationWithDefault assertionsConfiguration = null;
   public boolean configurationDebugging = false;
 
   // Don't convert Code objects to IRCode.
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionsConfigurationTest.java b/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionsConfigurationTest.java
index ce9f1c5..2d79d48 100644
--- a/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionsConfigurationTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionsConfigurationTest.java
@@ -10,9 +10,12 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.AssertionsConfiguration;
+import com.android.tools.r8.D8TestBuilder;
+import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ThrowableConsumer;
 import com.android.tools.r8.rewrite.assertions.testclasses.TestClassForInnerClass;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.ThrowingConsumer;
@@ -21,7 +24,6 @@
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.google.common.collect.ImmutableList;
 import java.util.List;
-import java.util.function.Function;
 import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -65,15 +67,14 @@
   }
 
   private void runD8Test(
-      Function<AssertionsConfiguration.Builder, AssertionsConfiguration>
-          assertionsConfigurationBuilder,
+      ThrowableConsumer<D8TestBuilder> builderConsumer,
       ThrowingConsumer<CodeInspector, RuntimeException> inspector,
       List<String> outputLines)
       throws Exception {
     testForD8()
         .addProgramClasses(testClasses)
         .setMinApi(parameters.getApiLevel())
-        .addAssertionsConfiguration(assertionsConfigurationBuilder)
+        .apply(builderConsumer)
         .compile()
         .inspect(inspector)
         .run(parameters.getRuntime(), TestClass.class)
@@ -81,17 +82,15 @@
   }
 
   public void runR8Test(
-      Function<AssertionsConfiguration.Builder, AssertionsConfiguration>
-          assertionsConfigurationBuilder,
+      ThrowableConsumer<R8FullTestBuilder> builderConsumer,
       ThrowingConsumer<CodeInspector, RuntimeException> inspector,
       List<String> outputLines)
       throws Exception {
-    runR8Test(assertionsConfigurationBuilder, inspector, outputLines, false);
+    runR8Test(builderConsumer, inspector, outputLines, false);
   }
 
   public void runR8Test(
-      Function<AssertionsConfiguration.Builder, AssertionsConfiguration>
-          assertionsConfigurationBuilder,
+      ThrowableConsumer<R8FullTestBuilder> builderConsumer,
       ThrowingConsumer<CodeInspector, RuntimeException> inspector,
       List<String> outputLines,
       boolean enableJvmAssertions)
@@ -102,7 +101,7 @@
         .addKeepMainRule(TestClass.class)
         .addKeepClassAndMembersRules(class1, class2, subpackageClass1, subpackageClass2)
         .setMinApi(parameters.getApiLevel())
-        .addAssertionsConfiguration(assertionsConfigurationBuilder)
+        .apply(builderConsumer)
         .compile()
         .inspect(inspector)
         .enableRuntimeAssertions(enableJvmAssertions)
@@ -110,18 +109,6 @@
         .assertSuccessWithOutput(StringUtils.lines(outputLines));
   }
 
-  private AssertionsConfiguration enableAllAssertions(AssertionsConfiguration.Builder builder) {
-    return builder.enable().build();
-  }
-
-  private AssertionsConfiguration disableAllAssertions(AssertionsConfiguration.Builder builder) {
-    return builder.disable().build();
-  }
-
-  private AssertionsConfiguration leaveAllAssertions(AssertionsConfiguration.Builder builder) {
-    return builder.passthrough().build();
-  }
-
   private List<String> allAssertionsExpectedLines() {
     return ImmutableList.of(
         "AssertionError in testclasses.Class1",
@@ -218,29 +205,53 @@
     Assume.assumeTrue(parameters.isDexRuntime());
     // Leaving assertions in or disabling them on Dalvik/Art means no assertions.
     runD8Test(
-        this::leaveAllAssertions, this::checkAssertionCodeLeft, noAllAssertionsExpectedLines());
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::passthroughAllAssertions),
+        this::checkAssertionCodeLeft,
+        noAllAssertionsExpectedLines());
     runR8Test(
-        this::leaveAllAssertions, this::checkAssertionCodeLeft, noAllAssertionsExpectedLines());
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::passthroughAllAssertions),
+        this::checkAssertionCodeLeft,
+        noAllAssertionsExpectedLines());
     runD8Test(
-        this::disableAllAssertions,
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::disableAllAssertions),
         this::checkAssertionCodeRemoved,
         noAllAssertionsExpectedLines());
     runR8Test(
-        this::disableAllAssertions,
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::disableAllAssertions),
         this::checkAssertionCodeRemoved,
         noAllAssertionsExpectedLines());
     // Compile time enabling assertions gives assertions on Dalvik/Art.
     runD8Test(
-        this::enableAllAssertions, this::checkAssertionCodeEnabled, allAssertionsExpectedLines());
-    runR8Test(
-        this::enableAllAssertions, this::checkAssertionCodeEnabled, allAssertionsExpectedLines());
-    // Enabling for the package should enable all.
-    runD8Test(
-        builder -> builder.enableForPackage(packageName).build(),
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::enableAllAssertions),
         this::checkAssertionCodeEnabled,
         allAssertionsExpectedLines());
     runR8Test(
-        builder -> builder.enableForPackage(packageName).build(),
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::enableAllAssertions),
+        this::checkAssertionCodeEnabled,
+        allAssertionsExpectedLines());
+    // Enabling for the package should enable all.
+    runD8Test(
+        builder ->
+            builder.addAssertionsConfiguration(
+                b -> b.setEnable().setScopePackage(packageName).build()),
+        this::checkAssertionCodeEnabled,
+        allAssertionsExpectedLines());
+    runR8Test(
+        builder ->
+            builder.addAssertionsConfiguration(
+                b -> b.setEnable().setScopePackage(packageName).build()),
         this::checkAssertionCodeEnabled,
         allAssertionsExpectedLines());
   }
@@ -250,23 +261,42 @@
     Assume.assumeTrue(parameters.isCfRuntime());
     // Leaving assertion code means assertions are controlled by the -ea flag.
     runR8Test(
-        this::leaveAllAssertions, this::checkAssertionCodeLeft, noAllAssertionsExpectedLines());
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::passthroughAllAssertions),
+        this::checkAssertionCodeLeft,
+        noAllAssertionsExpectedLines());
     runR8Test(
-        this::leaveAllAssertions, this::checkAssertionCodeLeft, allAssertionsExpectedLines(), true);
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::passthroughAllAssertions),
+        this::checkAssertionCodeLeft,
+        allAssertionsExpectedLines(),
+        true);
     // Compile time enabling or disabling assertions means the -ea flag has no effect.
     runR8Test(
-        this::enableAllAssertions, this::checkAssertionCodeEnabled, allAssertionsExpectedLines());
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::enableAllAssertions),
+        this::checkAssertionCodeEnabled,
+        allAssertionsExpectedLines());
     runR8Test(
-        this::enableAllAssertions,
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::enableAllAssertions),
         this::checkAssertionCodeEnabled,
         allAssertionsExpectedLines(),
         true);
     runR8Test(
-        this::disableAllAssertions,
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::disableAllAssertions),
         this::checkAssertionCodeRemoved,
         noAllAssertionsExpectedLines());
     runR8Test(
-        this::disableAllAssertions,
+        builder ->
+            builder.addAssertionsConfiguration(
+                AssertionsConfiguration.Builder::disableAllAssertions),
         this::checkAssertionCodeRemoved,
         noAllAssertionsExpectedLines(),
         true);
@@ -276,7 +306,9 @@
   public void testEnableForPackageForDex() throws Exception {
     Assume.assumeTrue(parameters.isDexRuntime());
     runD8Test(
-        builder -> builder.enableForPackage(subPackageName).build(),
+        builder ->
+            builder.addAssertionsConfiguration(
+                b -> b.setEnable().setScopePackage(subPackageName).build()),
         inspector -> {
           checkAssertionCodeEnabled(inspector, subpackageClass1);
           checkAssertionCodeEnabled(inspector, subpackageClass2);
@@ -286,7 +318,9 @@
             "AssertionError in testclasses.subpackage.Class2",
             "DONE"));
     runR8Test(
-        builder -> builder.enableForPackage(subPackageName).build(),
+        builder ->
+            builder.addAssertionsConfiguration(
+                b -> b.setEnable().setScopePackage(subPackageName).build()),
         inspector -> {
           checkAssertionCodeEnabled(inspector, subpackageClass1);
           checkAssertionCodeEnabled(inspector, subpackageClass2);
@@ -303,12 +337,13 @@
     runD8Test(
         builder ->
             builder
-                .enableForClass(class1.getCanonicalName())
-                .enableForClass(subpackageClass2.getCanonicalName())
-                .build(),
+                .addAssertionsConfiguration(
+                    b -> b.setEnable().setScopeClass(class1.getCanonicalName()).build())
+                .addAssertionsConfiguration(
+                    b -> b.setEnable().setScopeClass(subpackageClass2.getCanonicalName()).build()),
         inspector -> {
-          // checkAssertionCodeEnabled(inspector, class1);
-          // checkAssertionCodeEnabled(inspector, subpackageClass2);
+          checkAssertionCodeEnabled(inspector, class1);
+          checkAssertionCodeEnabled(inspector, subpackageClass2);
         },
         ImmutableList.of(
             "AssertionError in testclasses.Class1",
@@ -317,9 +352,10 @@
     runR8Test(
         builder ->
             builder
-                .enableForClass(class1.getCanonicalName())
-                .enableForClass(subpackageClass2.getCanonicalName())
-                .build(),
+                .addAssertionsConfiguration(
+                    b -> b.setEnable().setScopeClass(class1.getCanonicalName()).build())
+                .addAssertionsConfiguration(
+                    b -> b.setEnable().setScopeClass(subpackageClass2.getCanonicalName()).build()),
         inspector -> {
           checkAssertionCodeEnabled(inspector, class1);
           checkAssertionCodeEnabled(inspector, subpackageClass2);
@@ -336,10 +372,11 @@
     runD8Test(
         builder ->
             builder
-                .enableForPackage(packageName)
-                .disableForClass(class2.getCanonicalName())
-                .disableForClass(subpackageClass1.getCanonicalName())
-                .build(),
+                .addAssertionsConfiguration(b -> b.setEnable().setScopePackage(packageName).build())
+                .addAssertionsConfiguration(
+                    b -> b.setDisable().setScopeClass(class2.getCanonicalName()).build())
+                .addAssertionsConfiguration(
+                    b -> b.setDisable().setScopeClass(subpackageClass1.getCanonicalName()).build()),
         inspector -> {
           checkAssertionCodeEnabled(inspector, class1);
           checkAssertionCodeRemoved(inspector, class2);
@@ -353,10 +390,11 @@
     runR8Test(
         builder ->
             builder
-                .enableForPackage(packageName)
-                .disableForClass(class2.getCanonicalName())
-                .disableForClass(subpackageClass1.getCanonicalName())
-                .build(),
+                .addAssertionsConfiguration(b -> b.setEnable().setScopePackage(packageName).build())
+                .addAssertionsConfiguration(
+                    b -> b.setDisable().setScopeClass(class2.getCanonicalName()).build())
+                .addAssertionsConfiguration(
+                    b -> b.setDisable().setScopeClass(subpackageClass1.getCanonicalName()).build()),
         inspector -> {
           checkAssertionCodeEnabled(inspector, class1);
           checkAssertionCodeRemoved(inspector, class2);
@@ -379,7 +417,7 @@
             classInUnnamedPackage("Class1"),
             classInUnnamedPackage("Class2"))
         .setMinApi(parameters.getApiLevel())
-        .addAssertionsConfiguration(builder -> builder.enableForPackage("").build())
+        .addAssertionsConfiguration(builder -> builder.setEnable().setScopePackage("").build())
         .compile()
         .inspect(
             inspector -> {
@@ -427,7 +465,10 @@
         .setMinApi(parameters.getApiLevel())
         .addAssertionsConfiguration(
             builder ->
-                builder.enableForClass(TestClassForInnerClass.class.getCanonicalName()).build())
+                builder
+                    .setEnable()
+                    .setScopeClass(TestClassForInnerClass.class.getCanonicalName())
+                    .build())
         .compile()
         .inspect(
             inspector -> {
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java b/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java
index 27e53ba..bbcc8e2 100644
--- a/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java
@@ -199,7 +199,8 @@
         .debug()
         .noTreeShaking()
         .noMinification()
-        .addAssertionsConfiguration(builder -> builder.setTransformation(transformation).build())
+        .addAssertionsConfiguration(
+            builder -> builder.setTransformation(transformation).setScopeAll().build())
         .compile();
   }
 
@@ -337,7 +338,8 @@
         .addProgramClasses(ClassWithAssertions.class)
         .debug()
         .setMinApi(AndroidApiLevel.B)
-        .addAssertionsConfiguration(builder -> builder.setTransformation(transformation).build())
+        .addAssertionsConfiguration(
+            builder -> builder.setTransformation(transformation).setScopeAll().build())
         .compile();
   }
 
@@ -357,7 +359,8 @@
         .addProgramFiles(program)
         .debug()
         .setMinApi(AndroidApiLevel.B)
-        .addAssertionsConfiguration(builder -> builder.setTransformation(transformation).build())
+        .addAssertionsConfiguration(
+            builder -> builder.setTransformation(transformation).setScopeAll().build())
         .compile();
   }