Move getConfig into ProguardConfiguration.Builder

Change-Id: I68a884c1b1b69eadf2d285a00e5c7dda028d43b5
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 75cd44f..c994367 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -551,7 +551,7 @@
           getDesugaredLibraryConfiguration(factory, false);
 
       ImmutableList<ProguardConfigurationRule> mainDexKeepRules =
-          ProguardConfigurationParser.parse(mainDexRules, factory, getReporter());
+          ProguardConfigurationParser.parseMainDex(mainDexRules, factory, getReporter());
 
       if (!globalSyntheticsResourceProviders.isEmpty()) {
         addProgramResourceProvider(
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
index 1efa5bc..4e1e118 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
@@ -111,7 +111,7 @@
       }
 
       List<ProguardConfigurationRule> mainDexKeepRules =
-          ProguardConfigurationParser.parse(mainDexRules, factory, getReporter());
+          ProguardConfigurationParser.parseMainDex(mainDexRules, factory, getReporter());
 
       return new GenerateMainDexListCommand(
           factory,
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index f640e5c..49672a7 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -846,7 +846,7 @@
       long created = System.nanoTime();
       Reporter reporter = getReporter();
       List<ProguardConfigurationRule> mainDexKeepRules =
-          ProguardConfigurationParser.parse(mainDexRules, factory, reporter);
+          ProguardConfigurationParser.parseMainDex(mainDexRules, factory, reporter);
 
       DesugaredLibrarySpecification desugaredLibrarySpecification =
           getDesugaredLibraryConfiguration(factory, false);
@@ -917,7 +917,8 @@
     }
 
     private ProguardConfiguration makeConfiguration(DexItemFactory factory) {
-      ProguardConfigurationParserOptions parserOptions = parserOptionsBuilder.build();
+      ProguardConfigurationParserOptions parserOptions =
+          parserOptionsBuilder.setForceProguardCompatibility(forceProguardCompatibility).build();
       ProguardConfigurationParser parser =
           new ProguardConfigurationParser(
               factory, getReporter(), parserOptions, inputDependencyGraphConsumer);
diff --git a/src/main/java/com/android/tools/r8/ReadKeepFile.java b/src/main/java/com/android/tools/r8/ReadKeepFile.java
deleted file mode 100644
index c2ddab3..0000000
--- a/src/main/java/com/android/tools/r8/ReadKeepFile.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2016, 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;
-
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.shaking.ProguardConfigurationParser;
-import com.android.tools.r8.utils.Reporter;
-import com.android.tools.r8.utils.timing.Timing;
-import java.nio.file.Paths;
-
-/**
- * Benchmark for testing ability to and speed of parsing Proguard keep files.
- */
-public class ReadKeepFile {
-
-  private static final String DEFAULT_KEEP_FILE_NAME = "build/proguard.cfg";
-
-  final Timing timing = Timing.empty();
-
-  private void readProguardKeepFile(String fileName) {
-    System.out.println("  - reading " + fileName);
-    timing.begin("Reading " + fileName);
-    new ProguardConfigurationParser(new DexItemFactory(), new Reporter())
-        .parse(Paths.get(fileName));
-    timing.end();
-  }
-
-  public static void main(String[] args) {
-    new ReadKeepFile().run(args);
-  }
-
-  private void run(String[] args) {
-    System.out.println("ProguardKeepRuleParser benchmark.");
-    if (args.length == 0) {
-      readProguardKeepFile(DEFAULT_KEEP_FILE_NAME);
-    } else {
-      for (String name : args) {
-        readProguardKeepFile(name);
-      }
-    }
-    timing.report();
-  }
-}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index d23dd0e..33f0bd5 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -113,18 +113,23 @@
   private static final List<String> UNSUPPORTED_FLAG_OPTIONS =
       ImmutableList.of("skipnonpubliclibraryclasses");
 
-  public static ImmutableList<ProguardConfigurationRule> parse(
+  @Deprecated
+  public static ImmutableList<ProguardConfigurationRule> parseMainDex(
       List<ProguardConfigurationSource> sources, DexItemFactory factory, Reporter reporter) {
     if (sources.isEmpty()) {
       return ImmutableList.of();
     }
-    ProguardConfigurationParser parser = new ProguardConfigurationParser(factory, reporter);
+    ProguardConfiguration.Builder builder = ProguardConfiguration.builder(factory, reporter);
+    ProguardConfigurationParser parser =
+        new ProguardConfigurationParser(factory, reporter, builder);
     parser.parse(sources);
-    return ImmutableList.copyOf(parser.getConfig().getRules());
+    return ImmutableList.copyOf(builder.build().getRules());
   }
 
   public ProguardConfigurationParser(
-      DexItemFactory dexItemFactory, Reporter reporter) {
+      DexItemFactory dexItemFactory,
+      Reporter reporter,
+      ProguardConfiguration.Builder configurationBuilder) {
     this(
         dexItemFactory,
         reporter,
@@ -134,7 +139,9 @@
             .setEnableExperimentalConvertCheckNotNull(false)
             .setEnableExperimentalWhyAreYouNotInlining(false)
             .setEnableTestingOptions(false)
-            .build());
+            .build(),
+        null,
+        configurationBuilder);
   }
 
   public ProguardConfigurationParser(
@@ -191,34 +198,6 @@
     return configurationBuilder;
   }
 
-  private void validate() {
-    if (configurationBuilder.isKeepParameterNames() && configurationBuilder.isObfuscating()) {
-      // The flag -keepparameternames has only effect when minifying, so ignore it if we
-      // are not.
-      throw reporter.fatalError(new StringDiagnostic(
-          "-keepparameternames is not supported",
-          configurationBuilder.getKeepParameterNamesOptionOrigin(),
-          configurationBuilder.getKeepParameterNamesOptionPosition()));
-    }
-  }
-
-  /**
-   * Returns the Proguard configuration with default rules derived from empty rules added.
-   */
-  public ProguardConfiguration getConfig() {
-    validate();
-    return configurationBuilder.build();
-  }
-
-  /**
-   * Returns the Proguard configuration from exactly the rules parsed, without any
-   * defaults derived from empty rules.
-   */
-  public ProguardConfiguration getConfigRawForTesting() {
-    validate();
-    return configurationBuilder.buildRaw();
-  }
-
   public void parse(Path path) {
     parse(ImmutableList.of(new ProguardConfigurationSourceFile(path)));
   }
@@ -861,12 +840,12 @@
       Position end = getPosition();
       ProguardKeepRule rule =
           keepRuleBuilder.setSource(getSourceSnippet(contents, start, end)).setEnd(end).build();
-      if (options.isLegacyFullModeForKeepRulesEnabled(configurationBuilder)
+      if (options.isLegacyFullModeForKeepRulesEnabled()
           && rule.getMemberRules().isEmpty()
           && rule.getType() != ProguardKeepRuleType.KEEP_CLASSES_WITH_MEMBERS) {
         // If there are no member rules, a default rule for the parameterless constructor applies
         // in compatibility mode.
-        if (options.isLegacyFullModeForKeepRulesWarningsEnabled(configurationBuilder)) {
+        if (options.isLegacyFullModeForKeepRulesWarningsEnabled()) {
           reporter.warning(
               EmptyMemberRulesToDefaultInitRuleConversionDiagnostic.Factory.create(rule));
         }
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
index fcc499b..df606a1 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
@@ -15,6 +15,7 @@
   private final boolean enableExperimentalWhyAreYouNotInlining;
   private final boolean enableKeepRuntimeInvisibleAnnotations;
   private final boolean enableTestingOptions;
+  private final boolean forceProguardCompatibility;
 
   ProguardConfigurationParserOptions(
       boolean enableLegacyFullModeForKeepRules,
@@ -23,7 +24,8 @@
       boolean enableExperimentalConvertCheckNotNull,
       boolean enableExperimentalWhyAreYouNotInlining,
       boolean enableKeepRuntimeInvisibleAnnotations,
-      boolean enableTestingOptions) {
+      boolean enableTestingOptions,
+      boolean forceProguardCompatibility) {
     this.enableExperimentalCheckEnumUnboxed = enableExperimentalCheckEnumUnboxed;
     this.enableExperimentalConvertCheckNotNull = enableExperimentalConvertCheckNotNull;
     this.enableExperimentalWhyAreYouNotInlining = enableExperimentalWhyAreYouNotInlining;
@@ -31,23 +33,21 @@
     this.enableTestingOptions = enableTestingOptions;
     this.enableLegacyFullModeForKeepRules = enableLegacyFullModeForKeepRules;
     this.enableLegacyFullModeForKeepRulesWarnings = enableLegacyFullModeForKeepRulesWarnings;
+    this.forceProguardCompatibility = forceProguardCompatibility;
   }
 
   public static Builder builder() {
     return new Builder();
   }
 
-  public boolean isLegacyFullModeForKeepRulesEnabled(
-      ProguardConfiguration.Builder configurationBuilder) {
+  public boolean isLegacyFullModeForKeepRulesEnabled() {
     // TODO(b/356344563): Disable in full mode in the next major version.
-    return configurationBuilder.isForceProguardCompatibility() || enableLegacyFullModeForKeepRules;
+    return forceProguardCompatibility || enableLegacyFullModeForKeepRules;
   }
 
-  public boolean isLegacyFullModeForKeepRulesWarningsEnabled(
-      ProguardConfiguration.Builder configurationBuilder) {
-    assert isLegacyFullModeForKeepRulesEnabled(configurationBuilder);
-    return !configurationBuilder.isForceProguardCompatibility()
-        && enableLegacyFullModeForKeepRulesWarnings;
+  public boolean isLegacyFullModeForKeepRulesWarningsEnabled() {
+    assert isLegacyFullModeForKeepRulesEnabled();
+    return !forceProguardCompatibility && enableLegacyFullModeForKeepRulesWarnings;
   }
 
   public boolean isExperimentalCheckEnumUnboxedEnabled() {
@@ -79,6 +79,7 @@
     private boolean enableExperimentalWhyAreYouNotInlining;
     private boolean enableKeepRuntimeInvisibleAnnotations = true;
     private boolean enableTestingOptions;
+    private boolean forceProguardCompatibility = false;
 
     public Builder readEnvironment() {
       enableLegacyFullModeForKeepRules =
@@ -138,6 +139,11 @@
       return this;
     }
 
+    public Builder setForceProguardCompatibility(boolean forceProguardCompatibility) {
+      this.forceProguardCompatibility = forceProguardCompatibility;
+      return this;
+    }
+
     public ProguardConfigurationParserOptions build() {
       return new ProguardConfigurationParserOptions(
           enableLegacyFullModeForKeepRules,
@@ -146,7 +152,8 @@
           enableExperimentalConvertCheckNotNull,
           enableExperimentalWhyAreYouNotInlining,
           enableKeepRuntimeInvisibleAnnotations,
-          enableTestingOptions);
+          enableTestingOptions,
+          forceProguardCompatibility);
     }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/conversion/PartialCallGraphTest.java b/src/test/java/com/android/tools/r8/ir/conversion/PartialCallGraphTest.java
index 0cb5bfa..69e016e 100644
--- a/src/test/java/com/android/tools/r8/ir/conversion/PartialCallGraphTest.java
+++ b/src/test/java/com/android/tools/r8/ir/conversion/PartialCallGraphTest.java
@@ -20,6 +20,7 @@
 import com.android.tools.r8.ir.conversion.callgraph.Node;
 import com.android.tools.r8.ir.conversion.callgraph.PartialCallGraphBuilder;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.ProguardConfiguration;
 import com.android.tools.r8.shaking.ProguardConfigurationParser;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
@@ -47,12 +48,15 @@
         computeAppViewWithLiveness(
             app,
             factory -> {
+              Reporter reporter = new Reporter();
+              ProguardConfiguration.Builder configurationBuilder =
+                  ProguardConfiguration.builder(factory, reporter);
               ProguardConfigurationParser parser =
-                  new ProguardConfigurationParser(factory, new Reporter());
+                  new ProguardConfigurationParser(factory, reporter, configurationBuilder);
               parser.parse(
                   createConfigurationForTesting(
                       ImmutableList.of("-keep class ** { void m1(); void m5(); }")));
-              return parser.getConfig();
+              return configurationBuilder.build();
             });
     this.options = appView.options();
     this.executorService = ThreadUtils.getExecutorService(options);
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index 665eba2..907e566 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -161,6 +161,8 @@
       ImmutableList.of("", " ", "   ", "\t", " \t", " \t", " \t ", " \t\t \t ");
   private List<String> lineSeparators = ImmutableList.of("\n", "\r\n");
   private List<Character> quotes = ImmutableList.of('"', '\'');
+  private ProguardConfiguration.Builder builder;
+  private DexItemFactory dexItemFactory;
 
   @Parameterized.Parameters(name = "{0}")
   public static TestParametersCollection data() {
@@ -175,53 +177,66 @@
   public void reset() {
     handler = new KeepingDiagnosticHandler();
     reporter = new Reporter(handler);
-    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
+    dexItemFactory = new DexItemFactory();
+    builder = ProguardConfiguration.builder(dexItemFactory, reporter);
+    parser =
+        new ProguardConfigurationParser(
+            dexItemFactory,
+            reporter,
+            ProguardConfigurationParserOptions.builder()
+                .setEnableLegacyFullModeForKeepRules(false)
+                .setEnableExperimentalCheckEnumUnboxed(false)
+                .setEnableExperimentalConvertCheckNotNull(false)
+                .setEnableExperimentalWhyAreYouNotInlining(false)
+                .setEnableTestingOptions(false)
+                .build(),
+            null,
+            builder);
   }
 
   @Before
   public void resetAllowTestOptions() {
     handler = new KeepingDiagnosticHandler();
     reporter = new Reporter(handler);
+    dexItemFactory = new DexItemFactory();
+    builder = ProguardConfiguration.builder(dexItemFactory, reporter);
     parser =
         new ProguardConfigurationParser(
-            new DexItemFactory(),
+            dexItemFactory,
             reporter,
             ProguardConfigurationParserOptions.builder()
                 .setEnableExperimentalCheckEnumUnboxed(false)
                 .setEnableExperimentalConvertCheckNotNull(false)
                 .setEnableExperimentalWhyAreYouNotInlining(false)
                 .setEnableTestingOptions(true)
-                .build());
+                .build(),
+            null,
+            builder);
   }
 
   @Test
   public void parse() throws Exception {
-    ProguardConfigurationParser parser;
-
     // Parse from file.
-    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(PROGUARD_SPEC_FILE));
     verifyParserEndsCleanly();
-    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> rules = builder.build().getRules();
     assertEquals(24, rules.size());
     assertEquals(1, rules.get(0).getMemberRules().size());
 
     // Parse from strings.
-    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     List<String> lines = FileUtils.readAllLines(Paths.get(PROGUARD_SPEC_FILE));
     parser.parse(createConfigurationForTesting(lines));
-    rules = parser.getConfig().getRules();
+    rules = builder.build().getRules();
     assertEquals(24, rules.size());
     assertEquals(1, rules.get(0).getMemberRules().size());
   }
 
   @Test
   public void parseMultipleNamePatterns() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(MULTIPLE_NAME_PATTERNS_FILE));
     verifyParserEndsCleanly();
-    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> rules = builder.build().getRules();
     assertEquals(1, rules.size());
     ProguardConfigurationRule rule = rules.get(0);
     assertEquals(1, rule.getMemberRules().size());
@@ -240,9 +255,6 @@
 
   @Test
   public void parseNonJavaIdentifiers() {
-    DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(dexItemFactory, new Reporter());
     String nonJavaIdentifiers =
         String.join("\n", ImmutableList.of(
             "-keep class -package-.-ClassNameWithDash-{",
@@ -251,7 +263,7 @@
             "}"));
     parser.parse(createConfigurationForTesting(ImmutableList.of(nonJavaIdentifiers)));
     verifyParserEndsCleanly();
-    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> rules = builder.build().getRules();
     assertEquals(1, rules.size());
     assertEquals(ProguardClassType.CLASS, rules.get(0).getClassType());
     assertEquals(1, rules.get(0).getClassNames().size());
@@ -283,13 +295,10 @@
 
   private void testDontXXX(
       String xxx, Function<ProguardConfiguration, Predicate<DexType>> matcherFactory) {
-    DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(dexItemFactory, reporter);
     String configuration = "-dont" + xxx + " !foobar,*bar";
     parser.parse(createConfigurationForTesting(ImmutableList.of(configuration)));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     Predicate<DexType> matcher = matcherFactory.apply(config);
     assertFalse(matcher.test(dexItemFactory.createType("Lboobaz;")));
     assertTrue(matcher.test(dexItemFactory.createType("Lboobar;")));
@@ -305,14 +314,12 @@
   private void testDontXXXMultiple(
       String xxx, Function<ProguardConfiguration, Predicate<DexType>> matcherFactory) {
     DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(dexItemFactory, reporter);
     List<String> configuration1 = ImmutableList.of("-dont" + xxx + " foo.**, bar.**");
     List<String> configuration2 = ImmutableList.of("-dont" + xxx + " foo.**", "-dontwarn bar.**");
     for (List<String> configuration : ImmutableList.of(configuration1, configuration2)) {
       parser.parse(createConfigurationForTesting(configuration));
       verifyParserEndsCleanly();
-      ProguardConfiguration config = parser.getConfig();
+      ProguardConfiguration config = builder.build();
       Predicate<DexType> matcher = matcherFactory.apply(config);
       assertTrue(matcher.test(dexItemFactory.createType("Lfoo/Bar;")));
       assertTrue(matcher.test(dexItemFactory.createType("Lfoo/bar7Bar;")));
@@ -329,12 +336,10 @@
   private void testDontXXXAllExplicitly(
       String xxx, Function<ProguardConfiguration, Predicate<DexType>> matcherFactory) {
     DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(dexItemFactory, reporter);
     String dontwarnAll = "-dont" + xxx + " *";
     parser.parse(createConfigurationForTesting(ImmutableList.of(dontwarnAll)));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     Predicate<DexType> matcher = matcherFactory.apply(config);
     assertTrue(matcher.test(dexItemFactory.createType("Lboobaz;")));
     assertTrue(matcher.test(dexItemFactory.createType("Lboobar;")));
@@ -350,12 +355,10 @@
   private void testDontXXXAllImplicitly(
       String xxx, Function<ProguardConfiguration, Predicate<DexType>> matcherFactory) {
     DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(dexItemFactory, reporter);
     String dontwarnAll = "-dont" + xxx;
     String otherOption = "-keep class *";
     parser.parse(createConfigurationForTesting(ImmutableList.of(dontwarnAll, otherOption)));
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     Predicate<DexType> matcher = matcherFactory.apply(config);
     assertTrue(matcher.test(dexItemFactory.createType("Lboobaz;")));
     assertTrue(matcher.test(dexItemFactory.createType("Lboobar;")));
@@ -370,11 +373,9 @@
 
   @Test
   public void parseAccessFlags() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(ACCESS_FLAGS_FILE));
     verifyParserEndsCleanly();
-    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> rules = builder.build().getRules();
     assertEquals(1, rules.size());
     ProguardConfigurationRule rule = rules.get(0);
     ClassAccessFlags publicAndFinalFlags = ClassAccessFlags.fromSharedAccessFlags(0);
@@ -416,11 +417,9 @@
 
   @Test
   public void parseWhyAreYouKeeping() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(WHY_ARE_YOU_KEEPING_FILE));
     verifyParserEndsCleanly();
-    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> rules = builder.build().getRules();
     assertEquals(1, rules.size());
     ProguardConfigurationRule rule = rules.get(0);
     assertEquals(1, rule.getClassNames().size());
@@ -431,11 +430,9 @@
 
   @Test
   public void parseAssumeNoSideEffects() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(ASSUME_NO_SIDE_EFFECTS));
     verifyParserEndsCleanly();
-    List<ProguardConfigurationRule> assumeNoSideEffects = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> assumeNoSideEffects = builder.build().getRules();
     assertEquals(1, assumeNoSideEffects.size());
     assumeNoSideEffects.get(0).getMemberRules().forEach(rule -> {
       assertFalse(rule.hasReturnValue());
@@ -444,11 +441,9 @@
 
   @Test
   public void parseAssumeNoSideEffectsWithReturnValue() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(ASSUME_NO_SIDE_EFFECTS_WITH_RETURN_VALUE));
     verifyParserEndsCleanly();
-    List<ProguardConfigurationRule> assumeNoSideEffects = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> assumeNoSideEffects = builder.build().getRules();
     assertEquals(1, assumeNoSideEffects.size());
     int matches = 0;
     for (ProguardMemberRule rule : assumeNoSideEffects.get(0).getMemberRules()) {
@@ -530,11 +525,9 @@
 
   @Test
   public void parseAssumeValuesWithReturnValue() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(ASSUME_VALUES_WITH_RETURN_VALUE));
     verifyParserEndsCleanly();
-    List<ProguardConfigurationRule> assumeValues = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> assumeValues = builder.build().getRules();
     assertEquals(1, assumeValues.size());
     int matches = 0;
     for (ProguardMemberRule rule : assumeValues.get(0).getMemberRules()) {
@@ -618,13 +611,10 @@
 
   @Test
   public void testAdaptClassStrings() {
-    DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(dexItemFactory, reporter);
     String adaptClassStrings = "-adaptclassstrings !foobar,*bar";
     parser.parse(createConfigurationForTesting(ImmutableList.of(adaptClassStrings)));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertFalse(
         config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
     assertTrue(
@@ -635,16 +625,13 @@
 
   @Test
   public void testAdaptClassStringsMultiple() {
-    DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(dexItemFactory, reporter);
     List<String> configuration1 = ImmutableList.of("-adaptclassstrings foo.**, bar.**");
     List<String> configuration2 =
         ImmutableList.of("-adaptclassstrings foo.**", "-adaptclassstrings bar.**");
     for (List<String> configuration : ImmutableList.of(configuration1, configuration2)) {
       parser.parse(createConfigurationForTesting(configuration));
       verifyParserEndsCleanly();
-      ProguardConfiguration config = parser.getConfig();
+      ProguardConfiguration config = builder.build();
       assertTrue(
           config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoo/Bar;")));
       assertTrue(
@@ -656,13 +643,10 @@
 
   @Test
   public void testAdaptClassStringsAllExplicitly() {
-    DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(dexItemFactory, reporter);
     String adaptAll = "-adaptclassstrings *";
     parser.parse(createConfigurationForTesting(ImmutableList.of(adaptAll)));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(
         config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
     assertTrue(
@@ -673,13 +657,10 @@
 
   @Test
   public void testAdaptClassStringsAllImplicitly() {
-    DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(dexItemFactory, reporter);
     String adaptAll = "-adaptclassstrings";
     parser.parse(createConfigurationForTesting(ImmutableList.of(adaptAll)));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(
         config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
     assertTrue(
@@ -690,8 +671,6 @@
 
   @Test
   public void testIdentifierNameString() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     String config1 =
         "-identifiernamestring class a.b.c.*GeneratedClass {\n"
             + "  static java.lang.String CONTAINING_TYPE_*;\n"
@@ -706,7 +685,7 @@
             + "}";
     parser.parse(createConfigurationForTesting(ImmutableList.of(config1, config2, config3)));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     List<ProguardConfigurationRule> identifierNameStrings = config.getRules();
     assertEquals(3, identifierNameStrings.size());
     assertEquals(1, identifierNameStrings.get(0).getClassNames().size());
@@ -743,7 +722,7 @@
 
   @Test
   public void testConvertCheckNotNullWithReturn() {
-    DexItemFactory dexItemFactory = new DexItemFactory();
+    ProguardConfiguration.Builder builder = ProguardConfiguration.builder(dexItemFactory, reporter);
     ProguardConfigurationParser parser =
         new ProguardConfigurationParser(
             dexItemFactory,
@@ -753,18 +732,19 @@
                 .setEnableExperimentalConvertCheckNotNull(true)
                 .setEnableExperimentalWhyAreYouNotInlining(false)
                 .setEnableTestingOptions(false)
-                .build());
+                .build(),
+            null,
+            builder);
     String rule = "-convertchecknotnull class C { ** m(**, ...); }";
     parser.parse(createConfigurationForTesting(ImmutableList.of(rule)));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
     assertTrue(config.getRules().get(0) instanceof ConvertCheckNotNullRule);
   }
 
   @Test
   public void testConvertCheckNotNullWithoutReturn() {
-    DexItemFactory dexItemFactory = new DexItemFactory();
     ProguardConfigurationParser parser =
         new ProguardConfigurationParser(
             dexItemFactory,
@@ -774,32 +754,30 @@
                 .setEnableExperimentalConvertCheckNotNull(true)
                 .setEnableExperimentalWhyAreYouNotInlining(false)
                 .setEnableTestingOptions(false)
-                .build());
+                .build(),
+            null,
+            builder);
     String rule = "-convertchecknotnull class C { void m(**, ...); }";
     parser.parse(createConfigurationForTesting(ImmutableList.of(rule)));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
     assertTrue(config.getRules().get(0) instanceof ConvertCheckNotNullRule);
   }
 
   @Test
   public void parseDontobfuscate() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(DONT_OBFUSCATE));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertFalse(config.isObfuscating());
   }
 
   @Test
   public void parseRepackageClassesEmpty() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(PACKAGE_OBFUSCATION_1));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
     assertNotNull(config.getPackagePrefix());
     assertEquals("", config.getPackagePrefix());
@@ -807,11 +785,9 @@
 
   @Test
   public void parseRepackageClassesNonEmpty() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(PACKAGE_OBFUSCATION_2));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
     assertNotNull(config.getPackagePrefix());
     assertEquals("p.q.r", config.getPackagePrefix());
@@ -819,11 +795,9 @@
 
   @Test
   public void parseFlattenPackageHierarchyEmpty() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(PACKAGE_OBFUSCATION_3));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(PackageObfuscationMode.FLATTEN, config.getPackageObfuscationMode());
     assertNotNull(config.getPackagePrefix());
     assertEquals("", config.getPackagePrefix());
@@ -831,11 +805,9 @@
 
   @Test
   public void parseFlattenPackageHierarchyNonEmpty() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(PACKAGE_OBFUSCATION_4));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(PackageObfuscationMode.FLATTEN, config.getPackageObfuscationMode());
     assertNotNull(config.getPackagePrefix());
     assertEquals("p.q.r", config.getPackagePrefix());
@@ -843,13 +815,11 @@
 
   @Test
   public void flattenPackageHierarchyCannotOverrideRepackageClasses() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     Path path = Paths.get(PACKAGE_OBFUSCATION_5);
     parser.parse(path);
     checkDiagnostics(handler.warnings, path, 6, 1,
         "repackageclasses", "overrides", "flattenpackagehierarchy");
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
     assertNotNull(config.getPackagePrefix());
     assertEquals("top", config.getPackagePrefix());
@@ -857,13 +827,11 @@
 
   @Test
   public void repackageClassesOverridesFlattenPackageHierarchy() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     Path path = Paths.get(PACKAGE_OBFUSCATION_6);
     parser.parse(path);
     checkDiagnostics(handler.warnings, path, 6, 1,
         "repackageclasses", "overrides", "flattenpackagehierarchy");
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
     assertNotNull(config.getPackagePrefix());
     assertEquals("top", config.getPackagePrefix());
@@ -871,11 +839,9 @@
 
   @Test
   public void parseApplyMapping() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(APPLY_MAPPING));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.hasApplyMappingFile());
   }
 
@@ -883,8 +849,6 @@
   public void parseApplyMappingWithoutFile() {
     Path path = Paths.get(APPLY_MAPPING_WITHOUT_FILE);
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(path);
       fail("Expect to fail due to the lack of file name.");
     } catch (RuntimeException e) {
@@ -894,8 +858,6 @@
 
   @Test
   public void parseAdaptKotlinMetadata() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     Path path = Paths.get(ADAPT_KOTLIN_METADATA);
     parser.parse(path);
     verifyParserEndsCleanly();
@@ -903,12 +865,10 @@
 
   @Test
   public void parseKeepKotlinMetadata() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     Path path = Paths.get(KEEP_KOTLIN_METADATA);
     parser.parse(path);
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(
         "-keepattributes RuntimeVisibleAnnotations,RuntimeInvisibleAnnotations",
         config.getKeepAttributes().toString());
@@ -919,8 +879,6 @@
 
   @Test
   public void parseIncluding() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(INCLUDING));
     verifyParserEndsCleanly();
   }
@@ -929,8 +887,7 @@
   public void parseInvalidIncluding1() {
     Path path = Paths.get(INVALID_INCLUDING_1);
     try {
-      new ProguardConfigurationParser(new DexItemFactory(), reporter)
-          .parse(path);
+      parser.parse(path);
       fail();
     } catch (RuntimeException e) {
       checkDiagnostics(handler.errors, path, 6, 10,"does-not-exist.flags");
@@ -941,8 +898,7 @@
   public void parseInvalidIncluding2() {
     Path path = Paths.get(INVALID_INCLUDING_2);
     try {
-      new ProguardConfigurationParser(new DexItemFactory(), reporter)
-          .parse(path);
+      parser.parse(path);
       fail();
     } catch (RuntimeException e) {
       checkDiagnostics(handler.errors, path, 6,2, "does-not-exist.flags");
@@ -951,23 +907,20 @@
 
   @Test
   public void parseLibraryJars() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     if (!ToolHelper.isLinux() && !ToolHelper.isMac()) {
       parser.parse(Paths.get(LIBRARY_JARS_WIN));
     } else {
       parser.parse(Paths.get(LIBRARY_JARS));
     }
-    assertEquals(4, parser.getConfig().getLibraryjars().size());
+    assertEquals(4, builder.build().getLibraryjars().size());
   }
 
   @Test
   public void parseInvalidFilePattern() {
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
-      parser.parse(createConfigurationForTesting(
-          Collections.singletonList("-injars abc.jar(*.zip;*.class)")));
+      parser.parse(
+          createConfigurationForTesting(
+              Collections.singletonList("-injars abc.jar(*.zip;*.class)")));
       fail();
     } catch (RuntimeException e) {
       assertEquals(1, handler.errors.size());
@@ -1027,72 +980,56 @@
 
   @Test
   public void parseSeeds() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(SEEDS));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.isPrintSeeds());
     assertNull(config.getSeedFile());
   }
 
   @Test
   public void parseSeeds2() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(SEEDS_2));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.isPrintSeeds());
     assertNotNull(config.getSeedFile());
   }
 
   @Test
   public void parseVerbose() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(VERBOSE));
     verifyParserEndsCleanly();
   }
 
   @Test
   public void parseKeepdirectories() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(KEEPDIRECTORIES));
     verifyParserEndsCleanly();
   }
 
   @Test
   public void parseDontshrink() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(DONT_SHRINK));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertFalse(config.isShrinking());
   }
 
   @Test
   public void parseDontSkipNonPublicLibraryClasses() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES));
     verifyParserEndsCleanly();
   }
 
   @Test
   public void parseDontskipnonpubliclibraryclassmembers() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS));
     verifyParserEndsCleanly();
   }
 
   @Test
   public void parseIdentifiernamestring() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     Path source = Paths.get(IDENTIFIER_NAME_STRING);
     parser.parse(source);
     verifyParserEndsCleanly();
@@ -1100,41 +1037,33 @@
 
   @Test
   public void parseOverloadAggressively() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(OVERLOAD_AGGRESIVELY));
     verifyParserEndsCleanly();
   }
 
   @Test
   public void parseDontOptimize() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(DONT_OPTIMIZE));
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     verifyParserEndsCleanly();
     assertFalse(config.isOptimizing());
   }
 
   @Test
   public void parseDontOptimizeOverridesPasses() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     Path path = Paths.get(DONT_OPTIMIZE_OVERRIDES_PASSES);
     parser.parse(path);
     checkDiagnostics(handler.infos, path, 7, 1, "Ignoring", "-optimizationpasses");
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertFalse(config.isOptimizing());
   }
 
   @Test
   public void parseOptimizationPasses() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     Path path = Paths.get(OPTIMIZATION_PASSES);
     parser.parse(path);
     checkDiagnostics(handler.infos, path, 5, 1, "Ignoring", "-optimizationpasses");
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.isOptimizing());
   }
 
@@ -1142,8 +1071,6 @@
   public void parseOptimizationPassesError() {
     Path path = Paths.get(OPTIMIZATION_PASSES_WITHOUT_N);
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(path);
       fail();
     } catch (AbortException e) {
@@ -1168,34 +1095,24 @@
 
   @Test
   public void parseAndskipSingleArgument() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(PARSE_AND_SKIP_SINGLE_ARGUMENT));
     verifyParserEndsCleanly();
   }
 
   @Test
   public void parse_printconfiguration_noArguments() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
-    parser.parse(createConfigurationForTesting(ImmutableList.of(
-        "-printconfiguration"
-    )));
+    parser.parse(createConfigurationForTesting(ImmutableList.of("-printconfiguration")));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.isPrintConfiguration());
     assertNull(config.getPrintConfigurationFile());
   }
 
   @Test
   public void parse_printconfiguration_argument() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
-    parser.parse(createConfigurationForTesting(ImmutableList.of(
-        "-printconfiguration file_name"
-    )));
+    parser.parse(createConfigurationForTesting(ImmutableList.of("-printconfiguration file_name")));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.isPrintConfiguration());
     assertEquals("file_name", config.getPrintConfigurationFile().toString());
   }
@@ -1255,8 +1172,7 @@
               "-optimizations xxx",
               "-optimizationpasses 5",
               "-optimizations yyy"));
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
       parser.parse(proguardConfig);
       assertEquals(3, handler.infos.size());
 
@@ -1292,30 +1208,24 @@
 
   @Test
   public void parsePrintUsage() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(PRINT_USAGE));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.isPrintUsage());
     assertNull(config.getPrintUsageFile());
   }
 
   @Test
   public void parsePrintUsageToFile() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(PRINT_USAGE_TO_FILE));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.isPrintUsage());
     assertNotNull(config.getPrintUsageFile());
   }
 
   @Test
   public void parseTarget() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(TARGET));
     verifyParserEndsCleanly();
   }
@@ -1328,8 +1238,6 @@
         "}                             "
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -1343,8 +1251,6 @@
     Path proguardConfig = writeTextToTempFile(
         System.lineSeparator(), ImmutableList.of("-keep"), false);
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -1361,8 +1267,6 @@
         "}                             "
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -1373,8 +1277,6 @@
 
   @Test
   public void parseCustomFlags() throws Exception {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     // Custom Proguard flags -runtype and -laststageoutput are ignored.
     Path proguardConfig = writeTextToTempFile(
         "-runtype FINAL                    ",
@@ -1392,11 +1294,10 @@
           writeTextToTempFile(
               lineSeparator,
               ImmutableList.of("-renamesourcefileattribute PG", "-keepattributes SourceFile"));
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
       parser.parse(proguardConfig);
       verifyParserEndsCleanly();
-      ProguardConfiguration config = parser.getConfigRawForTesting();
+      ProguardConfiguration config = builder.buildRaw();
       assertEquals("PG", config.getRenameSourceFileAttribute());
       assertTrue(config.getKeepAttributes().sourceFile);
     }
@@ -1410,11 +1311,10 @@
           ImmutableList.of(
               "-renamesourcefileattribute",
               "-keepattributes SourceFile"));
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
       parser.parse(proguardConfig);
       verifyParserEndsCleanly();
-      ProguardConfiguration config = parser.getConfigRawForTesting();
+      ProguardConfiguration config = builder.buildRaw();
       assertEquals("", config.getRenameSourceFileAttribute());
       assertTrue(config.getKeepAttributes().sourceFile);
     }
@@ -1429,11 +1329,10 @@
             ImmutableList.of(
                 "-renamesourcefileattribute " + quote + "PG" + quote,
                 "-keepattributes SourceFile"));
-        ProguardConfigurationParser parser =
-            new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
         parser.parse(proguardConfig);
         verifyParserEndsCleanly();
-        ProguardConfiguration config = parser.getConfigRawForTesting();
+        ProguardConfiguration config = builder.buildRaw();
         assertEquals("PG", config.getRenameSourceFileAttribute());
         assertTrue(config.getKeepAttributes().sourceFile);
       }
@@ -1449,11 +1348,10 @@
             ImmutableList.of(
                 "-renamesourcefileattribute " + quote + quote,
                 "-keepattributes SourceFile"));
-        ProguardConfigurationParser parser =
-            new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
         parser.parse(proguardConfig);
         verifyParserEndsCleanly();
-        ProguardConfiguration config = parser.getConfigRawForTesting();
+        ProguardConfiguration config = builder.buildRaw();
         assertEquals("", config.getRenameSourceFileAttribute());
         assertTrue(config.getKeepAttributes().sourceFile);
       }
@@ -1461,13 +1359,10 @@
   }
 
   private void testKeepattributes(List<String> expected, String config) {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(createConfigurationForTesting(ImmutableList.of(config)));
     verifyParserEndsCleanly();
     assertEquals(
-        ProguardKeepAttributes.fromPatterns(expected),
-        parser.getConfigRawForTesting().getKeepAttributes());
+        ProguardKeepAttributes.fromPatterns(expected), builder.buildRaw().getKeepAttributes());
   }
 
   @Test
@@ -1507,8 +1402,6 @@
   }
 
   private void testKeeppackagenames(String config) {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(createConfigurationForTesting(ImmutableList.of(config)));
     verifyParserEndsCleanly();
   }
@@ -1536,8 +1429,6 @@
   @Test
   public void parseInvalidKeepattributes_brokenList() {
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(createConfigurationForTesting(ImmutableList.of("-keepattributes xxx,")));
       fail();
     } catch (RuntimeException e) {
@@ -1549,57 +1440,30 @@
   @Test
   public void parseUseUniqueClassMemberNames() throws IOException {
     Path proguardConfig = writeTextToTempFile("-useuniqueclassmembernames");
-    new ProguardConfigurationParser(new DexItemFactory(), reporter).parse(proguardConfig);
+    parser.parse(proguardConfig);
     checkDiagnostics(
         handler.warnings, proguardConfig, 1, 1, "Ignoring", "-useuniqueclassmembernames");
   }
 
   @Test
-  public void parseKeepParameterNames() {
-    try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
-      parser.parse(createConfigurationForTesting(ImmutableList.of(
-          "-keepparameternames"
-      )));
-      parser.getConfig();
-      fail();
-    } catch (AbortException e) {
-      assertTrue(handler.errors.get(0).getDiagnosticMessage().contains(
-          "-keepparameternames is not supported"));
-    }
-  }
-
-  @Test
   public void parseKeepParameterNamesWithoutMinification() {
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
-    parser.parse(createConfigurationForTesting(ImmutableList.of(
-        "-keepparameternames",
-        "-dontobfuscate"
-    )));
+    parser.parse(
+        createConfigurationForTesting(ImmutableList.of("-keepparameternames", "-dontobfuscate")));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.isKeepParameterNames());
 
-    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
-    parser.parse(createConfigurationForTesting(ImmutableList.of(
-        "-keepparameternames"
-    )));
+    parser.parse(createConfigurationForTesting(ImmutableList.of("-keepparameternames")));
     verifyParserEndsCleanly();
-    parser.parse(createConfigurationForTesting(ImmutableList.of(
-        "-dontobfuscate"
-    )));
+    parser.parse(createConfigurationForTesting(ImmutableList.of("-dontobfuscate")));
     verifyParserEndsCleanly();
-    config = parser.getConfig();
+    config = builder.build();
     assertTrue(config.isKeepParameterNames());
   }
 
   @Test
   public void parseShortLine() {
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(createConfigurationForTesting(Collections.singletonList("-")));
       fail();
     } catch (AbortException e) {
@@ -1611,12 +1475,9 @@
   @Test
   public void parseNoLocals() {
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(createConfigurationForTesting(Collections.singletonList("--no-locals")));
       fail();
     } catch (AbortException e) {
-
       assertEquals(1, handler.errors.size());
       assertTrue(handler.errors.get(0).getDiagnosticMessage().contains("--no-locals"));
     }
@@ -1788,11 +1649,10 @@
         "-keep class C",
         "-keepnames class dagger.Lazy"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     // Three -if rules and one independent -keepnames
     assertEquals(4, config.getRules().size());
     long ifCount =
@@ -1818,11 +1678,10 @@
         "-if class **$R**",
         "-keep class **$D<2>"  // <2> corresponds to the 2nd ** in -if rule.
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
     ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
     assertEquals("**$R**", if0.getClassNames().toString());
@@ -1849,11 +1708,10 @@
         "  <1>.F<2> fld;",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
     ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
     assertEquals("**.R*", if0.getClassNames().toString());
@@ -1872,11 +1730,10 @@
         "  java.lang.String fld<2>;",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
     ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
     assertEquals("**.R*", if0.getClassNames().toString());
@@ -1895,11 +1752,10 @@
         "  <1>.M<2> mtd(...);",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
     ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
     assertEquals("**.R*", if0.getClassNames().toString());
@@ -1939,11 +1795,10 @@
         "  void <3>_delegate(...);",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
     ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
     assertEquals("**.R*", if0.getClassNames().toString());
@@ -1964,11 +1819,10 @@
         "  <3> <4>(...);",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
     ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
     assertEquals("**.R*", if0.getClassNames().toString());
@@ -1987,8 +1841,6 @@
         "-keep class **D<n>"
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2004,8 +1856,6 @@
         "-keep class **D<*>"
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2022,8 +1872,7 @@
         "  int id<*>;",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
   }
@@ -2036,8 +1885,7 @@
         "  int id<<*>>;",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
   }
@@ -2046,8 +1894,7 @@
   public void parse_if_closeBracketBeforeOpenBracket_inMemberName() throws Exception {
     Path proguardConfig =
         writeTextToTempFile("-if class **$R**", "-keep class **D<2> {", "  int id>1<;", "}");
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
   }
@@ -2061,8 +1908,6 @@
         "}"
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2078,8 +1923,6 @@
         "-keep class **D<0>"  // nth wildcard starts from 1, not 0.
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2095,8 +1938,6 @@
         "-keep class **D<4>"  // There are 3 previous wildcards in this rule.
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2112,8 +1953,6 @@
         "-keep class **D<2>"
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2133,8 +1972,6 @@
         "}"
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2152,8 +1989,6 @@
         "-keep @interface <1>.<3><2>"
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2169,8 +2004,6 @@
         "-if   class **$$InjectAdapter"
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2185,8 +2018,6 @@
         "-if   class **$$ModuleAdapter"
     );
     try {
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
       parser.parse(proguardConfig);
       fail();
     } catch (AbortException e) {
@@ -2216,8 +2047,7 @@
         "  public java.lang.String toString();",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
         "Ignoring", "-assumenoexternalsideeffects");
@@ -2230,8 +2060,7 @@
         "  public static void arraycopy(java.lang.Object, int, java.lang.Object, int, int);",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
         "Ignoring", "-assumenoescapingparameters");
@@ -2254,8 +2083,7 @@
         "  public java.lang.StringBuilder append(double);",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
         "Ignoring", "-assumenoexternalreturnvalues");
@@ -2266,8 +2094,7 @@
     Path proguardConfig = writeTextToTempFile(
         "-dump"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
         "Ignoring", "-dump");
@@ -2278,8 +2105,7 @@
     Path proguardConfig = writeTextToTempFile(
         "-dump class_files.txt"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
         "Ignoring", "-dump");
@@ -2290,8 +2116,7 @@
     Path proguardConfig = writeTextToTempFile(
         "-android"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
   }
@@ -2301,8 +2126,7 @@
     Path proguardConfig = writeTextToTempFile(
         "-mergeinterfacesaggressively"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
   }
@@ -2312,8 +2136,7 @@
     Path proguardConfig = writeTextToTempFile(
         "-addconfigurationdebugging"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     assertEquals(0, handler.infos.size());
     assertEquals(1, handler.warnings.size());
@@ -2327,8 +2150,7 @@
         "  A <fields>;",
         "}"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
   }
@@ -2338,12 +2160,11 @@
     Path proguardConfig = writeTextToTempFile(
         "-keep public @ interface test.MyAnnotation"
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
 
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
     ProguardKeepRule rule = (ProguardKeepRule) config.getRules().get(0);
     assertEquals(ProguardClassType.ANNOTATION_INTERFACE, rule.getClassType());
@@ -2354,8 +2175,7 @@
     Path proguardConfig =
         writeTextToTempFile(
             "-keepclassmembernames class A {", "  <public methods>;", "  <public fields>;", "}");
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
   }
@@ -2368,8 +2188,7 @@
             "-keepclassmembers class <1> {",
             "  static <1>$* Companion;",
             "}");
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     assertEquals(0, handler.warnings.size());
   }
@@ -2383,7 +2202,7 @@
     reset();
     parser.parse(createConfigurationForTesting(sourceRules));
     verifyParserEndsCleanly();
-    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> rules = builder.build().getRules();
     assertEquals(expected.size(), rules.size());
     for (int i = 0; i < expected.size(); i++) {
       assertEquals(trim ? expected.get(i).trim() : expected.get(i), rules.get(i).getSource());
@@ -2445,11 +2264,10 @@
         "-printconfiguration",
         "@" + includeFile.toAbsolutePath()
     );
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertTrue(config.isPrintConfiguration());
     assertNull(config.getPrintConfigurationFile());
     assertEquals("SRC", config.getRenameSourceFileAttribute());
@@ -2464,7 +2282,7 @@
       reset();
       parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
       verifyParserEndsCleanly();
-      ProguardConfiguration config = parser.getConfig();
+      ProguardConfiguration config = builder.build();
       check.accept(value, extractPath.apply(config).toString());
     }
   }
@@ -2538,7 +2356,7 @@
       reset();
       parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
       verifyParserEndsCleanly();
-      ProguardConfiguration config = parser.getConfig();
+      ProguardConfiguration config = builder.build();
       Path path = extractPath.apply(config);
       check.accept(
           value
@@ -2625,7 +2443,7 @@
     reset();
     parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     checker.accept(config.getPackageObfuscationMode(), config.getPackagePrefix());
   }
 
@@ -2699,13 +2517,13 @@
   private ProguardConfiguration parseAndVerifyParserEndsCleanly(List<String> config) {
     parser.parse(createConfigurationForTesting(config));
     verifyParserEndsCleanly();
-    return parser.getConfig();
+    return builder.build();
   }
 
   private ProguardConfiguration parseAndVerifyParserEndsCleanly(Path config) {
     parser.parse(config);
     verifyParserEndsCleanly();
-    return parser.getConfig();
+    return builder.build();
   }
 
   private void verifyParserEndsCleanly() {
@@ -2717,8 +2535,6 @@
   @Test
   public void b124181032() {
     // Test spaces and quotes in class name list.
-    ProguardConfigurationParser parser;
-    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(
         createConfigurationForTesting(
             ImmutableList.of(
@@ -2727,7 +2543,7 @@
                 "<fields>;",
                 "<init>();",
                 "}")));
-    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
+    List<ProguardConfigurationRule> rules = builder.build().getRules();
     assertEquals(1, rules.size());
     ProguardConfigurationRule rule = rules.get(0);
     assertEquals(ProguardKeepRuleType.KEEP_CLASS_MEMBERS.toString(), rule.typeString());
@@ -2743,10 +2559,9 @@
           packageObfuscationMode == PackageObfuscationMode.FLATTEN
               ? "-flattenpackagehierarchy"
               : "-repackageclasses";
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
       parser.parse(createConfigurationForTesting(ImmutableList.of(directive + " -keep class *")));
-      ProguardConfiguration configuration = parser.getConfig();
+      ProguardConfiguration configuration = builder.build();
       assertEquals(packageObfuscationMode, configuration.getPackageObfuscationMode());
       assertEquals("", configuration.getPackagePrefix());
 
@@ -2769,12 +2584,11 @@
           packageObfuscationMode == PackageObfuscationMode.FLATTEN
               ? "-flattenpackagehierarchy"
               : "-repackageclasses";
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
       parser.parse(
           createConfigurationForTesting(
               ImmutableList.of(directive + " @" + includeFile.toAbsolutePath())));
-      ProguardConfiguration configuration = parser.getConfig();
+      ProguardConfiguration configuration = builder.build();
       assertEquals(packageObfuscationMode, configuration.getPackageObfuscationMode());
       assertEquals("", configuration.getPackagePrefix());
 
@@ -2791,8 +2605,7 @@
   public void negatedMemberTypeTest() throws IOException {
     Path proguardConfigurationFile = writeTextToTempFile("-keepclassmembers class ** { !int x; }");
     try {
-      new ProguardConfigurationParser(new DexItemFactory(), reporter)
-          .parse(proguardConfigurationFile);
+      parser.parse(proguardConfigurationFile);
       fail("Expected to fail since the type name cannot be negated.");
     } catch (RuntimeException e) {
       checkDiagnostics(
@@ -2851,11 +2664,9 @@
 
   @Test
   public void parseIncludeCode() throws Exception {
-    ProguardConfigurationParser parser;
-    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
     Path proguardConfig = writeTextToTempFile("-keep,includecode class A { method(); }");
     parser.parse(proguardConfig);
-    assertEquals(1, parser.getConfig().getRules().size());
+    assertEquals(1, builder.build().getRules().size());
     assertEquals(1, handler.infos.size());
     checkDiagnostics(handler.infos, proguardConfig, 1, 7, "Ignoring modifier", "includecode");
   }
@@ -2863,8 +2674,6 @@
   @Test
   public void parseFileStartingWithBOM() throws Exception {
     // Copied from test 'parseIncludeCode()' and added a BOM.
-    ProguardConfigurationParser parser;
-    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
     Path proguardConfig =
         writeTextToTempFile(StringUtils.BOM + "-keep,includecode class A { method(); }");
     byte[] bytes = Files.readAllBytes(proguardConfig);
@@ -2872,7 +2681,7 @@
     assertEquals(0xbb, Byte.toUnsignedLong(bytes[1]));
     assertEquals(0xbf, Byte.toUnsignedLong(bytes[2]));
     parser.parse(proguardConfig);
-    assertEquals(1, parser.getConfig().getRules().size());
+    assertEquals(1, builder.build().getRules().size());
     assertEquals(1, handler.infos.size());
     checkDiagnostics(handler.infos, proguardConfig, 1, 7, "Ignoring modifier", "includecode");
   }
@@ -2900,7 +2709,7 @@
                     + "class A { method(); }"
                     + whitespace1);
         parser.parse(proguardConfig);
-        assertEquals(1, parser.getConfig().getRules().size());
+        assertEquals(1, builder.build().getRules().size());
         assertEquals(1, handler.infos.size());
         // All BOSs except the leading are counted as input characters.
         checkDiagnostics(handler.infos, proguardConfig, 1, 0, "Ignoring modifier", "includecode");
@@ -2910,13 +2719,11 @@
 
   @Test
   public void backReferenceElimination() {
-    DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser = new ProguardConfigurationParser(dexItemFactory, reporter);
     String configuration = StringUtils.lines("-if class *.*.*", "-keep class <1>.<2>$<3>");
     parser.parse(createConfigurationForTesting(ImmutableList.of(configuration)));
     verifyParserEndsCleanly();
 
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(1, config.getRules().size());
 
     ProguardIfRule ifRule = (ProguardIfRule) config.getRules().iterator().next();
@@ -2943,8 +2750,7 @@
   public void parseCheckenumstringsdiscarded() throws Exception {
     Path proguardConfig =
         writeTextToTempFile("-checkenumstringsdiscarded @com.example.SomeAnnotation enum *");
-    ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(new DexItemFactory(), reporter);
+
     parser.parse(proguardConfig);
     verifyParserEndsCleanly();
   }
@@ -2976,13 +2782,11 @@
             "-keep @Foo public @Bar final class *",
             "-keep @Foo @Bar public final class *");
     for (String configurationContent : configurationContents) {
-      DexItemFactory dexItemFactory = new DexItemFactory();
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(dexItemFactory, reporter);
+      reset();
       parser.parse(createConfigurationForTesting(ImmutableList.of(configurationContent)));
       verifyParserEndsCleanly();
 
-      ProguardConfiguration configuration = parser.getConfig();
+      ProguardConfiguration configuration = builder.build();
       assertEquals(1, configuration.getRules().size());
 
       ProguardKeepRule rule = ListUtils.first(configuration.getRules()).asProguardKeepRule();
@@ -3050,9 +2854,7 @@
             .build();
     configurationContents.forEach(
         (configurationContent, expectedExceptionClass) -> {
-          DexItemFactory dexItemFactory = new DexItemFactory();
-          ProguardConfigurationParser parser =
-              new ProguardConfigurationParser(dexItemFactory, reporter);
+          reset();
           try {
             parser.parse(createConfigurationForTesting(ImmutableList.of(configurationContent)));
             assertFalse(expectedExceptionClass.isPresent());
@@ -3065,7 +2867,7 @@
 
           verifyParserEndsCleanly();
 
-          ProguardConfiguration configuration = parser.getConfig();
+          ProguardConfiguration configuration = builder.build();
           assertEquals(1, configuration.getRules().size());
 
           ProguardKeepRule rule = ListUtils.first(configuration.getRules()).asProguardKeepRule();
@@ -3141,9 +2943,7 @@
             .build();
     configurationContents.forEach(
         (configurationContent, expectedExceptionClass) -> {
-          DexItemFactory dexItemFactory = new DexItemFactory();
-          ProguardConfigurationParser parser =
-              new ProguardConfigurationParser(dexItemFactory, reporter);
+          reset();
           try {
             parser.parse(createConfigurationForTesting(ImmutableList.of(configurationContent)));
             assertFalse(expectedExceptionClass.isPresent());
@@ -3156,7 +2956,7 @@
 
           verifyParserEndsCleanly();
 
-          ProguardConfiguration configuration = parser.getConfig();
+          ProguardConfiguration configuration = builder.build();
           assertEquals(1, configuration.getRules().size());
 
           ProguardKeepRule rule = ListUtils.first(configuration.getRules()).asProguardKeepRule();
@@ -3189,9 +2989,7 @@
     for (String rule : ImmutableList.of("-keep", "-keepclassmembers", "-keepclasseswithmembers")) {
       for (String modifier :
           ImmutableList.of("", "names", ",allowshrinking", "names,allowshrinking")) {
-        DexItemFactory dexItemFactory = new DexItemFactory();
-        ProguardConfigurationParser parser =
-            new ProguardConfigurationParser(dexItemFactory, reporter);
+        reset();
         String ruleWithModifier =
             (rule.endsWith("s") && (!modifier.startsWith(",") && !modifier.isEmpty())
                     ? rule.substring(0, rule.length() - 1)
@@ -3201,7 +2999,7 @@
             createConfigurationForTesting(ImmutableList.of(ruleWithModifier + " class A")));
         verifyParserEndsCleanly();
 
-        ProguardConfiguration configuration = parser.getConfig();
+        ProguardConfiguration configuration = builder.build();
         assertEquals(1, configuration.getRules().size());
         assertEquals(
             !modifier.isEmpty(),
@@ -3215,13 +3013,11 @@
 
   @Test
   public void parseMaximumRemovedAndroidLogLevelWithoutClassSpecification() {
-    DexItemFactory dexItemFactory = new DexItemFactory();
-    ProguardConfigurationParser parser = new ProguardConfigurationParser(dexItemFactory, reporter);
     String configuration = StringUtils.lines("-maximumremovedandroidloglevel 2");
     parser.parse(createConfigurationForTesting(ImmutableList.of(configuration)));
     verifyParserEndsCleanly();
 
-    ProguardConfiguration config = parser.getConfig();
+    ProguardConfiguration config = builder.build();
     assertEquals(MaximumRemovedAndroidLogLevelRule.VERBOSE, config.getMaxRemovedAndroidLogLevel());
     assertEquals(0, config.getRules().size());
   }
@@ -3233,14 +3029,12 @@
           "-maximumremovedandroidloglevel 2 class * { <methods>; }",
           "-maximumremovedandroidloglevel 2 @Foo class * { <methods>; }"
         }) {
-      DexItemFactory dexItemFactory = new DexItemFactory();
-      ProguardConfigurationParser parser =
-          new ProguardConfigurationParser(dexItemFactory, reporter);
+      reset();
       String configuration = StringUtils.lines(input);
       parser.parse(createConfigurationForTesting(ImmutableList.of(configuration)));
       verifyParserEndsCleanly();
 
-      ProguardConfiguration config = parser.getConfig();
+      ProguardConfiguration config = builder.build();
       assertEquals(
           MaximumRemovedAndroidLogLevelRule.NOT_SET, config.getMaxRemovedAndroidLogLevel());
       assertEquals(1, config.getRules().size());
diff --git a/src/test/testbase/java/com/android/tools/r8/ToolHelper.java b/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
index cc057b1..268a9e0 100644
--- a/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
@@ -1693,8 +1693,9 @@
   public static ProguardConfiguration loadProguardConfiguration(
       DexItemFactory factory, List<Path> configPaths) {
     Reporter reporter = new Reporter();
+    ProguardConfiguration.Builder builder = ProguardConfiguration.builder(factory, reporter);
     if (configPaths.isEmpty()) {
-      return ProguardConfiguration.builder(factory, reporter)
+      return builder
           .disableShrinking()
           .disableObfuscation()
           .disableOptimization()
@@ -1702,11 +1703,11 @@
           .build();
     }
     ProguardConfigurationParser parser =
-        new ProguardConfigurationParser(factory, reporter);
+        new ProguardConfigurationParser(factory, reporter, builder);
     for (Path configPath : configPaths) {
       parser.parse(configPath);
     }
-    return parser.getConfig();
+    return builder.build();
   }
 
   public static D8Command.Builder prepareD8CommandBuilder(AndroidApp app) {