// 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.androidapi.AndroidApiLevelCompute;
import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.contexts.CompilationContext;
import com.android.tools.r8.contexts.CompilationContext.ProcessorContext;
import com.android.tools.r8.errors.dontwarn.DontWarnConfiguration;
import com.android.tools.r8.experimental.startup.StartupOrder;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.analysis.InitializedClassesInInstanceMethodsAnalysis.InitializedClassesInInstanceMethods;
import com.android.tools.r8.graph.classmerging.MergedClassesCollection;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
import com.android.tools.r8.horizontalclassmerging.HorizontallyMergedClasses;
import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraintFactory;
import com.android.tools.r8.ir.analysis.proto.EnumLiteProtoShrinker;
import com.android.tools.r8.ir.analysis.proto.GeneratedExtensionRegistryShrinker;
import com.android.tools.r8.ir.analysis.proto.GeneratedMessageLiteBuilderShrinker;
import com.android.tools.r8.ir.analysis.proto.GeneratedMessageLiteShrinker;
import com.android.tools.r8.ir.analysis.proto.ProtoShrinker;
import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
import com.android.tools.r8.ir.desugar.TypeRewriter;
import com.android.tools.r8.ir.optimize.enums.EnumDataMap;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoFactory;
import com.android.tools.r8.ir.optimize.library.LibraryMemberOptimizer;
import com.android.tools.r8.ir.optimize.library.LibraryMethodSideEffectModelCollection;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.naming.SeedMapper;
import com.android.tools.r8.optimize.argumentpropagation.ArgumentPropagator;
import com.android.tools.r8.optimize.interfaces.collection.OpenClosedInterfacesCollection;
import com.android.tools.r8.profile.art.ArtProfileCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.AssumeInfoCollection;
import com.android.tools.r8.shaking.KeepClassInfo;
import com.android.tools.r8.shaking.KeepFieldInfo;
import com.android.tools.r8.shaking.KeepInfoCollection;
import com.android.tools.r8.shaking.KeepMethodInfo;
import com.android.tools.r8.shaking.LibraryModeledPredicate;
import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.shaking.ProguardCompatibilityActions;
import com.android.tools.r8.shaking.RootSetUtils.MainDexRootSet;
import com.android.tools.r8.shaking.RootSetUtils.RootSet;
import com.android.tools.r8.synthesis.SyntheticItems;
import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.TestingOptions;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.Timing;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class AppView<T extends AppInfo> implements DexDefinitionSupplier, LibraryModeledPredicate {

  private enum WholeProgramOptimizations {
    ON,
    OFF
  }

  private T appInfo;
  private AppInfoWithClassHierarchy appInfoForDesugaring;
  private AppServices appServices;
  private ArtProfileCollection artProfileCollection;
  private AssumeInfoCollection assumeInfoCollection = AssumeInfoCollection.builder().build();
  private final DontWarnConfiguration dontWarnConfiguration;
  private final WholeProgramOptimizations wholeProgramOptimizations;
  private GraphLens codeLens = GraphLens.getIdentityLens();
  private GraphLens graphLens = GraphLens.getIdentityLens();
  private InitClassLens initClassLens;
  private NamingLens namingLens = NamingLens.getIdentityLens();
  private ProguardCompatibilityActions proguardCompatibilityActions;
  private RootSet rootSet;
  private MainDexRootSet mainDexRootSet = null;
  // This should preferably always be obtained via AppInfoWithLiveness.
  // Currently however the liveness may be downgraded thus loosing the computed keep info.
  private KeepInfoCollection keepInfo = null;

  private final AbstractValueFactory abstractValueFactory = new AbstractValueFactory();
  private final InstanceFieldInitializationInfoFactory instanceFieldInitializationInfoFactory =
      new InstanceFieldInitializationInfoFactory();
  private final SimpleInliningConstraintFactory simpleInliningConstraintFactory =
      new SimpleInliningConstraintFactory();

  // Desugaring.
  public final TypeRewriter typeRewriter;

  // Modeling.
  private final LibraryMethodSideEffectModelCollection libraryMethodSideEffectModelCollection;

  // Optimizations.
  private final ArgumentPropagator argumentPropagator;
  private final LibraryMemberOptimizer libraryMemberOptimizer;
  private final ProtoShrinker protoShrinker;

  // Optimization results.
  private boolean allCodeProcessed = false;
  private Predicate<DexType> classesEscapingIntoLibrary = Predicates.alwaysTrue();
  private InitializedClassesInInstanceMethods initializedClassesInInstanceMethods;
  private HorizontallyMergedClasses horizontallyMergedClasses = HorizontallyMergedClasses.empty();
  private VerticallyMergedClasses verticallyMergedClasses;
  private EnumDataMap unboxedEnums = null;
  private OpenClosedInterfacesCollection openClosedInterfacesCollection =
      OpenClosedInterfacesCollection.getDefault();
  // TODO(b/169115389): Remove
  private Set<DexMethod> cfByteCodePassThrough = ImmutableSet.of();
  private final Map<DexType, DexValueString> sourceDebugExtensions = new IdentityHashMap<>();
  private final Map<DexType, String> sourceFileForPrunedTypes = new IdentityHashMap<>();

  private SeedMapper applyMappingSeedMapper;

  // When input has been (partially) desugared these are the classes which has been library
  // desugared. This information is populated in the IR converter.
  private Set<DexType> alreadyLibraryDesugared = null;

  private final CompilationContext context;

  private final Thread mainThread = Thread.currentThread();

  private final AndroidApiLevelCompute apiLevelCompute;
  private final ComputedApiLevel computedMinApiLevel;

  private AppView(
      T appInfo,
      ArtProfileCollection artProfileCollection,
      WholeProgramOptimizations wholeProgramOptimizations,
      TypeRewriter mapper) {
    this(appInfo, artProfileCollection, wholeProgramOptimizations, mapper, Timing.empty());
  }

  private AppView(
      T appInfo,
      ArtProfileCollection artProfileCollection,
      WholeProgramOptimizations wholeProgramOptimizations,
      TypeRewriter mapper,
      Timing timing) {
    assert appInfo != null;
    this.appInfo = appInfo;
    this.context =
        timing.time(
            "Compilation context", () -> CompilationContext.createInitialContext(options()));
    this.artProfileCollection = artProfileCollection;
    this.dontWarnConfiguration =
        timing.time(
            "Dont warn config",
            () -> DontWarnConfiguration.create(options().getProguardConfiguration()));
    this.wholeProgramOptimizations = wholeProgramOptimizations;
    this.initClassLens = timing.time("Init class lens", InitClassLens::getThrowingInstance);
    this.typeRewriter = mapper;
    timing.begin("Create argument propagator");
    if (enableWholeProgramOptimizations() && options().callSiteOptimizationOptions().isEnabled()) {
      this.argumentPropagator = new ArgumentPropagator(withLiveness());
    } else {
      this.argumentPropagator = null;
    }
    timing.end();
    this.libraryMethodSideEffectModelCollection =
        timing.time("Library side-effects", () -> new LibraryMethodSideEffectModelCollection(this));
    this.libraryMemberOptimizer =
        timing.time("Library optimizer", () -> new LibraryMemberOptimizer(this, timing));
    this.protoShrinker = timing.time("Proto shrinker", () -> ProtoShrinker.create(withLiveness()));
    this.apiLevelCompute =
        timing.time("ApiLevel compute", () -> AndroidApiLevelCompute.create(this));
    this.computedMinApiLevel =
        timing.time(
            "ApiLevel computed", () -> apiLevelCompute.computeInitialMinApiLevel(options()));
  }

  public boolean verifyMainThread() {
    assert mainThread == Thread.currentThread();
    return true;
  }

  @Override
  public boolean isModeled(DexType type) {
    return libraryMemberOptimizer.isModeled(type);
  }

  private static <T extends AppInfo> TypeRewriter defaultTypeRewriter(T appInfo) {
    InternalOptions options = appInfo.options();
    return options.getTypeRewriter();
  }

  public static <T extends AppInfo> AppView<T> createForD8(T appInfo) {
    return new AppView<>(
        appInfo,
        ArtProfileCollection.createInitialArtProfileCollection(appInfo.options()),
        WholeProgramOptimizations.OFF,
        defaultTypeRewriter(appInfo));
  }

  public static <T extends AppInfo> AppView<T> createForSimulatingD8InR8(T appInfo) {
    return new AppView<>(
        appInfo,
        ArtProfileCollection.empty(),
        WholeProgramOptimizations.OFF,
        defaultTypeRewriter(appInfo));
  }

  public static <T extends AppInfo> AppView<T> createForD8(
      T appInfo, TypeRewriter mapper, Timing timing) {
    return new AppView<>(
        appInfo,
        ArtProfileCollection.createInitialArtProfileCollection(appInfo.options()),
        WholeProgramOptimizations.OFF,
        mapper,
        timing);
  }

  public static AppView<AppInfoWithClassHierarchy> createForR8(DexApplication application) {
    return createForR8(application, MainDexInfo.none());
  }

  public static AppView<AppInfoWithClassHierarchy> createForR8(
      DexApplication application, MainDexInfo mainDexInfo) {
    ClassToFeatureSplitMap classToFeatureSplitMap =
        ClassToFeatureSplitMap.createInitialClassToFeatureSplitMap(application.options);
    StartupOrder startupOrder = StartupOrder.createInitialStartupOrderForR8(application);
    AppInfoWithClassHierarchy appInfo =
        AppInfoWithClassHierarchy.createInitialAppInfoWithClassHierarchy(
            application,
            classToFeatureSplitMap,
            mainDexInfo,
            GlobalSyntheticsStrategy.forSingleOutputMode(),
            startupOrder);
    return new AppView<>(
        appInfo,
        ArtProfileCollection.createInitialArtProfileCollection(application.options),
        WholeProgramOptimizations.ON,
        defaultTypeRewriter(appInfo));
  }

  public static <T extends AppInfo> AppView<T> createForL8(T appInfo, TypeRewriter mapper) {
    return new AppView<>(
        appInfo,
        ArtProfileCollection.createInitialArtProfileCollection(appInfo.options()),
        WholeProgramOptimizations.OFF,
        mapper);
  }

  public static <T extends AppInfo> AppView<T> createForRelocator(T appInfo) {
    return new AppView<>(
        appInfo,
        ArtProfileCollection.empty(),
        WholeProgramOptimizations.OFF,
        defaultTypeRewriter(appInfo));
  }

  public static AppView<AppInfoWithClassHierarchy> createForTracer(
      AppInfoWithClassHierarchy appInfo) {
    return new AppView<>(
        appInfo,
        ArtProfileCollection.empty(),
        WholeProgramOptimizations.ON,
        defaultTypeRewriter(appInfo));
  }

  public AbstractValueFactory abstractValueFactory() {
    return abstractValueFactory;
  }

  public InstanceFieldInitializationInfoFactory instanceFieldInitializationInfoFactory() {
    return instanceFieldInitializationInfoFactory;
  }

  public SimpleInliningConstraintFactory simpleInliningConstraintFactory() {
    return simpleInliningConstraintFactory;
  }

  public DexApplication app() {
    return appInfo().app();
  }

  public T appInfo() {
    assert !appInfo.hasClassHierarchy() || enableWholeProgramOptimizations();
    return appInfo;
  }

  public AppInfoWithClassHierarchy appInfoWithClassHierarchy() {
    return hasClassHierarchy() ? appInfo.withClassHierarchy() : null;
  }

  public AppInfoWithLiveness appInfoWithLiveness() {
    return hasLiveness() ? appInfo.withLiveness() : null;
  }

  public AppInfoWithClassHierarchy appInfoForDesugaring() {
    if (enableWholeProgramOptimizations()) {
      assert appInfo.hasClassHierarchy();
      return appInfo.withClassHierarchy();
    }
    assert !appInfo.hasClassHierarchy();
    if (appInfoForDesugaring == null) {
      appInfoForDesugaring = AppInfoWithClassHierarchy.createForDesugaring(appInfo());
    }
    return appInfoForDesugaring;
  }

  private void unsetAppInfoForDesugaring() {
    appInfoForDesugaring = null;
  }

  public <U extends T> AppView<U> setAppInfo(U appInfo) {
    assert !appInfo.isObsolete();
    AppInfo previous = this.appInfo;
    this.appInfo = appInfo;
    unsetAppInfoForDesugaring();
    if (appInfo != previous) {
      previous.markObsolete();
    }
    if (appInfo.hasLiveness()) {
      keepInfo = appInfo.withLiveness().getKeepInfo();
    }
    @SuppressWarnings("unchecked")
    AppView<U> appViewWithSpecializedAppInfo = (AppView<U>) this;
    return appViewWithSpecializedAppInfo;
  }

  public boolean isAllCodeProcessed() {
    return allCodeProcessed;
  }

  public void setAllCodeProcessed() {
    allCodeProcessed = true;
  }

  public GraphLens clearCodeRewritings() {
    GraphLens newLens = graphLens.withCodeRewritingsApplied(dexItemFactory());
    setGraphLens(newLens);
    return newLens;
  }

  public AppServices appServices() {
    return appServices;
  }

  public void setAppServices(AppServices appServices) {
    this.appServices = appServices;
  }

  public ArtProfileCollection getArtProfileCollection() {
    return artProfileCollection;
  }

  public void setArtProfileCollection(ArtProfileCollection artProfileCollection) {
    this.artProfileCollection = artProfileCollection;
  }

  public AssumeInfoCollection getAssumeInfoCollection() {
    return assumeInfoCollection;
  }

  public void setAssumeInfoCollection(AssumeInfoCollection assumeInfoCollection) {
    this.assumeInfoCollection = assumeInfoCollection;
  }

  public DontWarnConfiguration getDontWarnConfiguration() {
    return dontWarnConfiguration;
  }

  public boolean isClassEscapingIntoLibrary(DexType type) {
    assert type.isClassType();
    return classesEscapingIntoLibrary.test(type);
  }

  public void setClassesEscapingIntoLibrary(Predicate<DexType> classesEscapingIntoLibrary) {
    this.classesEscapingIntoLibrary = classesEscapingIntoLibrary;
  }

  public void setSourceDebugExtensionForType(DexClass clazz, DexValueString sourceDebugExtension) {
    sourceDebugExtensions.put(clazz.type, sourceDebugExtension);
  }

  public DexValueString getSourceDebugExtensionForType(DexClass clazz) {
    return sourceDebugExtensions.get(clazz.type);
  }

  @Override
  public ClassResolutionResult contextIndependentDefinitionForWithResolutionResult(DexType type) {
    return appInfo().contextIndependentDefinitionForWithResolutionResult(type);
  }

  @Override
  public final DexClass definitionFor(DexType type) {
    return appInfo().definitionFor(type);
  }

  public OptionalBool isInterface(DexType type) {
    assert type.isClassType();
    // Without whole program information we should not assume anything about any other class than
    // the current holder in a given context.
    if (enableWholeProgramOptimizations()) {
      DexClass clazz = definitionFor(type);
      if (clazz == null) {
        return OptionalBool.unknown();
      }
      return OptionalBool.of(clazz.isInterface());
    }
    return OptionalBool.unknown();
  }

  @Override
  public DexItemFactory dexItemFactory() {
    return appInfo.dexItemFactory();
  }

  public boolean enableWholeProgramOptimizations() {
    return wholeProgramOptimizations == WholeProgramOptimizations.ON;
  }

  /**
   * Create a new processor context.
   *
   * <p>The order of processor contexts for a compilation must be deterministic so this is required
   * to be called on the main thread only.
   */
  public ProcessorContext createProcessorContext() {
    assert verifyMainThread();
    return context.createProcessorContext();
  }

  public SyntheticItems getSyntheticItems() {
    return appInfo.getSyntheticItems();
  }

  public <E extends Throwable> void withArgumentPropagator(
      ThrowingConsumer<ArgumentPropagator, E> consumer) throws E {
    if (argumentPropagator != null) {
      consumer.accept(argumentPropagator);
    }
  }

  public LibraryMemberOptimizer libraryMethodOptimizer() {
    return libraryMemberOptimizer;
  }

  public LibraryMethodSideEffectModelCollection getLibraryMethodSideEffectModelCollection() {
    return libraryMethodSideEffectModelCollection;
  }

  public ProtoShrinker protoShrinker() {
    return protoShrinker;
  }

  public <E extends Throwable> void withProtoShrinker(ThrowingConsumer<ProtoShrinker, E> consumer)
      throws E {
    if (protoShrinker != null) {
      consumer.accept(protoShrinker);
    }
  }

  public <U> U withProtoShrinker(Function<ProtoShrinker, U> consumer, U defaultValue) {
    if (protoShrinker != null) {
      return consumer.apply(protoShrinker);
    }
    return defaultValue;
  }

  public <U> U withProtoEnumShrinker(Function<EnumLiteProtoShrinker, U> fn, U defaultValue) {
    if (protoShrinker != null && options().protoShrinking().isEnumLiteProtoShrinkingEnabled()) {
      return fn.apply(protoShrinker.enumLiteProtoShrinker);
    }
    return defaultValue;
  }

  public <E extends Throwable> void withGeneratedExtensionRegistryShrinker(
      ThrowingConsumer<GeneratedExtensionRegistryShrinker, E> consumer) throws E {
    if (protoShrinker != null && protoShrinker.generatedExtensionRegistryShrinker != null) {
      consumer.accept(protoShrinker.generatedExtensionRegistryShrinker);
    }
  }

  public <U> U withGeneratedExtensionRegistryShrinker(
      Function<GeneratedExtensionRegistryShrinker, U> fn, U defaultValue) {
    if (protoShrinker != null && protoShrinker.generatedExtensionRegistryShrinker != null) {
      return fn.apply(protoShrinker.generatedExtensionRegistryShrinker);
    }
    return defaultValue;
  }

  public <E extends Throwable> void withGeneratedMessageLiteShrinker(
      ThrowingConsumer<GeneratedMessageLiteShrinker, E> consumer) throws E {
    if (protoShrinker != null && protoShrinker.generatedMessageLiteShrinker != null) {
      consumer.accept(protoShrinker.generatedMessageLiteShrinker);
    }
  }

  public <E extends Throwable> void withGeneratedMessageLiteBuilderShrinker(
      ThrowingConsumer<GeneratedMessageLiteBuilderShrinker, E> consumer) throws E {
    if (protoShrinker != null && protoShrinker.generatedMessageLiteBuilderShrinker != null) {
      consumer.accept(protoShrinker.generatedMessageLiteBuilderShrinker);
    }
  }

  public <U> U withGeneratedMessageLiteShrinker(
      Function<GeneratedMessageLiteShrinker, U> fn, U defaultValue) {
    if (protoShrinker != null && protoShrinker.generatedMessageLiteShrinker != null) {
      return fn.apply(protoShrinker.generatedMessageLiteShrinker);
    }
    return defaultValue;
  }

  public <U> U withGeneratedMessageLiteBuilderShrinker(
      Function<GeneratedMessageLiteBuilderShrinker, U> fn, U defaultValue) {
    if (protoShrinker != null && protoShrinker.generatedMessageLiteBuilderShrinker != null) {
      return fn.apply(protoShrinker.generatedMessageLiteBuilderShrinker);
    }
    return defaultValue;
  }

  public GraphLens codeLens() {
    return codeLens;
  }

  public void setCodeLens(GraphLens codeLens) {
    this.codeLens = codeLens;
  }

  public GraphLens graphLens() {
    return graphLens;
  }

  /** @return true if the graph lens changed, otherwise false. */
  public boolean setGraphLens(GraphLens graphLens) {
    if (graphLens != this.graphLens) {
      this.graphLens = graphLens;

      // TODO(b/202368283): Currently, we always set an applied lens or a clear code rewriting lens
      //  when the graph lens has been fully applied to all code. Therefore, we implicitly update
      //  the code lens when these lenses are set. Now that we have an explicit code lens, the clear
      //  code rewriting lens is redundant and could be removed.
      if (graphLens.isAppliedLens() || graphLens.isClearCodeRewritingLens()) {
        setCodeLens(graphLens);
      }
      return true;
    }
    return false;
  }

  public boolean canUseInitClass() {
    return options().isShrinking() && !initClassLens.isFinal();
  }

  public InitClassLens initClassLens() {
    return initClassLens;
  }

  public boolean hasInitClassLens() {
    return initClassLens != null;
  }

  public void setInitClassLens(InitClassLens initClassLens) {
    this.initClassLens = initClassLens;
  }

  public void setInitializedClassesInInstanceMethods(
      InitializedClassesInInstanceMethods initializedClassesInInstanceMethods) {
    this.initializedClassesInInstanceMethods = initializedClassesInInstanceMethods;
  }

  public void setCfByteCodePassThrough(Set<DexMethod> cfByteCodePassThrough) {
    this.cfByteCodePassThrough = cfByteCodePassThrough;
  }

  public <U> U withInitializedClassesInInstanceMethods(
      Function<InitializedClassesInInstanceMethods, U> fn, U defaultValue) {
    if (initializedClassesInInstanceMethods != null) {
      return fn.apply(initializedClassesInInstanceMethods);
    }
    return defaultValue;
  }

  public InternalOptions options() {
    return appInfo.options();
  }

  public Reporter reporter() {
    return options().reporter;
  }

  public TestingOptions testing() {
    return options().testing;
  }

  public boolean hasRootSet() {
    return rootSet != null;
  }

  public RootSet rootSet() {
    return rootSet;
  }

  public void setRootSet(RootSet rootSet) {
    this.rootSet = rootSet;
  }

  public void setMainDexRootSet(MainDexRootSet mainDexRootSet) {
    assert mainDexRootSet != null : "Root set should never be recomputed";
    this.mainDexRootSet = mainDexRootSet;
  }

  public boolean hasMainDexRootSet() {
    return mainDexRootSet != null;
  }

  public MainDexRootSet getMainDexRootSet() {
    return mainDexRootSet;
  }

  public KeepInfoCollection getKeepInfo() {
    return keepInfo;
  }

  public KeepClassInfo getKeepInfo(DexProgramClass clazz) {
    return getKeepInfo().getClassInfo(clazz);
  }

  public KeepFieldInfo getKeepInfo(ProgramField field) {
    return getKeepInfo().getFieldInfo(field);
  }

  public KeepMethodInfo getKeepInfo(ProgramMethod method) {
    return getKeepInfo().getMethodInfo(method);
  }

  public NamingLens getNamingLens() {
    return namingLens;
  }

  public void setNamingLens(NamingLens namingLens) {
    this.namingLens = namingLens;
  }

  public boolean hasProguardCompatibilityActions() {
    return proguardCompatibilityActions != null;
  }

  public ProguardCompatibilityActions getProguardCompatibilityActions() {
    return proguardCompatibilityActions;
  }

  public void setProguardCompatibilityActions(
      ProguardCompatibilityActions proguardCompatibilityActions) {
    assert options().forceProguardCompatibility;
    this.proguardCompatibilityActions = proguardCompatibilityActions;
  }

  public MergedClassesCollection allMergedClasses() {
    MergedClassesCollection collection = new MergedClassesCollection();
    if (hasHorizontallyMergedClasses()) {
      collection.add(horizontallyMergedClasses);
    }
    if (verticallyMergedClasses != null) {
      collection.add(verticallyMergedClasses);
    }
    return collection;
  }

  public boolean hasHorizontallyMergedClasses() {
    return !horizontallyMergedClasses.isEmpty();
  }

  /**
   * Get the result of horizontal class merging. Returns null if horizontal class merging has not
   * been run.
   */
  public HorizontallyMergedClasses horizontallyMergedClasses() {
    return horizontallyMergedClasses;
  }

  public void setHorizontallyMergedClasses(
      HorizontallyMergedClasses horizontallyMergedClasses, HorizontalClassMerger.Mode mode) {
    assert !hasHorizontallyMergedClasses() || mode.isFinal();
    this.horizontallyMergedClasses = horizontallyMergedClasses().extend(horizontallyMergedClasses);
    if (mode.isFinal()) {
      testing()
          .horizontallyMergedClassesConsumer
          .accept(dexItemFactory(), horizontallyMergedClasses());
    }
  }

  public boolean hasVerticallyMergedClasses() {
    return verticallyMergedClasses != null;
  }

  /**
   * Get the result of vertical class merging. Returns null if vertical class merging has not been
   * run.
   */
  public VerticallyMergedClasses verticallyMergedClasses() {
    return verticallyMergedClasses;
  }

  public void setVerticallyMergedClasses(VerticallyMergedClasses verticallyMergedClasses) {
    assert this.verticallyMergedClasses == null;
    this.verticallyMergedClasses = verticallyMergedClasses;
    testing().verticallyMergedClassesConsumer.accept(dexItemFactory(), verticallyMergedClasses);
  }

  public OpenClosedInterfacesCollection getOpenClosedInterfacesCollection() {
    return openClosedInterfacesCollection;
  }

  public void setOpenClosedInterfacesCollection(
      OpenClosedInterfacesCollection openClosedInterfacesCollection) {
    this.openClosedInterfacesCollection = openClosedInterfacesCollection;
  }

  public boolean hasUnboxedEnums() {
    return unboxedEnums != null;
  }

  public EnumDataMap unboxedEnums() {
    return hasUnboxedEnums() ? unboxedEnums : EnumDataMap.empty();
  }

  public void setUnboxedEnums(EnumDataMap unboxedEnums) {
    assert !hasUnboxedEnums();
    this.unboxedEnums = unboxedEnums;
    testing().unboxedEnumsConsumer.accept(dexItemFactory(), unboxedEnums);
  }

  public boolean validateUnboxedEnumsHaveBeenPruned() {
    for (DexType unboxedEnum : unboxedEnums.getUnboxedEnums()) {
      assert appInfo.definitionForWithoutExistenceAssert(unboxedEnum) == null
          : "Enum " + unboxedEnum + " has been unboxed but is still in the program.";
      assert appInfo().withLiveness().wasPruned(unboxedEnum)
          : "Enum " + unboxedEnum + " has been unboxed but was not pruned.";
    }
    return true;
  }

  public boolean hasClassHierarchy() {
    return appInfo().hasClassHierarchy();
  }

  @SuppressWarnings("unchecked")
  public AppView<AppInfoWithClassHierarchy> withClassHierarchy() {
    return appInfo.hasClassHierarchy()
        ? (AppView<AppInfoWithClassHierarchy>) this
        : null;
  }

  @SuppressWarnings("unchecked")
  public AppView<AppInfo> withoutClassHierarchy() {
    assert !hasClassHierarchy();
    return (AppView<AppInfo>) this;
  }

  public boolean hasLiveness() {
    return appInfo().hasLiveness();
  }

  public AppView<AppInfoWithLiveness> withLiveness() {
    @SuppressWarnings("unchecked")
    AppView<AppInfoWithLiveness> appViewWithLiveness = (AppView<AppInfoWithLiveness>) this;
    return appViewWithLiveness;
  }

  public OptionalBool isSubtype(DexType subtype, DexType supertype) {
    // Even if we can compute isSubtype by having class hierarchy we may not be allowed to ask the
    // question for all code paths in D8. Having the check for liveness ensure that we are in R8
    // territory.
    if (hasClassHierarchy()) {
      return OptionalBool.of(appInfo().withClassHierarchy().isSubtype(subtype, supertype));
    }
    if (subtype == supertype || supertype == dexItemFactory().objectType) {
      return OptionalBool.TRUE;
    }
    return OptionalBool.unknown();
  }

  public boolean isCfByteCodePassThrough(DexEncodedMethod method) {
    if (!options().isGeneratingClassFiles()) {
      return false;
    }
    if (cfByteCodePassThrough.contains(method.getReference())) {
      return true;
    }
    return options().testing.cfByteCodePassThrough != null
        && options().testing.cfByteCodePassThrough.test(method.getReference());
  }

  public boolean hasCfByteCodePassThroughMethods() {
    return !cfByteCodePassThrough.isEmpty();
  }

  public void pruneItems(PrunedItems prunedItems, ExecutorService executorService)
      throws ExecutionException {
    if (prunedItems.isEmpty()) {
      assert appInfo().app() == prunedItems.getPrunedApp();
      return;
    }
    if (appInfo.hasLiveness()) {
      AppView<AppInfoWithLiveness> self = withLiveness();
      self.setAppInfo(self.appInfo().prunedCopyFrom(prunedItems, executorService));
    } else if (appInfo.hasClassHierarchy()) {
      AppView<AppInfoWithClassHierarchy> self = withClassHierarchy();
      self.setAppInfo(self.appInfo().prunedCopyFrom(prunedItems, executorService));
    } else {
      pruneAppInfo(prunedItems, this, executorService);
    }
    if (appServices() != null) {
      setAppServices(appServices().prunedCopy(prunedItems));
    }
    setArtProfileCollection(getArtProfileCollection().withoutPrunedItems(prunedItems));
    setAssumeInfoCollection(getAssumeInfoCollection().withoutPrunedItems(prunedItems));
    if (hasProguardCompatibilityActions()) {
      setProguardCompatibilityActions(
          getProguardCompatibilityActions().withoutPrunedItems(prunedItems));
    }
    if (hasRootSet()) {
      rootSet.pruneItems(prunedItems);
    }
    if (hasMainDexRootSet()) {
      setMainDexRootSet(mainDexRootSet.withoutPrunedItems(prunedItems));
    }
    setOpenClosedInterfacesCollection(
        openClosedInterfacesCollection.withoutPrunedItems(prunedItems));
  }

  @SuppressWarnings("unchecked")
  private static void pruneAppInfo(
      PrunedItems prunedItems, AppView<?> appView, ExecutorService executorService)
      throws ExecutionException {
    ((AppView<AppInfo>) appView)
        .setAppInfo(appView.appInfo().prunedCopyFrom(prunedItems, executorService));
  }

  public void rewriteWithLens(NonIdentityGraphLens lens) {
    if (lens != null) {
      rewriteWithLens(lens, appInfo().app().asDirect(), withClassHierarchy(), lens.getPrevious());
    }
  }

  public void rewriteWithLensAndApplication(
      NonIdentityGraphLens lens, DirectMappedDexApplication application) {
    rewriteWithLensAndApplication(lens, application, lens.getPrevious());
  }

  public void rewriteWithLensAndApplication(
      NonIdentityGraphLens lens, DirectMappedDexApplication application, GraphLens appliedLens) {
    assert lens != null;
    assert application != null;
    rewriteWithLens(lens, application, withClassHierarchy(), appliedLens);
  }

  private static void rewriteWithLens(
      NonIdentityGraphLens lens,
      DirectMappedDexApplication application,
      AppView<? extends AppInfoWithClassHierarchy> appView,
      GraphLens appliedLens) {
    if (lens == null) {
      return;
    }

    boolean changed = appView.setGraphLens(lens);
    assert changed;
    assert application.verifyWithLens(appView.appInfo().app().asDirect(), lens);

    // The application has already been rewritten with the given applied lens. Therefore, we
    // temporarily replace that lens with a lens that does not have any rewritings to avoid the
    // overhead of traversing the entire lens chain upon each lookup during the rewriting.
    NonIdentityGraphLens firstUnappliedLens = lens;
    while (firstUnappliedLens.getPrevious() != appliedLens) {
      GraphLens previousLens = firstUnappliedLens.getPrevious();
      assert previousLens.isNonIdentityLens();
      assert previousLens != appView.codeLens();
      firstUnappliedLens = previousLens.asNonIdentityLens();
    }

    // Insert a member rebinding lens above the first unapplied lens.
    // TODO(b/182129249): Once the member rebinding phase has been removed, the MemberRebindingLens
    //  should be removed and all uses of FieldRebindingIdentityLens should be replaced by
    //  MemberRebindingIdentityLens.
    GraphLens newMemberRebindingLens = GraphLens.getIdentityLens();
    if (!firstUnappliedLens.isMemberRebindingLens()
        && !firstUnappliedLens.isMemberRebindingIdentityLens()) {
      NonIdentityGraphLens appliedMemberRebindingLens =
          firstUnappliedLens.findPreviousUntil(
              previous ->
                  previous.isMemberRebindingLens() || previous.isMemberRebindingIdentityLens(),
              previous -> previous == appView.codeLens());
      if (appliedMemberRebindingLens != null) {
        newMemberRebindingLens =
            appliedMemberRebindingLens.isMemberRebindingLens()
                ? appliedMemberRebindingLens
                    .asMemberRebindingLens()
                    .toRewrittenFieldRebindingLens(appView, appliedLens, appliedMemberRebindingLens)
                : appliedMemberRebindingLens
                    .asMemberRebindingIdentityLens()
                    .toRewrittenMemberRebindingIdentityLens(
                        appView, appliedLens, appliedMemberRebindingLens);
      }
    }

    firstUnappliedLens.withAlternativeParentLens(
        newMemberRebindingLens,
        () -> {
          if (appView.hasLiveness()) {
            appView
                .withLiveness()
                .setAppInfo(appView.appInfoWithLiveness().rewrittenWithLens(application, lens));
          }
          appView.setAppServices(appView.appServices().rewrittenWithLens(lens));
          appView.setArtProfileCollection(
              appView.getArtProfileCollection().rewrittenWithLens(lens));
          appView.setAssumeInfoCollection(
              appView.getAssumeInfoCollection().rewrittenWithLens(appView, lens));
          if (appView.hasInitClassLens()) {
            appView.setInitClassLens(appView.initClassLens().rewrittenWithLens(lens));
          }
          if (appView.hasProguardCompatibilityActions()) {
            appView.setProguardCompatibilityActions(
                appView.getProguardCompatibilityActions().rewrittenWithLens(lens));
          }
          if (appView.hasMainDexRootSet()) {
            appView.setMainDexRootSet(appView.getMainDexRootSet().rewrittenWithLens(lens));
          }
          appView.setOpenClosedInterfacesCollection(
              appView.getOpenClosedInterfacesCollection().rewrittenWithLens(lens));
          if (appView.hasRootSet()) {
            appView.setRootSet(appView.rootSet().rewrittenWithLens(lens));
          }
        });
  }

  public void setAlreadyLibraryDesugared(Set<DexType> alreadyLibraryDesugared) {
    assert this.alreadyLibraryDesugared == null;
    this.alreadyLibraryDesugared = alreadyLibraryDesugared;
  }

  public boolean isAlreadyLibraryDesugared(DexProgramClass clazz) {
    if (!options().desugarSpecificOptions().allowAllDesugaredInput) {
      return false;
    }
    assert alreadyLibraryDesugared != null;
    return alreadyLibraryDesugared.contains(clazz.getType());
  }

  public void loadApplyMappingSeedMapper() throws IOException {
    if (options().getProguardConfiguration().hasApplyMappingFile()) {
      applyMappingSeedMapper =
          SeedMapper.seedMapperFromFile(
              options().reporter, options().getProguardConfiguration().getApplyMappingFile());
    }
  }

  public SeedMapper getApplyMappingSeedMapper() {
    return applyMappingSeedMapper;
  }

  public void clearApplyMappingSeedMapper() {
    applyMappingSeedMapper = null;
  }

  public boolean checkForTesting(Supplier<Boolean> test) {
    return testing().enableTestAssertions ? test.get() : true;
  }

  public AndroidApiLevelCompute apiLevelCompute() {
    return apiLevelCompute;
  }

  public ComputedApiLevel computedMinApiLevel() {
    return computedMinApiLevel;
  }

  public void addPrunedClassSourceFile(DexType prunedType, String sourceFile) {
    sourceFileForPrunedTypes.put(prunedType, sourceFile);
  }

  public String getPrunedClassSourceFileInfo(DexType dexType) {
    return sourceFileForPrunedTypes.get(dexType);
  }
}
