// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;

import static com.android.tools.r8.kotlin.KotlinMetadataUtils.getNoKotlinInfo;
import static com.google.common.base.Predicates.alwaysTrue;

import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
import com.android.tools.r8.graph.MethodCollection.MethodCollectionFactory;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.synthesis.SyntheticMarker;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.TraversalContinuation;
import com.android.tools.r8.utils.structural.Ordered;
import com.android.tools.r8.utils.structural.StructuralItem;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class DexProgramClass extends DexClass
    implements ProgramClass, Supplier<DexProgramClass>, StructuralItem<DexProgramClass> {

  @FunctionalInterface
  public interface ChecksumSupplier {
    long getChecksum(DexProgramClass programClass);
  }

  public static final DexProgramClass[] EMPTY_ARRAY = {};

  private final ProgramResource.Kind originKind;
  private CfVersion initialClassFileVersion = null;
  private boolean deprecated = false;
  private KotlinClassLevelInfo kotlinInfo = getNoKotlinInfo();
  private OptionalBool reachabilitySensitive = OptionalBool.unknown();

  private final ChecksumSupplier checksumSupplier;

  private SyntheticMarker syntheticMarker;

  public DexProgramClass(
      DexType type,
      Kind originKind,
      Origin origin,
      ClassAccessFlags accessFlags,
      DexType superType,
      DexTypeList interfaces,
      DexString sourceFile,
      NestHostClassAttribute nestHost,
      List<NestMemberClassAttribute> nestMembers,
      List<PermittedSubclassAttribute> permittedSubclasses,
      List<RecordComponentInfo> recordComponents,
      EnclosingMethodAttribute enclosingMember,
      List<InnerClassAttribute> innerClasses,
      ClassSignature classSignature,
      DexAnnotationSet classAnnotations,
      DexEncodedField[] staticFields,
      DexEncodedField[] instanceFields,
      MethodCollectionFactory methodCollectionFactory,
      boolean skipNameValidationForTesting,
      ChecksumSupplier checksumSupplier,
      SyntheticMarker syntheticMarker) {
    super(
        sourceFile,
        interfaces,
        accessFlags,
        superType,
        type,
        staticFields,
        instanceFields,
        methodCollectionFactory,
        nestHost,
        nestMembers,
        permittedSubclasses,
        recordComponents,
        enclosingMember,
        innerClasses,
        classSignature,
        classAnnotations,
        origin,
        skipNameValidationForTesting);
    assert checksumSupplier != null;
    assert classAnnotations != null;
    this.originKind = originKind;
    this.checksumSupplier = checksumSupplier;
    this.syntheticMarker = syntheticMarker;
  }

  public DexProgramClass(
      DexType type,
      Kind originKind,
      Origin origin,
      ClassAccessFlags accessFlags,
      DexType superType,
      DexTypeList interfaces,
      DexString sourceFile,
      NestHostClassAttribute nestHost,
      List<NestMemberClassAttribute> nestMembers,
      List<PermittedSubclassAttribute> permittedSubclasses,
      List<RecordComponentInfo> recordComponents,
      EnclosingMethodAttribute enclosingMember,
      List<InnerClassAttribute> innerClasses,
      ClassSignature classSignature,
      DexAnnotationSet classAnnotations,
      DexEncodedField[] staticFields,
      DexEncodedField[] instanceFields,
      MethodCollectionFactory methodCollectionFactory,
      boolean skipNameValidationForTesting,
      ChecksumSupplier checksumSupplier) {
    this(
        type,
        originKind,
        origin,
        accessFlags,
        superType,
        interfaces,
        sourceFile,
        nestHost,
        nestMembers,
        permittedSubclasses,
        recordComponents,
        enclosingMember,
        innerClasses,
        classSignature,
        classAnnotations,
        staticFields,
        instanceFields,
        methodCollectionFactory,
        skipNameValidationForTesting,
        checksumSupplier,
        null);
  }

  public static DexProgramClass createMockClassForTesting(DexItemFactory dexItemFactory) {
    return new DexProgramClass(
        dexItemFactory.createType("LMock;"),
        null,
        Origin.unknown(),
        ClassAccessFlags.fromSharedAccessFlags(0),
        dexItemFactory.objectType,
        DexTypeList.empty(),
        null,
        null,
        Collections.emptyList(),
        Collections.emptyList(),
        Collections.emptyList(),
        null,
        Collections.emptyList(),
        ClassSignature.noSignature(),
        DexAnnotationSet.empty(),
        DexEncodedField.EMPTY_ARRAY,
        DexEncodedField.EMPTY_ARRAY,
        MethodCollectionFactory.empty(),
        false,
        DexProgramClass::invalidChecksumRequest);
  }

  @Override
  public void accept(
      Consumer<DexProgramClass> programClassConsumer,
      Consumer<DexClasspathClass> classpathClassConsumer,
      Consumer<DexLibraryClass> libraryClassConsumer) {
    programClassConsumer.accept(this);
  }

  @Override
  public DexProgramClass self() {
    return this;
  }

  @Override
  @SuppressWarnings("ReferenceEquality")
  public DexProgramClass getContext() {
    return this;
  }

  /**
   * Is the class reachability sensitive.
   *
   * <p>A class is reachability sensitive if the
   * dalvik.annotation.optimization.ReachabilitySensitive annotation is on any field or method. When
   * that is the case, dead reference elimination is disabled and locals are kept alive for their
   * entire scope.
   */
  public boolean getOrComputeReachabilitySensitive(AppView<?> appView) {
    if (reachabilitySensitive.isUnknown()) {
      reachabilitySensitive = OptionalBool.of(internalComputeReachabilitySensitive(appView));
    }
    return reachabilitySensitive.isTrue();
  }

  @SuppressWarnings("ReferenceEquality")
  private boolean internalComputeReachabilitySensitive(AppView<?> appView) {
    DexItemFactory dexItemFactory = appView.dexItemFactory();
    for (DexEncodedMember<?, ?> member : members()) {
      for (DexAnnotation annotation : member.annotations().annotations) {
        if (annotation.annotation.type == dexItemFactory.annotationReachabilitySensitive) {
          return true;
        }
      }
    }
    return false;
  }

  @Override
  public StructuralMapping<DexProgramClass> getStructuralMapping() {
    return DexProgramClass::specify;
  }

  public SyntheticMarker stripSyntheticInputMarker() {
    SyntheticMarker marker = syntheticMarker;
    // The synthetic input marker is "read once". It is stored only for identifying the input as
    // synthetic and amending it to the SyntheticItems collection. After identification this field
    // should not be used.
    syntheticMarker = null;
    return marker;
  }

  private static void specify(StructuralSpecification<DexProgramClass, ?> spec) {
    spec.withItem(c -> c.type)
        .withItem(c -> c.superType)
        .withItem(c -> c.interfaces)
        .withItem(c -> c.accessFlags)
        .withNullableItem(c -> c.sourceFile)
        .withNullableItem(c -> c.initialClassFileVersion)
        .withBool(c -> c.deprecated)
        .withNullableItem(DexClass::getNestHostClassAttribute)
        .withItemCollection(DexClass::getNestMembersClassAttributes)
        .withItem(DexDefinition::annotations)
        // TODO(b/158159959): Make signatures structural.
        .withAssert(c -> c.classSignature == ClassSignature.noSignature())
        .withItemCollection(DexClass::allFieldsSorted)
        .withItemCollection(DexClass::allMethodsSorted);
  }

  public void forEachProgramField(Consumer<? super ProgramField> consumer) {
    forEachProgramFieldMatching(alwaysTrue(), consumer);
  }

  public void forEachProgramFieldMatching(
      Predicate<? super DexEncodedField> predicate, Consumer<? super ProgramField> consumer) {
    forEachFieldMatching(predicate, field -> consumer.accept(new ProgramField(this, field)));
  }

  public void forEachProgramInstanceField(Consumer<? super ProgramField> consumer) {
    forEachInstanceField(field -> consumer.accept(new ProgramField(this, field)));
  }

  public void forEachProgramStaticField(Consumer<? super ProgramField> consumer) {
    forEachStaticField(field -> consumer.accept(new ProgramField(this, field)));
  }

  public void forEachProgramStaticFieldMatching(
      Predicate<? super DexEncodedField> predicate, Consumer<? super ProgramField> consumer) {
    forEachStaticFieldMatching(predicate, field -> consumer.accept(new ProgramField(this, field)));
  }

  public void forEachProgramStaticMethod(Consumer<? super ProgramMethod> consumer) {
    forEachProgramDirectMethodMatching(DexEncodedMethod::isStatic, consumer);
  }

  public void forEachProgramMember(Consumer<? super ProgramMember<?, ?>> consumer) {
    forEachProgramField(consumer);
    forEachProgramMethod(consumer);
  }

  public void forEachProgramMethod(Consumer<? super ProgramMethod> consumer) {
    forEachProgramMethodMatching(alwaysTrue(), consumer);
  }

  public void forEachProgramMethodMatching(
      Predicate<DexEncodedMethod> predicate, Consumer<? super ProgramMethod> consumer) {
    methodCollection.forEachMethodMatching(
        predicate, method -> consumer.accept(new ProgramMethod(this, method)));
  }

  public Iterable<ProgramMethod> programMethods() {
    return Iterables.concat(directProgramMethods(), virtualProgramMethods());
  }

  public Iterable<ProgramMethod> directProgramMethods() {
    return Iterables.transform(directMethods(), method -> new ProgramMethod(this, method));
  }

  public Iterable<ProgramMethod> directProgramMethods(Predicate<DexEncodedMethod> predicate) {
    return Iterables.transform(directMethods(predicate), method -> new ProgramMethod(this, method));
  }

  public Iterable<ProgramMethod> virtualProgramMethods() {
    return Iterables.transform(virtualMethods(), method -> new ProgramMethod(this, method));
  }

  public Iterable<ProgramMethod> virtualProgramMethods(Predicate<DexEncodedMethod> predicate) {
    return Iterables.transform(
        virtualMethods(predicate), method -> new ProgramMethod(this, method));
  }

  public Iterable<ProgramMethod> programInstanceInitializers() {
    return directProgramMethods(DexEncodedMethod::isInstanceInitializer);
  }

  public void forEachProgramDirectMethod(Consumer<ProgramMethod> consumer) {
    forEachProgramDirectMethodMatching(alwaysTrue(), consumer);
  }

  public void forEachProgramDirectMethodMatching(
      Predicate<DexEncodedMethod> predicate, Consumer<? super ProgramMethod> consumer) {
    methodCollection.forEachDirectMethodMatching(
        predicate, method -> consumer.accept(new ProgramMethod(this, method)));
  }

  public void forEachProgramInstanceInitializer(Consumer<ProgramMethod> consumer) {
    forEachProgramInstanceInitializerMatching(alwaysTrue(), consumer);
  }

  public void forEachProgramInstanceInitializerMatching(
      Predicate<DexEncodedMethod> predicate, Consumer<ProgramMethod> consumer) {
    forEachProgramDirectMethodMatching(
        method -> method.isInstanceInitializer() && predicate.test(method), consumer);
  }

  public void forEachProgramVirtualMethod(Consumer<ProgramMethod> consumer) {
    forEachProgramVirtualMethodMatching(alwaysTrue(), consumer);
  }

  public void forEachProgramVirtualMethodMatching(
      Predicate<DexEncodedMethod> predicate, Consumer<ProgramMethod> consumer) {
    methodCollection.forEachVirtualMethodMatching(
        predicate, method -> consumer.accept(new ProgramMethod(this, method)));
  }

  public ProgramMethod getProgramClassInitializer() {
    return toProgramMethodOrNull(getClassInitializer());
  }

  public void acceptProgramClassInitializer(Consumer<ProgramMethod> consumer) {
    if (hasClassInitializer()) {
      consumer.accept(getProgramClassInitializer());
    }
  }

  public ProgramMethod getProgramDefaultInitializer() {
    return getProgramInitializer(DexType.EMPTY_ARRAY);
  }

  public ProgramMethod getProgramInitializer(DexType[] types) {
    return toProgramMethodOrNull(getInitializer(types));
  }

  /** Find member in this class matching {@param member}. */
  @SuppressWarnings("unchecked")
  public <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
      ProgramMember<D, R> lookupProgramMember(DexMember<D, R> member) {
    ProgramMember<?, ?> definition =
        member.isDexField()
            ? lookupProgramField(member.asDexField())
            : lookupProgramMethod(member.asDexMethod());
    return (ProgramMember<D, R>) definition;
  }

  public ProgramField lookupProgramField(DexField reference) {
    return toProgramFieldOrNull(lookupField(reference));
  }

  public ProgramMethod lookupProgramMethod(DexMethod reference) {
    return toProgramMethodOrNull(getMethodCollection().getMethod(reference));
  }

  private ProgramField toProgramFieldOrNull(DexEncodedField field) {
    if (field != null) {
      return new ProgramField(this, field);
    }
    return null;
  }

  private ProgramMethod toProgramMethodOrNull(DexEncodedMethod method) {
    if (method != null) {
      return new ProgramMethod(this, method);
    }
    return null;
  }

  public TraversalContinuation<?, ?> traverseProgramMembers(
      Function<ProgramMember<?, ?>, TraversalContinuation<?, ?>> fn) {
    TraversalContinuation<?, ?> continuation = traverseProgramFields(fn);
    if (continuation.shouldContinue()) {
      return traverseProgramMethods(fn);
    }
    return TraversalContinuation.doBreak();
  }

  public TraversalContinuation<?, ?> traverseProgramFields(
      Function<? super ProgramField, TraversalContinuation<?, ?>> fn) {
    return getFieldCollection().traverse(field -> fn.apply(field.asProgramField()));
  }

  public <BT, CT> TraversalContinuation<BT, CT> traverseProgramFields(
      BiFunction<? super ProgramField, CT, TraversalContinuation<BT, CT>> fn, CT initialValue) {
    return getFieldCollection()
        .traverse((field, value) -> fn.apply(field.asProgramField(), value), initialValue);
  }

  public TraversalContinuation<?, ?> traverseProgramInstanceFields(
      Function<? super ProgramField, TraversalContinuation<?, ?>> fn) {
    return getFieldCollection().traverseInstanceFields(field -> fn.apply(field.asProgramField()));
  }

  public <BT, CT> TraversalContinuation<BT, CT> traverseProgramInstanceFields(
      BiFunction<? super ProgramField, CT, TraversalContinuation<BT, CT>> fn, CT initialValue) {
    return getFieldCollection()
        .traverseInstanceFields(
            (field, value) -> fn.apply(field.asProgramField(), value), initialValue);
  }

  public TraversalContinuation<?, ?> traverseProgramMethods(
      Function<? super ProgramMethod, TraversalContinuation<?, ?>> fn) {
    return getMethodCollection().traverse(method -> fn.apply(new ProgramMethod(this, method)));
  }

  public TraversalContinuation<?, ?> traverseProgramInstanceInitializers(
      Function<ProgramMethod, TraversalContinuation<?, ?>> fn) {
    return traverseProgramMethods(fn, DexEncodedMethod::isInstanceInitializer);
  }

  public TraversalContinuation<?, ?> traverseProgramMethods(
      Function<ProgramMethod, TraversalContinuation<?, ?>> fn,
      Predicate<DexEncodedMethod> predicate) {
    return getMethodCollection()
        .traverse(
            method ->
                predicate.test(method)
                    ? fn.apply(new ProgramMethod(this, method))
                    : TraversalContinuation.doContinue());
  }

  public Kind getOriginKind() {
    return originKind;
  }

  public boolean originatesFromDexResource() {
    return originKind == Kind.DEX;
  }

  public boolean originatesFromClassResource() {
    return originKind == Kind.CF;
  }

  public void collectIndexedItems(
      AppView<?> appView, IndexedItemCollection indexedItems, LensCodeRewriterUtils rewriter) {
    if (indexedItems.addClass(this)) {
      type.collectIndexedItems(appView, indexedItems);
      if (superType != null) {
        superType.collectIndexedItems(appView, indexedItems);
      } else {
        assert type.toDescriptorString().equals("Ljava/lang/Object;");
      }
      if (sourceFile != null) {
        sourceFile.collectIndexedItems(indexedItems);
      }
      annotations().collectIndexedItems(appView, indexedItems);
      if (interfaces != null) {
        interfaces.collectIndexedItems(appView, indexedItems);
      }
      if (getEnclosingMethodAttribute() != null) {
        getEnclosingMethodAttribute().collectIndexedItems(appView, indexedItems);
      }
      for (InnerClassAttribute attribute : getInnerClasses()) {
        attribute.collectIndexedItems(appView, indexedItems);
      }
      // We are explicitly not adding items referenced in signatures.
      forEachProgramField(field -> field.collectIndexedItems(appView, indexedItems));
      forEachProgramMethod(method -> method.collectIndexedItems(appView, indexedItems, rewriter));
    }
  }

  @Override
  protected void collectMixedSectionItems(MixedSectionCollection mixedItems) {
    assert getEnclosingMethodAttribute() == null;
    assert getInnerClasses().isEmpty();
    assert !classSignature.hasSignature();
    if (hasClassOrMemberAnnotations()) {
      mixedItems.setAnnotationsDirectoryForClass(this, new DexAnnotationDirectory(this));
    }
  }

  @Override
  public void addDependencies(MixedSectionCollection collector) {
    assert getEnclosingMethodAttribute() == null;
    assert getInnerClasses().isEmpty();
    assert !classSignature.hasSignature();
    // We only have a class data item if there are methods or fields.
    if (hasMethodsOrFields()) {
      collector.add(this);
      methodCollection.forEachMethod(m -> m.collectMixedSectionItems(collector));
      fieldCollection.forEachField(f -> f.getDefinition().collectMixedSectionItems(collector));
    }
    annotations().collectMixedSectionItems(collector);
    if (interfaces != null) {
      interfaces.collectMixedSectionItems(collector);
    }
  }

  @Override
  public String toString() {
    return type.toString();
  }

  @Override
  public String toSourceString() {
    return type.toSourceString();
  }

  /**
   * Returns true if this class is final, or it is a non-pinned program class with no instantiated
   * subtypes.
   */
  @Override
  public boolean isEffectivelyFinal(AppView<?> appView) {
    if (isFinal()) {
      return true;
    }
    if (appView.hasLiveness()) {
      assert appView.enableWholeProgramOptimizations();
      InternalOptions options = appView.options();
      return !appView.getKeepInfo(this).isPinned(options)
          && !appView.appInfoWithLiveness().isInstantiatedIndirectly(this);
    }
    return false;
  }

  @Override
  public boolean isProgramClass() {
    return true;
  }

  @Override
  public DexProgramClass asClass() {
    return this;
  }

  @Override
  public DexProgramClass asProgramClass() {
    return this;
  }

  public static DexProgramClass asProgramClassOrNull(DexClass clazz) {
    return clazz != null ? clazz.asProgramClass() : null;
  }

  @Override
  public boolean isNotProgramClass() {
    return false;
  }

  @Override
  public KotlinClassLevelInfo getKotlinInfo() {
    return kotlinInfo;
  }

  @Override
  public ClassKind<DexProgramClass> getKind() {
    return ClassKind.PROGRAM;
  }

  public void setKotlinInfo(KotlinClassLevelInfo kotlinInfo) {
    assert kotlinInfo != null;
    assert this.kotlinInfo == getNoKotlinInfo();
    this.kotlinInfo = kotlinInfo;
  }

  public void clearKotlinInfo() {
    this.kotlinInfo = getNoKotlinInfo();
  }

  @Override
  boolean internalClassOrInterfaceMayHaveInitializationSideEffects(
      AppView<?> appView,
      DexClass initialAccessHolder,
      Predicate<DexType> ignore,
      Set<DexType> seen) {
    if (!seen.add(getType()) || ignore.test(getType())) {
      return false;
    }
    return isInterface()
        ? internalInterfaceMayHaveInitializationSideEffects(
            appView, initialAccessHolder, ignore, seen)
        : internalClassMayHaveInitializationSideEffects(appView, initialAccessHolder, ignore, seen);
  }

  private boolean internalClassMayHaveInitializationSideEffects(
      AppView<?> appView,
      DexClass initialAccessHolder,
      Predicate<DexType> ignore,
      Set<DexType> seen) {
    assert !isInterface();
    assert seen.contains(getType());
    assert !ignore.test(getType());
    if (hasClassInitializer()
        && !getClassInitializer().getOptimizationInfo().classInitializerMayBePostponed()) {
      return true;
    }
    return defaultValuesForStaticFieldsMayTriggerAllocation()
        || initializationOfParentTypesMayHaveSideEffects(
            appView, initialAccessHolder, ignore, seen);
  }

  /**
   * Interface initialization is described the JVM Specification, section 5.5 Initialization (Java
   * SE 11 Edition).
   *
   * <p>A class or interface C may be initialized only as a result of:
   *
   * <ul>
   *   <li>The execution of any one of the Java Virtual Machine instructions new, getstatic,
   *       putstatic, or invokestatic that references C.
   *   <li>...
   *   <li>If C is an interface that declares a non-abstract, non-static method, the initialization
   *       of a class that implements C directly or indirectly.
   * </ul>
   */
  private boolean internalInterfaceMayHaveInitializationSideEffects(
      AppView<?> appView,
      DexClass initialAccessHolder,
      Predicate<DexType> ignore,
      Set<DexType> seen) {
    assert isInterface();
    assert seen.contains(getType());
    assert !ignore.test(getType());

    // If there is a direct access to the interface, then this has side effects if its clinit has
    // side effects. Parent types are not initialized and thus don't need to be considered.
    if (this == initialAccessHolder) {
      if (hasClassInitializer()
          && !getClassInitializer().getOptimizationInfo().classInitializerMayBePostponed()) {
        return true;
      }
      return defaultValuesForStaticFieldsMayTriggerAllocation();
    }

    // Otherwise, this interface has side effects if its clinit has side effects and it has at least
    // one default interface method, or if one of its parent types have observable side effects.
    if (hasClassInitializer()
        && !getClassInitializer().getOptimizationInfo().classInitializerMayBePostponed()
        && getMethodCollection().hasVirtualMethods(DexEncodedMethod::isDefaultMethod)) {
      return true;
    }

    return initializationOfParentTypesMayHaveSideEffects(
        appView, initialAccessHolder, ignore, seen);
  }

  private boolean initializationOfParentTypesMayHaveSideEffects(
      AppView<?> appView,
      DexClass initialAccessHolder,
      Predicate<DexType> ignore,
      Set<DexType> seen) {
    if (superType != null
        && superType.internalClassOrInterfaceMayHaveInitializationSideEffects(
            appView, initialAccessHolder, ignore, seen)) {
      return true;
    }
    for (DexType iface : interfaces) {
      if (iface.internalClassOrInterfaceMayHaveInitializationSideEffects(
          appView, initialAccessHolder, ignore, seen)) {
        return true;
      }
    }
    return false;
  }

  public boolean hasFields() {
    return fieldCollection.size() > 0;
  }

  public boolean hasMethods() {
    return methodCollection.size() > 0;
  }

  public boolean hasMethodsOrFields() {
    return hasMethods() || hasFields();
  }

  /** Determine if the class or any of its methods/fields has any attributes. */
  public boolean hasClassOrMemberAnnotations() {
    return !annotations().isEmpty()
        || hasAnnotations(methodCollection)
        || hasAnnotations(fieldCollection);
  }

  boolean hasOnlyInternalizableAnnotations() {
    return !hasAnnotations(methodCollection) && !hasAnnotations(fieldCollection);
  }

  private boolean hasAnnotations(FieldCollection fields) {
    synchronized (fields) {
      return fields.hasAnnotations();
    }
  }

  private boolean hasAnnotations(MethodCollection methods) {
    synchronized (methods) {
      return methods.hasAnnotations();
    }
  }

  public DexEncodedArray computeStaticValuesArray(NamingLens namingLens) {
    // Fast path to avoid sorting and collection allocation when no non-default values exist.
    if (!hasNonDefaultStaticFieldValues()) {
      return null;
    }
    List<DexEncodedField> fields = new ArrayList<>(staticFields());
    fields.sort((a, b) -> a.getReference().compareToWithNamingLens(b.getReference(), namingLens));
    int length = 0;
    List<DexValue> values = new ArrayList<>(fields.size());
    for (int i = 0; i < fields.size(); i++) {
      DexEncodedField field = fields.get(i);
      DexValue staticValue = field.getStaticValue();
      assert staticValue != null;
      values.add(staticValue);
      if (!staticValue.isDefault(field.getReference().type)) {
        length = i + 1;
      }
    }
    return length > 0
        ? new DexEncodedArray(values.subList(0, length).toArray(DexValue.EMPTY_ARRAY))
        : null;
  }

  private boolean hasNonDefaultStaticFieldValues() {
    for (DexEncodedField field : staticFields()) {
      DexValue value = field.getStaticValue();
      if (value != null && !value.isDefault(field.getReference().type)) {
        return true;
      }
    }
    return false;
  }

  public void addMethod(DexEncodedMethod method) {
    methodCollection.addMethod(method);
  }

  public void replaceVirtualMethod(
      DexMethod virtualMethod, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
    methodCollection.replaceVirtualMethod(virtualMethod, replacement);
  }

  public void addExtraInterfaces(List<ClassTypeSignature> extraInterfaces, DexItemFactory factory) {
    if (extraInterfaces.isEmpty()) {
      return;
    }
    addExtraInterfacesToInterfacesArray(extraInterfaces);
    addExtraInterfacesToSignatureIfPresent(extraInterfaces, factory);
  }

  private void addExtraInterfacesToInterfacesArray(List<ClassTypeSignature> extraInterfaces) {
    DexType[] newInterfaces =
        Arrays.copyOf(interfaces.values, interfaces.size() + extraInterfaces.size());
    for (int i = interfaces.size(); i < newInterfaces.length; i++) {
      newInterfaces[i] = extraInterfaces.get(i - interfaces.size()).type();
    }
    interfaces = new DexTypeList(newInterfaces);
  }

  private void addExtraInterfacesToSignatureIfPresent(
      List<ClassTypeSignature> extraInterfaces, DexItemFactory factory) {
    assert !extraInterfaces.isEmpty();
    // We introduce the extra interfaces to the generic signature.
    if (classSignature.hasNoSignature()) {
      return;
    }
    classSignature =
        ClassSignature.builder()
            .addSuperInterfaceSignatures(classSignature.getSuperInterfaceSignatures())
            .addSuperInterfaceSignatures(extraInterfaces)
            .setSuperClassSignature(classSignature.getSuperClassSignatureOrNull())
            .addFormalTypeParameters(classSignature.getFormalTypeParameters())
            .build(factory);
  }

  @Override
  public DexProgramClass get() {
    return this;
  }

  @Override
  public DexProgramClass getContextClass() {
    return this;
  }

  @Override
  public DexType getContextType() {
    return getType();
  }

  @Override
  public DexProgramClass getDefinition() {
    return this;
  }

  public void setInitialClassFileVersion(CfVersion initialClassFileVersion) {
    assert this.initialClassFileVersion == null;
    assert initialClassFileVersion != null;
    this.initialClassFileVersion = initialClassFileVersion;
  }

  public void downgradeInitialClassFileVersion(CfVersion version) {
    assert version != null;
    this.initialClassFileVersion = Ordered.minIgnoreNull(this.initialClassFileVersion, version);
  }

  public boolean hasClassFileVersion() {
    return initialClassFileVersion != null;
  }

  public CfVersion getInitialClassFileVersion() {
    return initialClassFileVersion;
  }

  public void setDeprecated() {
    deprecated = true;
  }

  public boolean isDeprecated() {
    return deprecated;
  }

  public static Iterable<DexProgramClass> asProgramClasses(
      Iterable<DexType> types, DexDefinitionSupplier definitions) {
    return () ->
        new Iterator<DexProgramClass>() {

          private final Iterator<DexType> iterator = types.iterator();

          private DexProgramClass next = findNext();

          @Override
          public boolean hasNext() {
            return next != null;
          }

          @Override
          public DexProgramClass next() {
            DexProgramClass current = next;
            next = findNext();
            return current;
          }

          private DexProgramClass findNext() {
            while (iterator.hasNext()) {
              DexType next = iterator.next();
              DexClass clazz = definitions.contextIndependentDefinitionFor(next);
              if (clazz != null && clazz.isProgramClass()) {
                return clazz.asProgramClass();
              }
            }
            return null;
          }
        };
  }

  @SuppressWarnings("DoNotCallSuggester")
  public static long invalidChecksumRequest(DexProgramClass clazz) {
    throw new CompilationError(
        clazz + " has no checksum information while checksum encoding is requested", clazz.origin);
  }

  public static long checksumFromType(DexProgramClass clazz) {
    return clazz.type.hashCode();
  }

  public long getChecksum() {
    return checksumSupplier.getChecksum(this);
  }

  public ChecksumSupplier getChecksumSupplier() {
    return checksumSupplier;
  }

}
