Remove internal options from AppView.

Change-Id: I71e6d3db4d5908ee3c7a23265d6b4050c0119d72
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index c40d755..b456ecb 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -187,7 +187,7 @@
             executor);
       }
 
-      AppView<?> appView = AppView.createForD8(appInfo, options, rewritePrefix);
+      AppView<?> appView = AppView.createForD8(appInfo, rewritePrefix);
 
       IRConverter converter = new IRConverter(appView, timing, printer);
       app = converter.convert(app, executor);
@@ -354,7 +354,7 @@
       throws IOException, ExecutionException {
     final CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
 
-    IRConverter converter = new IRConverter(appInfo, options, timing, printer);
+    IRConverter converter = new IRConverter(appInfo, timing, printer);
     application = converter.convert(application, executor);
 
     if (options.printCfg) {
diff --git a/src/main/java/com/android/tools/r8/GenerateLintFiles.java b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
index dcf33f1..bbee24d 100644
--- a/src/main/java/com/android/tools/r8/GenerateLintFiles.java
+++ b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
@@ -312,7 +312,7 @@
 
     // Write a header jar with the desugared APIs.
     AppInfo appInfo = new AppInfo(app);
-    AppView<?> appView = AppView.createForD8(appInfo, options);
+    AppView<?> appView = AppView.createForD8(appInfo);
     CfApplicationWriter writer =
         new CfApplicationWriter(
             builder.build(),
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index 42290d2..bacd375 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -50,7 +50,7 @@
       DirectMappedDexApplication application =
           new ApplicationReader(app, options, timing).read(executor).toDirect();
       AppView<? extends AppInfoWithClassHierarchy> appView =
-          AppView.createForR8(new AppInfoWithClassHierarchy(application), options);
+          AppView.createForR8(new AppInfoWithClassHierarchy(application));
       appView.setAppServices(AppServices.builder(appView).build());
 
       MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index 4b35d17..f5059e4 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -128,7 +128,7 @@
       DexApplication app = new L8TreePruner(options).prune(lazyApp, rewritePrefix);
       AppInfo appInfo = new AppInfo(app);
 
-      AppView<?> appView = AppView.createForL8(appInfo, options, rewritePrefix);
+      AppView<?> appView = AppView.createForL8(appInfo, rewritePrefix);
       IRConverter converter = new IRConverter(appView, timing);
 
       if (!options.testing.disableL8AnnotationRemoval) {
diff --git a/src/main/java/com/android/tools/r8/PrintSeeds.java b/src/main/java/com/android/tools/r8/PrintSeeds.java
index 7c2302a..3f8b70e 100644
--- a/src/main/java/com/android/tools/r8/PrintSeeds.java
+++ b/src/main/java/com/android/tools/r8/PrintSeeds.java
@@ -88,7 +88,7 @@
       DirectMappedDexApplication application =
           new ApplicationReader(command.getInputApp(), options, timing).read(executor).toDirect();
       AppView<? extends AppInfoWithClassHierarchy> appView =
-          AppView.createForR8(new AppInfoWithClassHierarchy(application), options);
+          AppView.createForR8(new AppInfoWithClassHierarchy(application));
       appView.setAppServices(AppServices.builder(appView).build());
       SubtypingInfo subtypingInfo = new SubtypingInfo(application.allClasses(), application);
       RootSet rootSet =
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 2c07cbf..24bbae5 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -279,7 +279,7 @@
       inputApp.closeInternalArchiveProviders();
 
       AppView<AppInfoWithClassHierarchy> appView =
-          AppView.createForR8(new AppInfoWithClassHierarchy(application), options);
+          AppView.createForR8(new AppInfoWithClassHierarchy(application));
       appView.setAppServices(AppServices.builder(appView).build());
 
       // Check for potentially having pass-through of Cf-code for kotlin libraries.
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 9763f50..3adb81d 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -43,11 +43,9 @@
   private T appInfo;
   private AppInfoWithClassHierarchy appInfoForDesugaring;
   private AppServices appServices;
-  private final DexItemFactory dexItemFactory;
   private final WholeProgramOptimizations wholeProgramOptimizations;
   private GraphLense graphLense;
   private InitClassLens initClassLens;
-  private final InternalOptions options;
   private RootSet rootSet;
   private final AbstractValueFactory abstractValueFactory = new AbstractValueFactory();
   private final InstanceFieldInitializationInfoFactory instanceFieldInitializationInfoFactory =
@@ -74,32 +72,19 @@
   private Map<DexClass, DexValueString> sourceDebugExtensions = new IdentityHashMap<>();
 
   private AppView(
-      T appInfo, WholeProgramOptimizations wholeProgramOptimizations, InternalOptions options) {
-    this(
-        appInfo,
-        wholeProgramOptimizations,
-        options,
-        appInfo == null
-            ? PrefixRewritingMapper.empty()
-            : options.desugaredLibraryConfiguration.createPrefixRewritingMapper(options));
-  }
-
-  private AppView(
       T appInfo,
       WholeProgramOptimizations wholeProgramOptimizations,
-      InternalOptions options,
       PrefixRewritingMapper mapper) {
+    assert appInfo != null;
     this.appInfo = appInfo;
-    this.dexItemFactory = appInfo != null ? appInfo.dexItemFactory() : null;
     this.wholeProgramOptimizations = wholeProgramOptimizations;
     this.graphLense = GraphLense.getIdentityLense();
     this.initClassLens = InitClassLens.getDefault();
     this.methodProcessingIdFactory =
-        new MethodProcessingId.Factory(options.testing.methodProcessingIdConsumer);
-    this.options = options;
+        new MethodProcessingId.Factory(options().testing.methodProcessingIdConsumer);
     this.rewritePrefix = mapper;
 
-    if (enableWholeProgramOptimizations() && options.callSiteOptimizationOptions().isEnabled()) {
+    if (enableWholeProgramOptimizations() && options().callSiteOptimizationOptions().isEnabled()) {
       this.callSiteOptimizationInfoPropagator =
           new CallSiteOptimizationInfoPropagator(withLiveness());
     } else {
@@ -108,7 +93,7 @@
 
     this.libraryMemberOptimizer = new LibraryMemberOptimizer(this);
 
-    if (enableWholeProgramOptimizations() && options.protoShrinking().isProtoShrinkingEnabled()) {
+    if (enableWholeProgramOptimizations() && options().protoShrinking().isProtoShrinkingEnabled()) {
       this.protoShrinker = new ProtoShrinker(withLiveness());
     } else {
       this.protoShrinker = null;
@@ -120,27 +105,34 @@
     return libraryMemberOptimizer.isModeled(type);
   }
 
-  public static <T extends AppInfo> AppView<T> createForD8(T appInfo, InternalOptions options) {
-    return new AppView<>(appInfo, WholeProgramOptimizations.OFF, options);
+  private static <T extends AppInfo> PrefixRewritingMapper defaultPrefixRewritingMapper(T appInfo) {
+    InternalOptions options = appInfo.options();
+    return options.desugaredLibraryConfiguration.createPrefixRewritingMapper(options);
+  }
+
+  public static <T extends AppInfo> AppView<T> createForD8(T appInfo) {
+    return new AppView<>(
+        appInfo, WholeProgramOptimizations.OFF, defaultPrefixRewritingMapper(appInfo));
   }
 
   public static <T extends AppInfo> AppView<T> createForD8(
-      T appInfo, InternalOptions options, PrefixRewritingMapper mapper) {
-    return new AppView<>(appInfo, WholeProgramOptimizations.OFF, options, mapper);
+      T appInfo, PrefixRewritingMapper mapper) {
+    return new AppView<>(appInfo, WholeProgramOptimizations.OFF, mapper);
   }
 
-  public static <T extends AppInfo> AppView<T> createForR8(T appInfo, InternalOptions options) {
-    return new AppView<>(appInfo, WholeProgramOptimizations.ON, options);
+  public static <T extends AppInfo> AppView<T> createForR8(T appInfo) {
+    return new AppView<>(
+        appInfo, WholeProgramOptimizations.ON, defaultPrefixRewritingMapper(appInfo));
   }
 
   public static <T extends AppInfo> AppView<T> createForL8(
-      T appInfo, InternalOptions options, PrefixRewritingMapper mapper) {
-    return new AppView<>(appInfo, WholeProgramOptimizations.OFF, options, mapper);
+      T appInfo, PrefixRewritingMapper mapper) {
+    return new AppView<>(appInfo, WholeProgramOptimizations.OFF, mapper);
   }
 
-  public static <T extends AppInfo> AppView<T> createForRelocator(
-      T appInfo, InternalOptions options) {
-    return new AppView<>(appInfo, WholeProgramOptimizations.OFF, options);
+  public static <T extends AppInfo> AppView<T> createForRelocator(T appInfo) {
+    return new AppView<>(
+        appInfo, WholeProgramOptimizations.OFF, defaultPrefixRewritingMapper(appInfo));
   }
 
   public AbstractValueFactory abstractValueFactory() {
@@ -252,7 +244,7 @@
 
   @Override
   public DexItemFactory dexItemFactory() {
-    return dexItemFactory;
+    return appInfo.dexItemFactory();
   }
 
   public boolean enableWholeProgramOptimizations() {
@@ -344,7 +336,7 @@
   }
 
   public boolean canUseInitClass() {
-    return options.isShrinking() && !initClassLens.isFinal();
+    return options().isShrinking() && !initClassLens.isFinal();
   }
 
   public InitClassLens initClassLens() {
@@ -373,7 +365,7 @@
   }
 
   public InternalOptions options() {
-    return options;
+    return appInfo.options();
   }
 
   public RootSet rootSet() {
@@ -455,14 +447,14 @@
   }
 
   public boolean isCfByteCodePassThrough(DexEncodedMethod method) {
-    if (!options.isGeneratingClassFiles()) {
+    if (!options().isGeneratingClassFiles()) {
       return false;
     }
     if (cfByteCodePassThrough.contains(method.method)) {
       return true;
     }
-    return options.testing.cfByteCodePassThrough != null
-        && options.testing.cfByteCodePassThrough.test(method.method);
+    return options().testing.cfByteCodePassThrough != null
+        && options().testing.cfByteCodePassThrough.test(method.method);
   }
 
   public boolean hasCfByteCodePassThroughMethods() {
diff --git a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
index 1315f4a..3cd5fc5 100644
--- a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
+++ b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
@@ -140,7 +140,7 @@
 
   private void writeIR(ProgramMethod method, PrintStream ps) {
     CfgPrinter printer = new CfgPrinter();
-    IRConverter converter = new IRConverter(appInfo, options, timing, printer);
+    IRConverter converter = new IRConverter(appInfo, timing, printer);
     OneTimeMethodProcessor methodProcessor =
         OneTimeMethodProcessor.create(method, methodProcessingIdFactory);
     methodProcessor.forEachWave(
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 5f6f83b..0809d00 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -372,8 +372,8 @@
     this(appView, timing, printer, MainDexClasses.NONE);
   }
 
-  public IRConverter(AppInfo appInfo, InternalOptions options, Timing timing, CfgPrinter printer) {
-    this(AppView.createForD8(appInfo, options), timing, printer, MainDexClasses.NONE);
+  public IRConverter(AppInfo appInfo, Timing timing, CfgPrinter printer) {
+    this(AppView.createForD8(appInfo), timing, printer, MainDexClasses.NONE);
   }
 
   private boolean enableTwrCloseResourceDesugaring() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index c0cdc54..fbf5a15 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -107,7 +107,7 @@
           new ApplicationReader(androidApp, options, Timing.empty()).read(executor);
       appInfo = new AppInfo(app);
     }
-    AppView<?> appView = AppView.createForD8(appInfo, options, rewritePrefix);
+    AppView<?> appView = AppView.createForD8(appInfo, rewritePrefix);
     BackportedMethodRewriter.RewritableMethods rewritableMethods =
         new BackportedMethodRewriter.RewritableMethods(options, appView);
     rewritableMethods.visit(methods::add);
diff --git a/src/main/java/com/android/tools/r8/relocator/Relocator.java b/src/main/java/com/android/tools/r8/relocator/Relocator.java
index 1e8420e..176e058 100644
--- a/src/main/java/com/android/tools/r8/relocator/Relocator.java
+++ b/src/main/java/com/android/tools/r8/relocator/Relocator.java
@@ -81,7 +81,7 @@
       DexApplication app = new ApplicationReader(inputApp, options, timing).read(executor);
 
       AppInfo appInfo = new AppInfo(app);
-      AppView<?> appView = AppView.createForRelocator(appInfo, options);
+      AppView<?> appView = AppView.createForRelocator(appInfo);
       appView.setAppServices(AppServices.builder(appView).build());
 
       SimplePackagesRewritingMapper packageRemapper = new SimplePackagesRewritingMapper(appView);
diff --git a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
index 846bc6b..2c53667 100644
--- a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
+++ b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
@@ -6,7 +6,6 @@
 import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
 import static org.junit.Assert.assertEquals;
 
-import com.android.tools.r8.TestRuntime.NoneRuntime;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.FileUtils;
@@ -32,7 +31,7 @@
   }
 
   public D8ApiBinaryCompatibilityTests(TestParameters parameters) {
-    assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+    parameters.assertNoneRuntime();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
index 954d773..ac3d89f 100644
--- a/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
+++ b/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
@@ -6,7 +6,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import com.android.tools.r8.TestRuntime.NoneRuntime;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.FileUtils;
@@ -35,7 +34,7 @@
   }
 
   public R8ApiBinaryCompatibilityTests(TestParameters parameters) {
-    assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+    parameters.assertNoneRuntime();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
index 2daa0a9..e30b788 100644
--- a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
+++ b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
@@ -44,8 +44,7 @@
     DirectMappedDexApplication application =
         new ApplicationReader(input, options, timing).read(executorService).toDirect();
     IRConverter converter =
-        new IRConverter(
-            AppView.createForR8(new AppInfoWithClassHierarchy(application), options), null);
+        new IRConverter(AppView.createForR8(new AppInfoWithClassHierarchy(application)), null);
     converter.optimize();
     DexProgramClass clazz = application.classes().iterator().next();
     assertEquals(4, clazz.getMethodCollection().numberOfDirectMethods());
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index b3988d4..78eaabf 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -47,6 +47,7 @@
 import com.android.tools.r8.shaking.EnqueuerFactory;
 import com.android.tools.r8.shaking.ProguardClassFilter;
 import com.android.tools.r8.shaking.ProguardClassNameList;
+import com.android.tools.r8.shaking.ProguardConfiguration;
 import com.android.tools.r8.shaking.ProguardConfigurationRule;
 import com.android.tools.r8.shaking.ProguardKeepRule;
 import com.android.tools.r8.shaking.ProguardKeepRule.Builder;
@@ -66,6 +67,7 @@
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.PreloadedClassFileProvider;
+import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.TestDescriptionWatcher;
 import com.android.tools.r8.utils.Timing;
@@ -574,35 +576,40 @@
     return newJar;
   }
 
-  protected static AppInfo computeAppInfo(AndroidApp application) {
-    try {
-      DexApplication dexApplication =
-          new ApplicationReader(application, new InternalOptions(), Timing.empty()).read();
-      return new AppInfo(dexApplication);
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
+  private static DexApplication readApplicationForDexOutput(AndroidApp app, InternalOptions options)
+      throws Exception {
+    assert options.programConsumer == null;
+    options.programConsumer = DexIndexedConsumer.emptyConsumer();
+    return new ApplicationReader(app, options, Timing.empty()).read();
   }
 
-  protected static AppInfoWithClassHierarchy computeAppInfoWithClassHierarchy(
-      AndroidApp application) {
-    try {
-      DexApplication dexApplication =
-          new ApplicationReader(application, new InternalOptions(), Timing.empty()).read();
-      return new AppInfoWithClassHierarchy(dexApplication);
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
+  protected static AppView<AppInfo> computeAppView(AndroidApp app) throws Exception {
+    AppInfo appInfo = new AppInfo(readApplicationForDexOutput(app, new InternalOptions()));
+    return AppView.createForD8(appInfo);
+  }
+
+  protected static AppInfoWithClassHierarchy computeAppInfoWithClassHierarchy(AndroidApp app)
+      throws Exception {
+    return new AppInfoWithClassHierarchy(readApplicationForDexOutput(app, new InternalOptions()));
   }
 
   protected static AppView<AppInfoWithClassHierarchy> computeAppViewWithSubtyping(AndroidApp app)
       throws Exception {
-    Timing timing = Timing.empty();
-    InternalOptions options = new InternalOptions();
-    DirectMappedDexApplication application =
-        new ApplicationReader(app, options, timing).read().toDirect();
+    return computeAppViewWithSubtyping(
+        app,
+        factory ->
+            buildConfigForRules(
+                factory,
+                Collections.singletonList(ProguardKeepRule.defaultKeepAllRule(unused -> {}))));
+  }
+
+  private static AppView<AppInfoWithClassHierarchy> computeAppViewWithSubtyping(
+      AndroidApp app, Function<DexItemFactory, ProguardConfiguration> keepConfig) throws Exception {
+    DexItemFactory dexItemFactory = new DexItemFactory();
+    InternalOptions options = new InternalOptions(keepConfig.apply(dexItemFactory), new Reporter());
+    DexApplication dexApplication = readApplicationForDexOutput(app, options);
     AppView<AppInfoWithClassHierarchy> appView =
-        AppView.createForR8(new AppInfoWithClassHierarchy(application), options);
+        AppView.createForR8(new AppInfoWithClassHierarchy(dexApplication.toDirect()));
     appView.setAppServices(AppServices.builder(appView).build());
     return appView;
   }
@@ -610,31 +617,32 @@
   protected static AppView<AppInfoWithLiveness> computeAppViewWithLiveness(AndroidApp app)
       throws Exception {
     return computeAppViewWithLiveness(
-        app, factory -> ImmutableList.of(ProguardKeepRule.defaultKeepAllRule(unused -> {})));
+        app,
+        factory ->
+            buildConfigForRules(
+                factory, ImmutableList.of(ProguardKeepRule.defaultKeepAllRule(unused -> {}))));
   }
 
   protected static AppView<AppInfoWithLiveness> computeAppViewWithLiveness(
       AndroidApp app, Class<?> mainClass) throws Exception {
     return computeAppViewWithLiveness(
-        app, factory -> buildKeepRuleForClassAndMethods(mainClass, factory));
+        app,
+        factory ->
+            buildConfigForRules(factory, buildKeepRuleForClassAndMethods(mainClass, factory)));
   }
 
   protected static AppView<AppInfoWithLiveness> computeAppViewWithLiveness(
-      AndroidApp app,
-      Function<DexItemFactory, Collection<ProguardConfigurationRule>>
-          proguardConfigurationRulesGenerator)
-      throws Exception {
-    AppView<AppInfoWithClassHierarchy> appView = computeAppViewWithSubtyping(app);
+      AndroidApp app, Function<DexItemFactory, ProguardConfiguration> keepConfig) throws Exception {
+    AppView<AppInfoWithClassHierarchy> appView = computeAppViewWithSubtyping(app, keepConfig);
     // Run the tree shaker to compute an instance of AppInfoWithLiveness.
     ExecutorService executor = Executors.newSingleThreadExecutor();
     DirectMappedDexApplication application = appView.appInfo().app().asDirect();
     SubtypingInfo subtypingInfo = new SubtypingInfo(application.allClasses(), application);
     RootSet rootSet =
         new RootSetBuilder(
-                appView,
-                subtypingInfo,
-                proguardConfigurationRulesGenerator.apply(appView.appInfo().dexItemFactory()))
+                appView, subtypingInfo, application.options.getProguardConfiguration().getRules())
             .run(executor);
+    appView.setRootSet(rootSet);
     AppInfoWithLiveness appInfoWithLiveness =
         EnqueuerFactory.createForInitialTreeShaking(appView, subtypingInfo)
             .traceApplication(rootSet, ProguardClassFilter.empty(), executor, application.timing);
@@ -714,6 +722,18 @@
     return Collections.singletonList(keepRuleBuilder.build());
   }
 
+  protected static ProguardConfiguration buildConfigForRules(
+      DexItemFactory factory, Collection<ProguardConfigurationRule> rules) {
+    return buildConfigForRules(factory, new Reporter(), rules);
+  }
+
+  protected static ProguardConfiguration buildConfigForRules(
+      DexItemFactory factory, Reporter reporter, Collection<ProguardConfigurationRule> rules) {
+    ProguardConfiguration.Builder builder = ProguardConfiguration.builder(factory, reporter);
+    rules.forEach(builder::addRule);
+    return builder.build();
+  }
+
   /** Returns a list containing all the data resources in the given app. */
   public static List<DataEntryResource> getDataResources(AndroidApp app) throws ResourceException {
     List<DataEntryResource> dataResources = new ArrayList<>();
diff --git a/src/test/java/com/android/tools/r8/TestParameters.java b/src/test/java/com/android/tools/r8/TestParameters.java
index d886efb..75b7336 100644
--- a/src/test/java/com/android/tools/r8/TestParameters.java
+++ b/src/test/java/com/android/tools/r8/TestParameters.java
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8;
 
+import static org.junit.Assert.assertEquals;
+
 import com.android.tools.r8.TestBase.Backend;
 import com.android.tools.r8.TestRuntime.NoneRuntime;
 import com.android.tools.r8.utils.AndroidApiLevel;
@@ -70,4 +72,8 @@
     }
     return runtime.toString();
   }
+
+  public void assertNoneRuntime() {
+    assertEquals(NoneRuntime.getInstance(), runtime);
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/bisect/BisectTest.java b/src/test/java/com/android/tools/r8/bisect/BisectTest.java
index 28ecca3..bd1d3c4 100644
--- a/src/test/java/com/android/tools/r8/bisect/BisectTest.java
+++ b/src/test/java/com/android/tools/r8/bisect/BisectTest.java
@@ -37,10 +37,8 @@
     return TestParametersBuilder.builder().withNoneRuntime().build();
   }
 
-  private final TestParameters parameters;
-
   public BisectTest(TestParameters parameters) {
-    this.parameters = parameters;
+    parameters.assertNoneRuntime();
   }
 
   private final String[] CLASSES = {"A", "B", "C", "D", "E", "F", "G", "H"};
diff --git a/src/test/java/com/android/tools/r8/classmerging/KeptTargetsIncompleteDiamondTest.java b/src/test/java/com/android/tools/r8/classmerging/KeptTargetsIncompleteDiamondTest.java
index c27b55b..8866342 100644
--- a/src/test/java/com/android/tools/r8/classmerging/KeptTargetsIncompleteDiamondTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/KeptTargetsIncompleteDiamondTest.java
@@ -19,10 +19,9 @@
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.ProguardConfigurationRule;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -45,13 +44,14 @@
       Class<?> methodToBeKept, Class<?> classToBeKept) throws Exception {
     return computeAppViewWithLiveness(
         buildClasses(I.class, J.class, K.class, L.class, A.class, Main.class).build(),
-        factory -> {
-          List<ProguardConfigurationRule> rules = new ArrayList<>();
-          rules.addAll(buildKeepRuleForClassAndMethods(methodToBeKept, factory));
-          rules.addAll(buildKeepRuleForClass(classToBeKept, factory));
-          rules.addAll(buildKeepRuleForClassAndMethods(Main.class, factory));
-          return rules;
-        });
+        factory ->
+            buildConfigForRules(
+                factory,
+                ImmutableList.<ProguardConfigurationRule>builder()
+                    .addAll(buildKeepRuleForClassAndMethods(methodToBeKept, factory))
+                    .addAll(buildKeepRuleForClass(classToBeKept, factory))
+                    .addAll(buildKeepRuleForClassAndMethods(Main.class, factory))
+                    .build()));
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java
index 54f3acb..6b46ee4 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java
@@ -7,7 +7,6 @@
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestRuntime.NoneRuntime;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.google.common.collect.ImmutableList;
@@ -33,7 +32,7 @@
   private final String release;
 
   public BackwardsCompatibleSpecificationTest(TestParameters parameters, String release) {
-    assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+    parameters.assertNoneRuntime();
     this.release = release;
   }
 
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java
index 3e819e2..8280f92 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java
@@ -5,7 +5,6 @@
 
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.CompilationMode;
@@ -16,7 +15,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.TestRuntime.NoneRuntime;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.utils.AndroidApiLevel;
@@ -36,7 +34,7 @@
   }
 
   public DesugaredLibaryChecksumsTest(TestParameters parameters) {
-    assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+    parameters.assertNoneRuntime();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
index 07c0703..1141cb3 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
@@ -17,7 +17,6 @@
 import com.android.tools.r8.TestDiagnosticMessagesImpl;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.TestRuntime.NoneRuntime;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
@@ -52,7 +51,7 @@
   }
 
   public DesugaredLibraryConfigurationParsingTest(TestParameters parameters) {
-    assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+    parameters.assertNoneRuntime();
   }
 
   final AndroidApiLevel minApi = AndroidApiLevel.B;
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java
index 1d66c7f..5f323bc 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java
@@ -5,11 +5,9 @@
 
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.TestRuntime.NoneRuntime;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import java.util.Arrays;
 import java.util.function.Consumer;
@@ -28,7 +26,7 @@
   final AndroidApiLevel minApiLevel = AndroidApiLevel.B;
 
   public DontKeepBootstrapClassesTest(TestParameters parameters) {
-    assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+    parameters.assertNoneRuntime();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
index 846b65d..2225ceb 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.TestRuntime.NoneRuntime;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
@@ -99,7 +98,7 @@
   private final AndroidApiLevel targetApi = AndroidApiLevel.Q;
 
   public ExtractWrapperTypesTest(TestParameters parameters) {
-    assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+    parameters.assertNoneRuntime();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java b/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
index 9c86160..7d22782 100644
--- a/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
@@ -9,7 +9,8 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.ToolHelper.ProcessResult;
@@ -30,11 +31,24 @@
 import java.nio.file.Path;
 import java.util.Collections;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class TargetLookupTest extends SmaliTestBase {
 
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  public TargetLookupTest(TestParameters parameters) {
+    parameters.assertNoneRuntime();
+  }
+
   @Test
-  public void lookupDirect() {
+  public void lookupDirect() throws Exception {
     SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
 
     builder.addDefaultConstructor();
@@ -100,7 +114,7 @@
   }
 
   @Test
-  public void lookupDirectSuper() {
+  public void lookupDirectSuper() throws Exception {
     SmaliBuilder builder = new SmaliBuilder("TestSuper");
 
     builder.addDefaultConstructor();
@@ -185,7 +199,7 @@
   }
 
   @Test
-  public void lookupFieldWithDefaultInInterface() throws CompilationFailedException {
+  public void lookupFieldWithDefaultInInterface() throws Exception {
     SmaliBuilder builder = new SmaliBuilder();
 
     builder.addInterface("Interface");
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
index 5048226..ca35303 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
@@ -60,7 +60,7 @@
             .read(proguardMap, executorService)
             .toDirect();
     InternalOptions options = new InternalOptions();
-    appView = AppView.createForR8(new AppInfoWithClassHierarchy(program), options);
+    appView = AppView.createForR8(new AppInfoWithClassHierarchy(program));
     appView.setAppServices(AppServices.builder(appView).build());
     subtypingInfo = new SubtypingInfo(program.allClasses(), program);
   }
diff --git a/src/test/java/com/android/tools/r8/internal/proto/ProtoShrinkingTestBase.java b/src/test/java/com/android/tools/r8/internal/proto/ProtoShrinkingTestBase.java
index 79ce685..23d12f6 100644
--- a/src/test/java/com/android/tools/r8/internal/proto/ProtoShrinkingTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/proto/ProtoShrinkingTestBase.java
@@ -115,7 +115,7 @@
           continue;
         }
 
-        IRCode code = methodSubject.buildIR(dexItemFactory);
+        IRCode code = methodSubject.buildIR();
         InvokeMethod invoke =
             GeneratedMessageLiteShrinker.getNewMessageInfoInvoke(code, references);
         assert invoke != null;
diff --git a/src/test/java/com/android/tools/r8/ir/BasicBlockIteratorTest.java b/src/test/java/com/android/tools/r8/ir/BasicBlockIteratorTest.java
index 586129b..04c8788 100644
--- a/src/test/java/com/android/tools/r8/ir/BasicBlockIteratorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/BasicBlockIteratorTest.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir;
 
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppView;
@@ -24,11 +26,25 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class BasicBlockIteratorTest extends SmaliTestBase {
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
   @Rule
   public ExpectedException thrown = ExpectedException.none();
 
+  public BasicBlockIteratorTest(TestParameters parameters) {
+    parameters.assertNoneRuntime();
+  }
+
   /**
    * Simple test IR, which has three blocks:
    *
@@ -55,7 +71,7 @@
     InternalOptions options = new InternalOptions();
     DexApplication dexApplication =
         new ApplicationReader(application, options, Timing.empty()).read();
-    AppView<?> appView = AppView.createForD8(new AppInfo(dexApplication), options);
+    AppView<?> appView = AppView.createForD8(new AppInfo(dexApplication));
 
     // Build the code, and split the code into three blocks.
     MethodSubject methodSubject = getMethodSubject(application, signature);
diff --git a/src/test/java/com/android/tools/r8/ir/InlineTest.java b/src/test/java/com/android/tools/r8/ir/InlineTest.java
index a2246c0..2bd2803 100644
--- a/src/test/java/com/android/tools/r8/ir/InlineTest.java
+++ b/src/test/java/com/android/tools/r8/ir/InlineTest.java
@@ -6,6 +6,9 @@
 
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
@@ -40,9 +43,22 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class InlineTest extends IrInjectionTestBase {
 
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  public InlineTest(TestParameters parameters) {
+    parameters.assertNoneRuntime();
+  }
+
   private TestApplication buildTestApplication(
       DexApplication application,
       InternalOptions options,
@@ -51,7 +67,7 @@
       throws ExecutionException {
     DirectMappedDexApplication directApp = application.asDirect();
     AppView<AppInfoWithClassHierarchy> appView =
-        AppView.createForR8(new AppInfoWithClassHierarchy(directApp), options);
+        AppView.createForR8(new AppInfoWithClassHierarchy(directApp));
     appView.setAppServices(AppServices.builder(appView).build());
     ExecutorService executorService = ThreadUtils.getExecutorService(options);
     SubtypingInfo subtypingInfo = new SubtypingInfo(directApp.allClasses(), directApp);
@@ -73,7 +89,9 @@
     Reporter reporter = new Reporter();
     ProguardConfiguration proguardConfiguration =
         ProguardConfiguration.builder(new DexItemFactory(), reporter).build();
-    return new InternalOptions(proguardConfiguration, reporter);
+    InternalOptions options = new InternalOptions(proguardConfiguration, reporter);
+    options.programConsumer = DexIndexedConsumer.emptyConsumer();
+    return options;
   }
 
   private TestApplication codeForMethodReplaceTest(int a, int b) throws ExecutionException {
@@ -129,10 +147,10 @@
     MethodSubject methodSubject = getMethodSubject(application, signature);
 
     MethodSubject methodASubject = getMethodSubject(application, signatureA);
-    IRCode codeA = methodASubject.buildIR(options.itemFactory);
+    IRCode codeA = methodASubject.buildIR();
 
     MethodSubject methodBSubject = getMethodSubject(application, signatureB);
-    IRCode codeB = methodBSubject.buildIR(options.itemFactory);
+    IRCode codeB = methodBSubject.buildIR();
 
     return buildTestApplication(
         application, options, methodSubject, ImmutableList.of(codeA, codeB));
@@ -211,7 +229,7 @@
     MethodSubject methodSubject = getMethodSubject(application, signature);
 
     MethodSubject methodASubject = getMethodSubject(application, signatureA);
-    IRCode codeA = methodASubject.buildIR(options.itemFactory);
+    IRCode codeA = methodASubject.buildIR();
 
     return buildTestApplication(application, options, methodSubject, ImmutableList.of(codeA));
   }
@@ -291,13 +309,13 @@
     List<IRCode> additionalCode = new ArrayList<>();
     for (int i = 0; i < 3; i++) {
       MethodSubject methodASubject = getMethodSubject(application, signatureA);
-      IRCode codeA = methodASubject.buildIR(options.itemFactory);
+      IRCode codeA = methodASubject.buildIR();
       additionalCode.add(codeA);
     }
 
     for (int i = 0; i < 3; i++) {
       MethodSubject methodBSubject = getMethodSubject(application, signatureB);
-      IRCode codeB = methodBSubject.buildIR(options.itemFactory);
+      IRCode codeB = methodBSubject.buildIR();
       additionalCode.add(codeB);
     }
 
@@ -421,10 +439,10 @@
     MethodSubject methodSubject = getMethodSubject(application, signature);
 
     MethodSubject methodASubject = getMethodSubject(application, signatureA);
-    IRCode codeA = methodASubject.buildIR(options.itemFactory);
+    IRCode codeA = methodASubject.buildIR();
 
     MethodSubject methodBSubject = getMethodSubject(application, signatureB);
-    IRCode codeB = methodBSubject.buildIR(options.itemFactory);
+    IRCode codeB = methodBSubject.buildIR();
 
     return buildTestApplication(
         application, options, methodSubject, ImmutableList.of(codeA, codeB));
@@ -534,10 +552,10 @@
     MethodSubject methodSubject = getMethodSubject(application, signature);
 
     MethodSubject methodASubject = getMethodSubject(application, signatureA);
-    IRCode codeA = methodASubject.buildIR(options.itemFactory);
+    IRCode codeA = methodASubject.buildIR();
 
     MethodSubject methodBSubject = getMethodSubject(application, signatureB);
-    IRCode codeB = methodBSubject.buildIR(options.itemFactory);
+    IRCode codeB = methodBSubject.buildIR();
 
     return buildTestApplication(
         application, options, methodSubject, ImmutableList.of(codeA, codeB));
@@ -645,10 +663,10 @@
     MethodSubject methodSubject = getMethodSubject(application, signature);
 
     MethodSubject methodASubject = getMethodSubject(application, signatureA);
-    IRCode codeA = methodASubject.buildIR(options.itemFactory);
+    IRCode codeA = methodASubject.buildIR();
 
     MethodSubject methodBSubject = getMethodSubject(application, signatureB);
-    IRCode codeB = methodBSubject.buildIR(options.itemFactory);
+    IRCode codeB = methodBSubject.buildIR();
 
     return buildTestApplication(
         application, options, methodSubject, ImmutableList.of(codeA, codeB));
@@ -761,13 +779,13 @@
     List<IRCode> additionalCode = new ArrayList<>();
     for (int i = 0; i < 3; i++) {
       MethodSubject methodASubject = getMethodSubject(application, signatureA);
-      IRCode codeA = methodASubject.buildIR(options.itemFactory);
+      IRCode codeA = methodASubject.buildIR();
       additionalCode.add(codeA);
     }
 
     for (int i = 0; i < 3; i++) {
       MethodSubject methodBSubject = getMethodSubject(application, signatureB);
-      IRCode codeB = methodBSubject.buildIR(options.itemFactory);
+      IRCode codeB = methodBSubject.buildIR();
       additionalCode.add(codeB);
     }
 
@@ -917,13 +935,13 @@
     List<IRCode> additionalCode = new ArrayList<>();
     for (int i = 0; i < 3; i++) {
       MethodSubject methodASubject = getMethodSubject(application, signatureA);
-      IRCode codeA = methodASubject.buildIR(options.itemFactory);
+      IRCode codeA = methodASubject.buildIR();
       additionalCode.add(codeA);
     }
 
     for (int i = 0; i < 3; i++) {
       MethodSubject methodBSubject = getMethodSubject(application, signatureB);
-      IRCode codeB = methodBSubject.buildIR(options.itemFactory);
+      IRCode codeB = methodBSubject.buildIR();
       additionalCode.add(codeB);
     }
 
@@ -1160,10 +1178,10 @@
     MethodSubject methodSubject = getMethodSubject(application, signature);
 
     MethodSubject methodASubject = getMethodSubject(application, signatureA);
-    IRCode codeA = methodASubject.buildIR(options.itemFactory);
+    IRCode codeA = methodASubject.buildIR();
 
     MethodSubject methodBSubject = getMethodSubject(application, signatureB);
-    IRCode codeB = methodBSubject.buildIR(options.itemFactory);
+    IRCode codeB = methodBSubject.buildIR();
 
     return buildTestApplication(
         application, options, methodSubject, ImmutableList.of(codeA, codeB));
diff --git a/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java b/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
index e9d9abd..83f64ee 100644
--- a/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
@@ -14,7 +14,6 @@
 import com.android.tools.r8.ir.code.InstructionListIterator;
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.ir.conversion.IRConverter;
-import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.MainDexClasses;
 import com.android.tools.r8.smali.SmaliBuilder;
 import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
@@ -34,22 +33,12 @@
 
   protected DexApplication buildApplication(SmaliBuilder builder, InternalOptions options) {
     try {
-      return buildApplication(
-          AndroidApp.builder().addDexProgramData(builder.compile(), Origin.unknown()).build(),
-          options);
+      return new ApplicationReader(builder.build(), options, Timing.empty()).read();
     } catch (IOException | RecognitionException | ExecutionException e) {
       throw new RuntimeException(e);
     }
   }
 
-  protected DexApplication buildApplication(AndroidApp input, InternalOptions options) {
-    try {
-      return new ApplicationReader(input, options, Timing.empty()).read();
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
   protected MethodSubject getMethodSubject(DexApplication application, MethodSignature signature) {
     return getMethodSubject(
         application,
@@ -89,7 +78,7 @@
       this.application = appView.appInfo().app();
       this.appView = appView;
       this.method = method.getMethod();
-      this.code = method.buildIR(appView.dexItemFactory());
+      this.code = method.buildIR();
       this.additionalCode = additionalCode;
       this.consumers = new AndroidAppConsumers(appView.options());
     }
diff --git a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
index 7104c9a..1662269 100644
--- a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
+++ b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
@@ -8,9 +8,10 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.code.Add;
 import com.android.tools.r8.ir.code.BasicBlock;
@@ -23,16 +24,28 @@
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.smali.SmaliBuilder;
 import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.List;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class SplitBlockTest extends IrInjectionTestBase {
 
-  private TestApplication codeWithoutCatchHandlers() {
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  public SplitBlockTest(TestParameters parameters) {
+    parameters.assertNoneRuntime();
+  }
+
+  private TestApplication codeWithoutCatchHandlers() throws Exception {
     SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
 
     String returnType = "int";
@@ -59,12 +72,10 @@
         "    return-void"
     );
 
-    InternalOptions options = new InternalOptions();
-    DexApplication application = buildApplication(builder, options);
-    AppView<?> appView = AppView.createForD8(new AppInfo(application), options);
+    AppView<AppInfo> appView = computeAppView(builder.build());
 
     // Return the processed method for inspection.
-    MethodSubject methodSubject = getMethodSubject(application, signature);
+    MethodSubject methodSubject = getMethodSubject(appView.appInfo().app(), signature);
     return new TestApplication(appView, methodSubject);
   }
 
@@ -137,7 +148,8 @@
     }
   }
 
-  private TestApplication codeWithCatchHandlers(boolean shouldThrow, boolean twoGuards) {
+  private TestApplication codeWithCatchHandlers(boolean shouldThrow, boolean twoGuards)
+      throws Exception {
     SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
 
     String secondGuard = twoGuards ?
@@ -175,12 +187,10 @@
         "    return-void"
     );
 
-    InternalOptions options = new InternalOptions();
-    DexApplication application = buildApplication(builder, options);
-    AppView<?> appView = AppView.createForD8(new AppInfo(application), options);
+    AppView<?> appView = computeAppView(builder.build());
 
     // Return the processed method for inspection.
-    MethodSubject methodSubject = getMethodSubject(application, signature);
+    MethodSubject methodSubject = getMethodSubject(appView.appInfo().app(), signature);
     return new TestApplication(appView, methodSubject);
   }
 
@@ -270,7 +280,7 @@
     runCatchHandlerSplitThreeTest(true, true);
   }
 
-  private TestApplication codeWithIf(boolean hitTrueBranch) {
+  private TestApplication codeWithIf(boolean hitTrueBranch) throws Exception {
     SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
 
     String returnType = "int";
@@ -299,12 +309,10 @@
         "    return-void"
     );
 
-    InternalOptions options = new InternalOptions();
-    DexApplication application = buildApplication(builder, options);
-    AppView<?> appView = AppView.createForD8(new AppInfo(application), options);
+    AppView<?> appView = computeAppView(builder.build());
 
     // Return the processed method for inspection.
-    MethodSubject methodSubject = getMethodSubject(application, signature);
+    MethodSubject methodSubject = getMethodSubject(appView.appInfo().app(), signature);
     return new TestApplication(appView, methodSubject);
   }
 
@@ -385,7 +393,7 @@
     splitBeforeReturn(true);
   }
 
-  private TestApplication codeWithSwitch(boolean hitCase) {
+  private TestApplication codeWithSwitch(boolean hitCase) throws Exception {
     SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
 
     String returnType = "int";
@@ -422,12 +430,10 @@
         "    return-void"
     );
 
-    InternalOptions options = new InternalOptions();
-    DexApplication application = buildApplication(builder, options);
-    AppView<?> appView = AppView.createForD8(new AppInfo(application), options);
+    AppView<?> appView = computeAppView(builder.build());
 
     // Return the processed method for inspection.
-    MethodSubject methodSubject = getMethodSubject(application, signature);
+    MethodSubject methodSubject = getMethodSubject(appView.appInfo().app(), signature);
     return new TestApplication(appView, methodSubject);
   }
 
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/AnalysisTestBase.java b/src/test/java/com/android/tools/r8/ir/analysis/AnalysisTestBase.java
index 80fef97..ce5cbce 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/AnalysisTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/AnalysisTestBase.java
@@ -64,7 +64,7 @@
   public void buildAndCheckIR(String methodName, Consumer<IRCode> irInspector) {
     CodeInspector inspector = new CodeInspector(appView.appInfo().app());
     MethodSubject methodSubject = inspector.clazz(className).uniqueMethodWithName(methodName);
-    irInspector.accept(methodSubject.buildIR(appView.dexItemFactory()));
+    irInspector.accept(methodSubject.buildIR());
   }
 
   @SuppressWarnings("unchecked")
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java b/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
index 5a53fb5..86f4e3d 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
@@ -134,7 +134,7 @@
                 timing)
             .read()
             .toDirect();
-    return AppView.createForR8(new AppInfoWithClassHierarchy(application), options);
+    return AppView.createForR8(new AppInfoWithClassHierarchy(application));
   }
 
   private DexEncodedField uniqueFieldByName(DexProgramClass clazz, String name) {
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
index 06f2813..a4c9785 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
@@ -11,6 +11,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
@@ -39,8 +41,22 @@
 import java.util.Map;
 import java.util.function.BiConsumer;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class NullabilityTest extends NonNullTrackerTestBase {
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  public NullabilityTest(TestParameters parameters) {
+    parameters.assertNoneRuntime();
+  }
+
   private void buildAndTest(
       Class<?> mainClass,
       MethodSignature signature,
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java
index d0cf699..40c87b6 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java
@@ -11,10 +11,8 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.code.ArrayLength;
 import com.android.tools.r8.ir.code.CheckCast;
@@ -32,9 +30,7 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.smali.SmaliTestBase;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Smali;
-import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
@@ -57,7 +53,6 @@
 
 @RunWith(Parameterized.class)
 public class TypeAnalysisTest extends SmaliTestBase {
-  private static final InternalOptions TEST_OPTIONS = new InternalOptions();
   private static final TypeElement NULL = TypeElement.getNull();
   private static final TypeElement SINGLE = TypeElement.getSingle();
   private static final TypeElement INT = TypeElement.getInt();
@@ -112,11 +107,8 @@
         .forEach(s -> smaliStringBuilder.append(s).append(System.lineSeparator()));
     byte[] content = Smali.compile(smaliStringBuilder.toString());
     AndroidApp app = AndroidApp.builder().addDexProgramData(content, Origin.unknown()).build();
-    DexApplication dexApplication =
-        new ApplicationReader(app, TEST_OPTIONS, Timing.empty()).read().toDirect();
-    inspection.accept(
-        AppView.createForD8(new AppInfo(dexApplication), TEST_OPTIONS),
-        new CodeInspector(dexApplication));
+    AppView<AppInfo> appView = computeAppView(app);
+    inspection.accept(appView, new CodeInspector(appView.appInfo().app()));
   }
 
   private static void forEachOutValue(IRCode irCode, BiConsumer<Value, TypeElement> consumer) {
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java
index cfe27c9..06de00a 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java
@@ -60,7 +60,7 @@
             .read()
             .toDirect();
     factory = options.itemFactory;
-    appView = AppView.createForR8(new AppInfoWithClassHierarchy(application), options);
+    appView = AppView.createForR8(new AppInfoWithClassHierarchy(application));
   }
 
   private TopTypeElement top() {
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 c838a0d..41c5ef5 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
@@ -45,7 +45,7 @@
               parser.parse(
                   createConfigurationForTesting(
                       ImmutableList.of("-keep class ** { void m1(); void m5(); }")));
-              return parser.getConfig().getRules();
+              return parser.getConfig();
             });
     this.options = appView.options();
     this.executorService = ThreadUtils.getExecutorService(options);
diff --git a/src/test/java/com/android/tools/r8/ir/conversion/StringSwitchConversionFromIfTest.java b/src/test/java/com/android/tools/r8/ir/conversion/StringSwitchConversionFromIfTest.java
index 2a700c3..294efee 100644
--- a/src/test/java/com/android/tools/r8/ir/conversion/StringSwitchConversionFromIfTest.java
+++ b/src/test/java/com/android/tools/r8/ir/conversion/StringSwitchConversionFromIfTest.java
@@ -17,8 +17,6 @@
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.utils.BooleanUtils;
-import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
@@ -75,15 +73,12 @@
               for (String methodName : methodNames) {
                 MethodSubject methodSubject = classSubject.uniqueMethodWithName(methodName);
                 assertThat(methodSubject, isPresent());
-
-                DexItemFactory dexItemFactory = new DexItemFactory();
-                InternalOptions options = new InternalOptions(dexItemFactory, new Reporter());
-                options.enableStringSwitchConversion = enableStringSwitchConversion;
-
-                IRCode code = methodSubject.buildIR(options);
+                IRCode code = methodSubject.buildIR();
                 List<Value> hashCodeValues =
                     Streams.stream(code.instructions())
-                        .filter(instruction -> isInvokeStringHashCode(instruction, dexItemFactory))
+                        .filter(
+                            instruction ->
+                                isInvokeStringHashCode(instruction, inspector.getFactory()))
                         .map(Instruction::asInvokeVirtual)
                         .map(Instruction::outValue)
                         .collect(Collectors.toList());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java
index fa6597f..dc6bc19 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java
@@ -134,7 +134,7 @@
     InternalOptions options = new InternalOptions();
     options.debug = true;
     AppInfo appInfo = new AppInfo(DexApplication.builder(options, null).build());
-    AppView<?> appView = AppView.createForD8(appInfo, options);
+    AppView<?> appView = AppView.createForD8(appInfo);
     IRCode code =
         new IRCode(
             options,
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java
index a9f77ce..daa21f4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java
@@ -7,6 +7,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.code.IRCode;
@@ -25,9 +27,22 @@
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import java.util.function.Consumer;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class NonNullTrackerTest extends NonNullTrackerTestBase {
 
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  public NonNullTrackerTest(TestParameters parameters) {
+    parameters.assertNoneRuntime();
+  }
+
   private void buildAndTest(
       Class<?> testClass,
       MethodSignature signature,
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
index 4820221..6b5f0cb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
@@ -5,27 +5,13 @@
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DirectMappedDexApplication;
-import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.Timing;
 
 public abstract class NonNullTrackerTestBase extends TestBase {
 
   protected AppView<? extends AppInfoWithClassHierarchy> build(Class<?> mainClass)
       throws Exception {
-    Timing timing = Timing.empty();
-    AndroidApp app = buildAndroidApp(ToolHelper.getClassAsBytes(mainClass));
-    InternalOptions options = new InternalOptions();
-    DirectMappedDexApplication dexApplication =
-        new ApplicationReader(app, options, timing).read().toDirect();
-    AppView<? extends AppInfoWithClassHierarchy> appView =
-        AppView.createForR8(new AppInfoWithClassHierarchy(dexApplication), options);
-    appView.setAppServices(AppServices.builder(appView).build());
-    return appView;
+    return computeAppViewWithSubtyping(buildAndroidApp(ToolHelper.getClassAsBytes(mainClass)));
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
index 95557b6..7d7785f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
@@ -6,9 +6,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.code.Argument;
@@ -26,13 +28,26 @@
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.ImmutableList;
 import java.util.LinkedList;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
-public class TrivialGotoEliminationTest {
+@RunWith(Parameterized.class)
+public class TrivialGotoEliminationTest extends TestBase {
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  public TrivialGotoEliminationTest(TestParameters parameters) {
+    parameters.assertNoneRuntime();
+  }
 
   private final IRMetadata metadata = IRMetadata.unknown();
 
@@ -92,10 +107,9 @@
   }
 
   @Test
-  public void trivialGotoLoopAsFallthrough() {
-    InternalOptions options = new InternalOptions();
-    DexApplication app = DexApplication.builder(new InternalOptions(), Timing.empty()).build();
-    AppView<AppInfo> appView = AppView.createForD8(new AppInfo(app), options);
+  public void trivialGotoLoopAsFallthrough() throws Exception {
+    AppView<AppInfo> appView = computeAppView(AndroidApp.builder().build());
+    InternalOptions options = appView.options();
     // Setup block structure:
     // block0:
     //   v0 <- argument
@@ -135,7 +149,7 @@
         new Value(
             0,
             TypeElement.fromDexType(
-                app.dexItemFactory.throwableType, Nullability.definitelyNotNull(), appView),
+                options.itemFactory.throwableType, Nullability.definitelyNotNull(), appView),
             null);
     instruction = new Argument(value, 0, false);
     instruction.setPosition(position);
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
index b4d2c3a..3c202dd 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
@@ -367,7 +367,7 @@
   public void multipleLiveTempRegisters() {
     InternalOptions options = new InternalOptions();
     AppView<AppInfo> appInfo =
-        AppView.createForD8(new AppInfo(DexApplication.builder(options, null).build()), options);
+        AppView.createForD8(new AppInfo(DexApplication.builder(options, null).build()));
     TypeElement objectType =
         TypeElement.fromDexType(options.itemFactory.objectType, Nullability.maybeNull(), appInfo);
     CollectMovesIterator moves = new CollectMovesIterator();
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java b/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java
index 2c1d228..e246335 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java
@@ -57,7 +57,7 @@
   public void splitOverlappingInactiveIntervalWithNoNextUse() {
     InternalOptions options = new InternalOptions();
     AppInfo appInfo = new AppInfo(DexApplication.builder(options, null).build());
-    AppView<?> appView = AppView.createForD8(appInfo, options);
+    AppView<?> appView = AppView.createForD8(appInfo);
     IRCode code = simpleCode();
     MyRegisterAllocator allocator = new MyRegisterAllocator(appView, code);
     // Setup live an inactive live interval with ranges [0, 10[ and [20, 30[ with only
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index 26186aa..b3cbe0e 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -809,7 +809,7 @@
     options.intermediate = intermediate;
     DexItemFactory factory = options.itemFactory;
     AppInfo appInfo = new AppInfo(DexApplication.builder(options, timing).build());
-    AppView<?> appView = AppView.createForR8(appInfo, options);
+    AppView<?> appView = AppView.createForR8(appInfo);
     DexApplication.Builder<?> builder = DexApplication.builder(options, timing);
     for (String clazz : classes) {
       DexString desc = factory.createString(DescriptorUtils.javaTypeToDescriptor(clazz));
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierTest.java b/src/test/java/com/android/tools/r8/naming/MinifierTest.java
index 1baffde..ebc3ad7 100644
--- a/src/test/java/com/android/tools/r8/naming/MinifierTest.java
+++ b/src/test/java/com/android/tools/r8/naming/MinifierTest.java
@@ -36,7 +36,7 @@
   @Test
   public void minifierTest() throws Exception {
     NamingLens naming = runMinifier(ListUtils.map(keepRulesFiles, Paths::get));
-    inspection.accept(dexItemFactory, naming);
+    inspection.accept(naming);
   }
 
   @Parameters(name = "test: {0} keep: {1}")
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index 385911c..e461666 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -3,83 +3,55 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
-import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DirectMappedDexApplication;
-import com.android.tools.r8.graph.SubtypingInfo;
-import com.android.tools.r8.shaking.Enqueuer;
-import com.android.tools.r8.shaking.EnqueuerFactory;
-import com.android.tools.r8.shaking.ProguardConfiguration;
-import com.android.tools.r8.shaking.RootSetBuilder;
-import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.Reporter;
-import com.android.tools.r8.utils.ThreadUtils;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.ImmutableList;
 import java.io.File;
-import java.io.IOException;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.function.BiConsumer;
-import org.junit.Before;
+import java.util.function.Consumer;
 
-public abstract class NamingTestBase {
+public abstract class NamingTestBase extends TestBase {
 
   private final String appFileName;
   protected final List<String> keepRulesFiles;
-  protected final BiConsumer<DexItemFactory, NamingLens> inspection;
+  protected final Consumer<NamingLens> inspection;
 
-  private final Timing timing;
-
-  private DirectMappedDexApplication program;
-  protected DexItemFactory dexItemFactory;
+  private DexItemFactory dexItemFactory = null;
 
   protected NamingTestBase(
       String test, List<String> keepRulesFiles, BiConsumer<DexItemFactory, NamingLens> inspection) {
     appFileName = ToolHelper.EXAMPLES_BUILD_DIR + test + "/classes.dex";
     this.keepRulesFiles = keepRulesFiles;
-    this.inspection = inspection;
-    this.timing = Timing.empty();
+    this.inspection = lens -> inspection.accept(dexItemFactory, lens);
   }
 
-  @Before
-  public void readApp() throws IOException, ExecutionException {
-    program = ToolHelper.buildApplication(ImmutableList.of(appFileName));
-    dexItemFactory = program.dexItemFactory;
-  }
-
-  protected NamingLens runMinifier(List<Path> configPaths) throws ExecutionException {
-    ProguardConfiguration configuration =
-        ToolHelper.loadProguardConfiguration(dexItemFactory, configPaths);
-
-    InternalOptions options = new InternalOptions(configuration, new Reporter());
-    options.programConsumer = DexIndexedConsumer.emptyConsumer();
-
-    ExecutorService executor = ThreadUtils.getExecutorService(1);
-
-    AppView<AppInfoWithClassHierarchy> appView =
-        AppView.createForR8(new AppInfoWithClassHierarchy(program), options);
-    SubtypingInfo subtypingInfo = new SubtypingInfo(program.allClasses(), program);
-    appView.setRootSet(
-        new RootSetBuilder(appView, subtypingInfo, configuration.getRules()).run(executor));
-    appView.setAppServices(AppServices.builder(appView).build());
-
-    Enqueuer enqueuer = EnqueuerFactory.createForInitialTreeShaking(appView, subtypingInfo);
-    appView.setAppInfo(
-        enqueuer.traceApplication(
-            appView.rootSet(), configuration.getDontWarnPatterns(), executor, timing));
-    return new Minifier(appView.withLiveness()).run(executor, timing);
+  protected NamingLens runMinifier(List<Path> configPaths) throws Exception {
+    AppView<AppInfoWithLiveness> appView =
+        computeAppViewWithLiveness(
+            AndroidApp.builder().addProgramFile(Paths.get(appFileName)).build(),
+            factory -> ToolHelper.loadProguardConfiguration(factory, configPaths));
+    dexItemFactory = appView.dexItemFactory();
+    ExecutorService executor = Executors.newSingleThreadExecutor();
+    try {
+      return new Minifier(appView).run(executor, Timing.empty());
+    } finally {
+      executor.shutdown();
+    }
   }
 
   protected static <T> Collection<Object[]> createTests(
diff --git a/src/test/java/com/android/tools/r8/naming/PackageNamingTest.java b/src/test/java/com/android/tools/r8/naming/PackageNamingTest.java
index 549b0e1..caa1ae9 100644
--- a/src/test/java/com/android/tools/r8/naming/PackageNamingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/PackageNamingTest.java
@@ -44,7 +44,7 @@
   @Test
   public void packageNamingTest() throws Exception {
     NamingLens naming = runMinifier(ListUtils.map(keepRulesFiles, Paths::get));
-    inspection.accept(dexItemFactory, naming);
+    inspection.accept(naming);
   }
 
   private static final List<String> CLASSES_IN_NAMING044 = ImmutableList.of(
diff --git a/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java b/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
index abd4956..4e19a05 100644
--- a/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
@@ -24,7 +24,6 @@
 import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.Sets;
-import java.util.ArrayList;
 import java.util.Set;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -48,7 +47,8 @@
     AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
             buildClasses(A.class, B.class, Main.class).build(),
-            factory -> new ArrayList<>(buildKeepRuleForClassAndMethods(Main.class, factory)));
+            factory ->
+                buildConfigForRules(factory, buildKeepRuleForClassAndMethods(Main.class, factory)));
     AppInfoWithLiveness appInfo = appView.appInfo();
     DexType typeA = buildType(A.class, appInfo.dexItemFactory());
     DexType typeB = buildType(B.class, appInfo.dexItemFactory());
@@ -72,7 +72,8 @@
     AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
             buildClasses(A.class, B.class, C.class, Main.class).build(),
-            factory -> new ArrayList<>(buildKeepRuleForClassAndMethods(Main.class, factory)));
+            factory ->
+                buildConfigForRules(factory, buildKeepRuleForClassAndMethods(Main.class, factory)));
     AppInfoWithLiveness appInfo = appView.appInfo();
     DexType typeA = buildType(A.class, appInfo.dexItemFactory());
     DexType typeB = buildType(B.class, appInfo.dexItemFactory());
@@ -97,8 +98,8 @@
         computeAppViewWithLiveness(
             buildClasses(A.class, B.class, C.class, MainAllInstantiated.class).build(),
             factory ->
-                new ArrayList<>(
-                    buildKeepRuleForClassAndMethods(MainAllInstantiated.class, factory)));
+                buildConfigForRules(
+                    factory, buildKeepRuleForClassAndMethods(MainAllInstantiated.class, factory)));
     AppInfoWithLiveness appInfo = appView.appInfo();
     DexType typeA = buildType(A.class, appInfo.dexItemFactory());
     DexType typeC = buildType(C.class, appInfo.dexItemFactory());
diff --git a/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java b/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java
index 9489060..593670d 100644
--- a/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java
@@ -17,7 +17,6 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import java.util.ArrayList;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -40,7 +39,8 @@
     AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
             buildClasses(I.class, A.class, Main.class).build(),
-            factory -> new ArrayList<>(buildKeepRuleForClassAndMethods(Main.class, factory)));
+            factory ->
+                buildConfigForRules(factory, buildKeepRuleForClassAndMethods(Main.class, factory)));
     AppInfoWithLiveness appInfo = appView.appInfo();
     DexType typeMain = buildType(Main.class, appInfo.dexItemFactory());
     DexMethod mainMethodReference =
@@ -63,7 +63,8 @@
     AppView<AppInfoWithLiveness> appView =
         computeAppViewWithLiveness(
             buildClasses(I.class, A.class, Main.class).build(),
-            factory -> new ArrayList<>(buildKeepRuleForClassAndMethods(Main.class, factory)));
+            factory ->
+                buildConfigForRules(factory, buildKeepRuleForClassAndMethods(Main.class, factory)));
     AppInfoWithLiveness appInfo = appView.appInfo();
     DexType typeMain = buildType(Main.class, appInfo.dexItemFactory());
     DexMethod mainMethodReference =
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java
index 745ff4b..4332d86 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java
@@ -82,7 +82,7 @@
               rules.addAll(buildKeepRuleForClassAndMethods(methodToBeKept, factory));
               rules.addAll(buildKeepRuleForClass(classToBeKept, factory));
               rules.addAll(buildKeepRuleForClassAndMethods(main, factory));
-              return rules;
+              return buildConfigForRules(factory, rules);
             });
     AppInfoWithLiveness appInfo = appView.appInfo();
     DexMethod method = buildNullaryVoidMethod(initial, "foo", appInfo.dexItemFactory());
diff --git a/src/test/java/com/android/tools/r8/smali/CatchSuccessorFallthroughTest.java b/src/test/java/com/android/tools/r8/smali/CatchSuccessorFallthroughTest.java
index 17cce81..f4884c3 100644
--- a/src/test/java/com/android/tools/r8/smali/CatchSuccessorFallthroughTest.java
+++ b/src/test/java/com/android/tools/r8/smali/CatchSuccessorFallthroughTest.java
@@ -79,7 +79,7 @@
 
     ProgramMethod method = getProgramMethod(originalApplication, methodSig);
     // Get the IR pre-optimization.
-    IRCode code = method.buildIR(AppView.createForD8(new AppInfo(application), options));
+    IRCode code = method.buildIR(AppView.createForD8(new AppInfo(application)));
 
     // Find the exit block and assert that the value is a phi merging the exceptional edge
     // with the normal edge.
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
index ed7ac4d..38dc236 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
@@ -10,12 +10,11 @@
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.naming.MemberNaming.Signature;
-import com.android.tools.r8.utils.InternalOptions;
 
 public class AbsentMethodSubject extends MethodSubject {
 
   @Override
-  public IRCode buildIR(InternalOptions options) {
+  public IRCode buildIR() {
     throw new Unreachable("Cannot build IR for an absent method");
   }
 
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index f43c01c..76ed0e2 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -5,6 +5,7 @@
 
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.DexIndexedConsumer;
 import com.android.tools.r8.StringResource;
 import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.cf.code.CfTryCatch;
@@ -126,6 +127,10 @@
     if (optionsConsumer != null) {
       optionsConsumer.accept(internalOptions);
     }
+    if (internalOptions.programConsumer == null) {
+      // The inspector allows building IR for a method. An output type must be defined for that.
+      internalOptions.programConsumer = DexIndexedConsumer.emptyConsumer();
+    }
     return internalOptions;
   }
 
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index 0e504ca..1f1fe84 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -4,7 +4,6 @@
 
 package com.android.tools.r8.utils.codeinspector;
 
-import com.android.tools.r8.DexIndexedConsumer;
 import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.cf.code.CfPosition;
 import com.android.tools.r8.code.Instruction;
@@ -32,7 +31,6 @@
 import com.android.tools.r8.naming.signature.GenericSignatureParser;
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.LocalVariableTable.LocalVariableTableEntry;
 import com.google.common.base.Predicates;
@@ -58,10 +56,9 @@
   }
 
   @Override
-  public IRCode buildIR(InternalOptions options) {
-    options.programConsumer = DexIndexedConsumer.emptyConsumer();
-    return getProgramMethod()
-        .buildIR(AppView.createForD8(new AppInfo(codeInspector.application), options));
+  public IRCode buildIR() {
+    assert codeInspector.application.options.programConsumer != null;
+    return getProgramMethod().buildIR(AppView.createForD8(new AppInfo(codeInspector.application)));
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
index 72b71b0..8fc439f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
@@ -5,12 +5,9 @@
 package com.android.tools.r8.utils.codeinspector;
 
 import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
-import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.Reporter;
 import com.google.common.collect.Streams;
 import java.util.Iterator;
 import java.util.function.Predicate;
@@ -18,15 +15,7 @@
 
 public abstract class MethodSubject extends MemberSubject {
 
-  public final IRCode buildIR() {
-    return buildIR(new DexItemFactory());
-  }
-
-  public IRCode buildIR(DexItemFactory dexItemFactory) {
-    return buildIR(new InternalOptions(dexItemFactory, new Reporter()));
-  }
-
-  public abstract IRCode buildIR(InternalOptions options);
+  public abstract IRCode buildIR();
 
   public final boolean isAbsent() {
     return !isPresent();