Merge "Access to most recent AppInfo and GraphLense via AppView"
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 3d2cc25..805bdf7 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.dex.Marker.Tool;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
@@ -249,12 +250,13 @@
       DexApplication application =
           new ApplicationReader(inputApp, options, timing).read(executorService).toDirect();
 
-      AppInfoWithSubtyping appInfo = new AppInfoWithSubtyping(application);
+      AppView<AppInfoWithSubtyping> appView =
+          new AppView<>(new AppInfoWithSubtyping(application), GraphLense.getIdentityLense());
       RootSet rootSet;
       String proguardSeedsData = null;
       timing.begin("Strip unused code");
       try {
-        Set<DexType> missingClasses = appInfo.getMissingClasses();
+        Set<DexType> missingClasses = appView.getAppInfo().getMissingClasses();
         missingClasses = filterMissingClasses(
             missingClasses, options.proguardConfiguration.getDontWarnPatterns());
         if (!missingClasses.isEmpty()) {
@@ -271,34 +273,50 @@
 
         // Compute kotlin info before setting the roots and before
         // kotlin metadata annotation is removed.
-        computeKotlinInfoForProgramClasses(application, appInfo);
+        computeKotlinInfoForProgramClasses(application, appView.getAppInfo());
 
         final ProguardConfiguration.Builder compatibility =
             ProguardConfiguration.builder(application.dexItemFactory, options.reporter);
 
-        rootSet = new RootSetBuilder(
-                    appInfo, application, options.proguardConfiguration.getRules(), options)
+        rootSet =
+            new RootSetBuilder(
+                    appView.getAppInfo(),
+                    application,
+                    options.proguardConfiguration.getRules(),
+                    options)
                 .run(executorService);
         ProtoLiteExtension protoLiteExtension =
-            options.forceProguardCompatibility ? null : new ProtoLiteExtension(appInfo);
-        Enqueuer enqueuer = new Enqueuer(appInfo, options, options.forceProguardCompatibility,
-            compatibility, protoLiteExtension);
-        appInfo = enqueuer.traceApplication(rootSet, executorService, timing);
+            options.forceProguardCompatibility
+                ? null
+                : new ProtoLiteExtension(appView.getAppInfo());
+        Enqueuer enqueuer =
+            new Enqueuer(
+                appView.getAppInfo(),
+                options,
+                options.forceProguardCompatibility,
+                compatibility,
+                protoLiteExtension);
+        appView.setAppInfo(enqueuer.traceApplication(rootSet, executorService, timing));
         if (options.proguardConfiguration.isPrintSeeds()) {
           ByteArrayOutputStream bytes = new ByteArrayOutputStream();
           PrintStream out = new PrintStream(bytes);
-          RootSetBuilder.writeSeeds(appInfo.withLiveness(), out, type -> true);
+          RootSetBuilder.writeSeeds(appView.getAppInfo().withLiveness(), out, type -> true);
           out.flush();
           proguardSeedsData = bytes.toString();
         }
         if (options.enableTreeShaking) {
-          TreePruner pruner = new TreePruner(application, appInfo.withLiveness(), options);
+          TreePruner pruner =
+              new TreePruner(application, appView.getAppInfo().withLiveness(), options);
           application = pruner.run();
           // Recompute the subtyping information.
-          appInfo = appInfo.withLiveness().prunedCopyFrom(application, pruner.getRemovedClasses());
-          new AbstractMethodRemover(appInfo).run();
+          appView.setAppInfo(
+              appView
+                  .getAppInfo()
+                  .withLiveness()
+                  .prunedCopyFrom(application, pruner.getRemovedClasses()));
+          new AbstractMethodRemover(appView.getAppInfo()).run();
         }
-        new AnnotationRemover(appInfo.withLiveness(), compatibility, options).run();
+        new AnnotationRemover(appView.getAppInfo().withLiveness(), compatibility, options).run();
 
         // TODO(69445518): This is still work in progress, and this file writing is currently used
         // for testing.
@@ -320,44 +338,52 @@
         timing.end();
       }
 
-      GraphLense graphLense = GraphLense.getIdentityLense();
-
       if (options.proguardConfiguration.isAccessModificationAllowed()) {
-        graphLense = ClassAndMemberPublicizer.run(
-            executorService, timing, application, appInfo, rootSet, graphLense);
+        appView.setGraphLense(
+            ClassAndMemberPublicizer.run(executorService, timing, application, appView, rootSet));
         // We can now remove visibility bridges. Note that we do not need to update the
         // invoke-targets here, as the existing invokes will simply dispatch to the now
         // visible super-method. MemberRebinding, if run, will then dispatch it correctly.
-        application = new VisibilityBridgeRemover(appInfo, application).run();
+        application = new VisibilityBridgeRemover(appView.getAppInfo(), application).run();
       }
 
-      if (appInfo.hasLiveness()) {
+      if (appView.getAppInfo().hasLiveness()) {
+        AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+
         if (options.proguardConfiguration.hasApplyMappingFile()) {
           SeedMapper seedMapper =
               SeedMapper.seedMapperFromFile(options.proguardConfiguration.getApplyMappingFile());
           timing.begin("apply-mapping");
-          graphLense =
-              new ProguardMapApplier(appInfo.withLiveness(), graphLense, seedMapper).run(timing);
-          application = application.asDirect().rewrittenWithLense(graphLense);
-          appInfo = appInfo.withLiveness().rewrittenWithLense(application.asDirect(), graphLense);
+          appView.setGraphLense(
+              new ProguardMapApplier(appView.withLiveness(), seedMapper).run(timing));
+          application = application.asDirect().rewrittenWithLense(appView.getGraphLense());
+          appView.setAppInfo(
+              appView
+                  .getAppInfo()
+                  .withLiveness()
+                  .rewrittenWithLense(application.asDirect(), appView.getGraphLense()));
           timing.end();
         }
-        graphLense = new MemberRebindingAnalysis(appInfo.withLiveness(), graphLense).run();
+        appView.setGraphLense(new MemberRebindingAnalysis(appViewWithLiveness).run());
         // Class merging requires inlining.
         if (options.enableClassMerging && options.enableInlining) {
           timing.begin("ClassMerger");
           VerticalClassMerger classMerger =
-              new VerticalClassMerger(application, appInfo.withLiveness(), graphLense, timing);
-          graphLense = classMerger.run();
+              new VerticalClassMerger(application, appViewWithLiveness, timing);
+          appView.setGraphLense(classMerger.run());
           timing.end();
-          application = application.asDirect().rewrittenWithLense(graphLense);
-          appInfo = appInfo.withLiveness()
-              .prunedCopyFrom(application, classMerger.getRemovedClasses())
-              .rewrittenWithLense(application.asDirect(), graphLense);
+          application = application.asDirect().rewrittenWithLense(appView.getGraphLense());
+          appViewWithLiveness.setAppInfo(
+              appViewWithLiveness
+                  .getAppInfo()
+                  .prunedCopyFrom(application, classMerger.getRemovedClasses())
+                  .rewrittenWithLense(application.asDirect(), appView.getGraphLense()));
         }
         // Collect switch maps and ordinals maps.
-        appInfo = new SwitchMapCollector(appInfo.withLiveness(), options).run();
-        appInfo = new EnumOrdinalMapCollector(appInfo.withLiveness(), options).run();
+        appViewWithLiveness.setAppInfo(
+            new SwitchMapCollector(appViewWithLiveness.getAppInfo(), options).run());
+        appViewWithLiveness.setAppInfo(
+            new EnumOrdinalMapCollector(appViewWithLiveness.getAppInfo(), options).run());
 
         // TODO(b/79143143): re-enable once fixed.
         // graphLense = new BridgeMethodAnalysis(graphLense, appInfo.withLiveness()).run();
@@ -366,7 +392,9 @@
       timing.begin("Create IR");
       CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
       try {
-        IRConverter converter = new IRConverter(appInfo, options, timing, printer, graphLense);
+        IRConverter converter =
+            new IRConverter(
+                appView.getAppInfo(), options, timing, printer, appView.getGraphLense());
         application = converter.optimize(application, executorService);
       } finally {
         timing.end();
@@ -386,15 +414,15 @@
 
       // Overwrite SourceFile if specified. This step should be done after IR conversion.
       timing.begin("Rename SourceFile");
-      new SourceFileRewriter(appInfo, options).run();
+      new SourceFileRewriter(appView.getAppInfo(), options).run();
       timing.end();
 
       if (!options.mainDexKeepRules.isEmpty()) {
-        appInfo = new AppInfoWithSubtyping(application);
-        Enqueuer enqueuer = new Enqueuer(appInfo, options, true);
+        appView.setAppInfo(new AppInfoWithSubtyping(application));
+        Enqueuer enqueuer = new Enqueuer(appView.getAppInfo(), options, true);
         // Lets find classes which may have code executed before secondary dex files installation.
         RootSet mainDexRootSet =
-            new RootSetBuilder(appInfo, application, options.mainDexKeepRules, options)
+            new RootSetBuilder(appView.getAppInfo(), application, options.mainDexKeepRules, options)
                 .run(executorService);
         AppInfoWithLiveness mainDexAppInfo =
             enqueuer.traceMainDex(mainDexRootSet, executorService, timing);
@@ -409,18 +437,24 @@
             .build();
       }
 
-      appInfo = new AppInfoWithSubtyping(application);
+      appView.setAppInfo(new AppInfoWithSubtyping(application));
 
       if (options.enableTreeShaking || options.enableMinification) {
         timing.begin("Post optimization code stripping");
         try {
-          Enqueuer enqueuer = new Enqueuer(appInfo, options, options.forceProguardCompatibility);
-          appInfo = enqueuer.traceApplication(rootSet, executorService, timing);
+          Enqueuer enqueuer =
+              new Enqueuer(appView.getAppInfo(), options, options.forceProguardCompatibility);
+          appView.setAppInfo(enqueuer.traceApplication(rootSet, executorService, timing));
+
+          AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
           if (options.enableTreeShaking) {
-            TreePruner pruner = new TreePruner(application, appInfo.withLiveness(), options);
+            TreePruner pruner =
+                new TreePruner(application, appViewWithLiveness.getAppInfo(), options);
             application = pruner.run();
-            appInfo = appInfo.withLiveness()
-                .prunedCopyFrom(application, pruner.getRemovedClasses());
+            appViewWithLiveness.setAppInfo(
+                appViewWithLiveness
+                    .getAppInfo()
+                    .prunedCopyFrom(application, pruner.getRemovedClasses()));
             // Print reasons on the application after pruning, so that we reflect the actual result.
             ReasonPrinter reasonPrinter = enqueuer.getReasonPrinter(rootSet.reasonAsked);
             reasonPrinter.run(application);
@@ -440,7 +474,7 @@
       // will happen. Just avoid the overhead.
       NamingLens namingLens =
           options.enableMinification
-              ? new Minifier(appInfo.withLiveness(), rootSet, options).run(timing)
+              ? new Minifier(appView.getAppInfo().withLiveness(), rootSet, options).run(timing)
               : NamingLens.getIdentityLens();
       timing.end();
 
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
new file mode 100644
index 0000000..8e468a1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -0,0 +1,78 @@
+// Copyright (c) 2018, 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.graph;
+
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+
+public class AppView<T extends AppInfo> {
+
+  private T appInfo;
+  private final DexItemFactory dexItemFactory;
+  private GraphLense graphLense;
+
+  public AppView(T appInfo, GraphLense graphLense) {
+    this.appInfo = appInfo;
+    this.dexItemFactory = appInfo.dexItemFactory;
+    this.graphLense = graphLense;
+  }
+
+  public T getAppInfo() {
+    return appInfo;
+  }
+
+  public void setAppInfo(T appInfo) {
+    this.appInfo = appInfo;
+  }
+
+  public DexItemFactory getDexItemFactory() {
+    return dexItemFactory;
+  }
+
+  public GraphLense getGraphLense() {
+    return graphLense;
+  }
+
+  public void setGraphLense(GraphLense graphLense) {
+    this.graphLense = graphLense;
+  }
+
+  public AppView<AppInfoWithLiveness> withLiveness() {
+    return new AppViewWithLiveness();
+  }
+
+  private class AppViewWithLiveness extends AppView<AppInfoWithLiveness> {
+
+    private AppViewWithLiveness() {
+      super(null, null);
+    }
+
+    @Override
+    public AppInfoWithLiveness getAppInfo() {
+      return AppView.this.getAppInfo().withLiveness();
+    }
+
+    @Override
+    public void setAppInfo(AppInfoWithLiveness appInfoWithLiveness) {
+      @SuppressWarnings("unchecked")
+      T appInfo = (T) appInfoWithLiveness;
+      AppView.this.setAppInfo(appInfo);
+    }
+
+    @Override
+    public GraphLense getGraphLense() {
+      return AppView.this.getGraphLense();
+    }
+
+    @Override
+    public void setGraphLense(GraphLense graphLense) {
+      AppView.this.setGraphLense(graphLense);
+    }
+
+    @Override
+    public AppView<AppInfoWithLiveness> withLiveness() {
+      return this;
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
index f5d48fd..f114a7e 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexClass;
@@ -33,13 +34,10 @@
   private final GraphLense previousLense;
   private final SeedMapper seedMapper;
 
-  public ProguardMapApplier(
-      AppInfoWithLiveness appInfo,
-      GraphLense previousLense,
-      SeedMapper seedMapper) {
-    assert previousLense.isContextFreeForMethods();
-    this.appInfo = appInfo;
-    this.previousLense = previousLense;
+  public ProguardMapApplier(AppView<AppInfoWithLiveness> appView, SeedMapper seedMapper) {
+    assert appView.getGraphLense().isContextFreeForMethods();
+    this.appInfo = appView.getAppInfo();
+    this.previousLense = appView.getGraphLense();
     this.seedMapper = seedMapper;
   }
 
diff --git a/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java b/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java
index 04f8a3b..73ebf73 100644
--- a/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.optimize;
 
-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.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -31,42 +31,34 @@
 
 public final class ClassAndMemberPublicizer {
   private final DexApplication application;
-  private final AppInfo appInfo;
+  private final AppView appView;
   private final RootSet rootSet;
-  private final GraphLense previousLense;
   private final PublicizedLenseBuilder lenseBuilder;
 
   private final Equivalence<DexMethod> equivalence = MethodSignatureEquivalence.get();
   private final Map<DexClass, MethodPool> methodPools = new ConcurrentHashMap<>();
 
-  private ClassAndMemberPublicizer(
-      DexApplication application,
-      AppInfo appInfo,
-      RootSet rootSet,
-      GraphLense previousLense) {
+  private ClassAndMemberPublicizer(DexApplication application, AppView appView, RootSet rootSet) {
     this.application = application;
-    this.appInfo = appInfo;
+    this.appView = appView;
     this.rootSet = rootSet;
-    this.previousLense = previousLense;
     lenseBuilder = PublicizerLense.createBuilder();
   }
 
   /**
-   * Marks all package private and protected methods and fields as public.
-   * Makes all private static methods public.
-   * Makes private instance methods public final instance methods, if possible.
-   * <p>
-   * This will destructively update the DexApplication passed in as argument.
+   * Marks all package private and protected methods and fields as public. Makes all private static
+   * methods public. Makes private instance methods public final instance methods, if possible.
+   *
+   * <p>This will destructively update the DexApplication passed in as argument.
    */
   public static GraphLense run(
       ExecutorService executorService,
       Timing timing,
       DexApplication application,
-      AppInfo appInfo,
-      RootSet rootSet,
-      GraphLense previousLense) throws ExecutionException {
-    return new ClassAndMemberPublicizer(application, appInfo, rootSet, previousLense)
-        .run(executorService, timing);
+      AppView appView,
+      RootSet rootSet)
+      throws ExecutionException {
+    return new ClassAndMemberPublicizer(application, appView, rootSet).run(executorService, timing);
   }
 
   private GraphLense run(ExecutorService executorService, Timing timing)
@@ -84,11 +76,11 @@
 
     // Phase 2: Visit classes and promote class/member to public if possible.
     timing.begin("Phase 2: promoteToPublic");
-    DexType.forAllInterfaces(appInfo.dexItemFactory, this::publicizeType);
-    publicizeType(appInfo.dexItemFactory.objectType);
+    DexType.forAllInterfaces(appView.getDexItemFactory(), this::publicizeType);
+    publicizeType(appView.getDexItemFactory().objectType);
     timing.end();
 
-    return lenseBuilder.build(appInfo, previousLense);
+    return lenseBuilder.build(appView);
   }
 
   private Runnable computeMethodPoolPerClass(DexClass clazz) {
@@ -145,7 +137,7 @@
       return false;
     }
 
-    if (appInfo.dexItemFactory.isClassConstructor(encodedMethod.method)) {
+    if (appView.getDexItemFactory().isClassConstructor(encodedMethod.method)) {
       return false;
     }
 
@@ -156,7 +148,7 @@
     }
     assert accessFlags.isPrivate();
 
-    if (appInfo.dexItemFactory.isConstructor(encodedMethod.method)) {
+    if (appView.getDexItemFactory().isConstructor(encodedMethod.method)) {
       // TODO(b/72211928)
       return false;
     }
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 9efd5c8..fe098cc 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.optimize;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -28,10 +29,10 @@
   private final GraphLense lense;
   private final MemberRebindingLense.Builder builder;
 
-  public MemberRebindingAnalysis(AppInfoWithLiveness appInfo, GraphLense lense) {
-    assert lense.isContextFreeForMethods();
-    this.appInfo = appInfo;
-    this.lense = lense;
+  public MemberRebindingAnalysis(AppView<AppInfoWithLiveness> appView) {
+    assert appView.getGraphLense().isContextFreeForMethods();
+    this.appInfo = appView.getAppInfo();
+    this.lense = appView.getGraphLense();
     this.builder = MemberRebindingLense.builder(appInfo);
   }
 
diff --git a/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java b/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java
index 835135e..7a9c08f 100644
--- a/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java
+++ b/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.optimize;
 
-import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
@@ -15,16 +15,19 @@
 import java.util.Set;
 
 final class PublicizerLense extends NestedGraphLense {
-  private final AppInfo appInfo;
+  private final AppView appView;
   private final Set<DexMethod> publicizedMethods;
 
-  PublicizerLense(
-      AppInfo appInfo, GraphLense previousLense, Set<DexMethod> publicizedMethods) {
+  PublicizerLense(AppView appView, Set<DexMethod> publicizedMethods) {
     // This lense does not map any DexItem's at all.
     // It will just tweak invoke type for publicized methods from invoke-direct to invoke-virtual.
-    super(ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of(),
-        previousLense, appInfo.dexItemFactory);
-    this.appInfo = appInfo;
+    super(
+        ImmutableMap.of(),
+        ImmutableMap.of(),
+        ImmutableMap.of(),
+        appView.getGraphLense(),
+        appView.getAppInfo().dexItemFactory);
+    this.appView = appView;
     this.publicizedMethods = publicizedMethods;
   }
 
@@ -35,18 +38,24 @@
     method = previous.getMethod();
     type = previous.getType();
     if (type == Type.DIRECT && publicizedMethods.contains(method)) {
-      DexClass holderClass = appInfo.definitionFor(method.holder);
-      if (holderClass != null) {
-        DexEncodedMethod actualEncodedTarget = holderClass.lookupVirtualMethod(method);
-        if (actualEncodedTarget != null
-            && actualEncodedTarget.isPublicized()) {
-          return new GraphLenseLookupResult(method, Type.VIRTUAL);
-        }
-      }
+      assert publicizedMethodIsPresentOnHolder(method, context);
+      return new GraphLenseLookupResult(method, Type.VIRTUAL);
     }
     return super.lookupMethod(method, context, type);
   }
 
+  private boolean publicizedMethodIsPresentOnHolder(DexMethod method, DexEncodedMethod context) {
+    GraphLenseLookupResult lookup =
+        appView.getGraphLense().lookupMethod(method, context, Type.VIRTUAL);
+    DexMethod signatureInCurrentWorld = lookup.getMethod();
+    DexClass clazz = appView.getAppInfo().definitionFor(signatureInCurrentWorld.holder);
+    assert clazz != null;
+    DexEncodedMethod actualEncodedTarget = clazz.lookupVirtualMethod(signatureInCurrentWorld);
+    assert actualEncodedTarget != null;
+    assert actualEncodedTarget.isPublicized();
+    return true;
+  }
+
   static PublicizedLenseBuilder createBuilder() {
     return new PublicizedLenseBuilder();
   }
@@ -57,8 +66,8 @@
     private PublicizedLenseBuilder() {
     }
 
-    public GraphLense build(AppInfo appInfo, GraphLense previousLense) {
-      return new PublicizerLense(appInfo, previousLense, methodSetBuilder.build());
+    public GraphLense build(AppView appView) {
+      return new PublicizerLense(appView, methodSetBuilder.build());
     }
 
     public void add(DexMethod publicizedMethod) {
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 9acb95c..531c731 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo.ResolutionResult;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexClass;
@@ -159,13 +160,10 @@
   private final VerticalClassMergerGraphLense.Builder renamedMembersLense;
 
   public VerticalClassMerger(
-      DexApplication application,
-      AppInfoWithLiveness appInfo,
-      GraphLense graphLense,
-      Timing timing) {
+      DexApplication application, AppView<AppInfoWithLiveness> appView, Timing timing) {
     this.application = application;
-    this.appInfo = appInfo;
-    this.graphLense = graphLense;
+    this.appInfo = appView.getAppInfo();
+    this.graphLense = appView.getGraphLense();
     this.renamedMembersLense = VerticalClassMergerGraphLense.builder(appInfo);
     this.timing = timing;
 
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 6d16184..5cc07a4 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.GraphLense;
@@ -44,7 +45,7 @@
 
   private DexApplication program;
   DexItemFactory dexItemFactory;
-  private AppInfoWithSubtyping appInfo;
+  private AppView<AppInfoWithSubtyping> appView;
 
   NamingTestBase(
       String test,
@@ -61,7 +62,7 @@
   public void readApp() throws IOException, ExecutionException {
     program = ToolHelper.buildApplication(ImmutableList.of(appFileName));
     dexItemFactory = program.dexItemFactory;
-    appInfo = new AppInfoWithSubtyping(program);
+    appView = new AppView<>(new AppInfoWithSubtyping(program), GraphLense.getIdentityLense());
   }
 
   NamingLens runMinifier(List<Path> configPaths)
@@ -73,12 +74,12 @@
 
     ExecutorService executor = ThreadUtils.getExecutorService(1);
 
+    AppInfoWithSubtyping appInfo = appView.getAppInfo();
     RootSet rootSet = new RootSetBuilder(appInfo, program, configuration.getRules(), options)
         .run(executor);
 
     if (options.proguardConfiguration.isAccessModificationAllowed()) {
-      ClassAndMemberPublicizer.run(
-          executor, timing, program, appInfo, rootSet, GraphLense.getIdentityLense());
+      ClassAndMemberPublicizer.run(executor, timing, program, appView, rootSet);
       rootSet =
           new RootSetBuilder(appInfo, program, configuration.getRules(), options).run(executor);
     }