// 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.google.common.base.Predicates.alwaysFalse;
import static com.google.common.base.Predicates.alwaysTrue;

import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
import com.android.tools.r8.graph.GenericSignature.FormalTypeParameter;
import com.android.tools.r8.graph.MethodCollection.MethodCollectionFactory;
import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.AndroidApiLevelUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.TraversalContinuation;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public abstract class DexClass extends DexDefinition
    implements ClassDefinition, ClassResolutionResult {

  public interface FieldSetter {
    void setField(int index, DexEncodedField field);
  }

  public final Origin origin;
  public final DexType type;
  public final ClassAccessFlags accessFlags;
  public DexType superType;
  public DexTypeList interfaces;
  public DexString sourceFile;

  private OptionalBool isResolvable = OptionalBool.unknown();

  /** Access has to be synchronized during concurrent collection/writing phase. */
  protected final FieldCollection fieldCollection;

  /** Access has to be synchronized during concurrent collection/writing phase. */
  protected final MethodCollection methodCollection;

  /** Enclosing context of this class if it is an inner class, null otherwise. */
  private EnclosingMethodAttribute enclosingMethod;

  /** InnerClasses table. If this class is an inner class, it will have an entry here. */
  private List<InnerClassAttribute> innerClasses;

  /**
   * Nest attributes. If this class was compiled in JDK 11 and higher, and is in a nest, one of the
   * two attributes will be set.
   */
  private NestHostClassAttribute nestHost;

  private List<NestMemberClassAttribute> nestMembers;

  private List<PermittedSubclassAttribute> permittedSubclasses;

  private List<RecordComponentInfo> recordComponents;

  /** Generic signature information if the attribute is present in the input */
  protected ClassSignature classSignature;

  public DexClass(
      DexString sourceFile,
      DexTypeList interfaces,
      ClassAccessFlags accessFlags,
      DexType superType,
      DexType type,
      DexEncodedField[] staticFields,
      DexEncodedField[] instanceFields,
      MethodCollectionFactory methodCollectionFactory,
      NestHostClassAttribute nestHost,
      List<NestMemberClassAttribute> nestMembers,
      List<PermittedSubclassAttribute> permittedSubclasses,
      List<RecordComponentInfo> recordComponents,
      EnclosingMethodAttribute enclosingMethod,
      List<InnerClassAttribute> innerClasses,
      ClassSignature classSignature,
      DexAnnotationSet annotations,
      Origin origin,
      boolean skipNameValidationForTesting) {
    super(annotations);
    assert origin != null;
    this.origin = origin;
    this.sourceFile = sourceFile;
    this.interfaces = interfaces;
    this.accessFlags = accessFlags;
    this.superType = superType;
    this.type = type;
    this.fieldCollection = FieldCollection.create(this, staticFields, instanceFields);
    this.methodCollection = methodCollectionFactory.create(this);
    this.nestHost = nestHost;
    this.nestMembers = nestMembers;
    assert nestMembers != null;
    this.permittedSubclasses = permittedSubclasses;
    this.recordComponents = recordComponents;
    assert permittedSubclasses != null;
    this.enclosingMethod = enclosingMethod;
    this.innerClasses = innerClasses;
    assert classSignature != null;
    this.classSignature = classSignature;
    assert GenericSignatureUtils.verifyNoDuplicateGenericDefinitions(classSignature, annotations);
    if (type == superType) {
      throw new CompilationError("Class " + type.toString() + " cannot extend itself");
    }
    for (DexType interfaceType : interfaces.values) {
      if (type == interfaceType) {
        throw new CompilationError("Interface " + type.toString() + " cannot implement itself");
      }
    }
    if (!skipNameValidationForTesting && !type.descriptor.isValidClassDescriptor()) {
      throw new CompilationError(
          "Class descriptor '"
              + type.descriptor.toString()
              + "' cannot be represented in dex format.");
    }
  }

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

  @Override
  public void forEachClassResolutionResult(Consumer<DexClass> consumer) {
    consumer.accept(this);
  }

  @Override
  public DexClass toSingleClassWithProgramOverLibrary() {
    return this;
  }

  @Override
  public DexClass toSingleClassWithLibraryOverProgram() {
    return this;
  }

  @Override
  public DexClass toAlternativeClass() {
    return null;
  }

  public abstract void accept(
      Consumer<DexProgramClass> programClassConsumer,
      Consumer<DexClasspathClass> classpathClassConsumer,
      Consumer<DexLibraryClass> libraryClassConsumer);

  @Override
  public void forEachClassField(Consumer<? super DexClassAndField> consumer) {
    forEachClassFieldMatching(alwaysTrue(), consumer);
  }

  public void forEachClassFieldMatching(
      Predicate<DexEncodedField> predicate, Consumer<? super DexClassAndField> consumer) {
    forEachFieldMatching(predicate, field -> consumer.accept(DexClassAndField.create(this, field)));
  }

  @Override
  public void forEachClassMethod(Consumer<? super DexClassAndMethod> consumer) {
    forEachClassMethodMatching(alwaysTrue(), consumer);
  }

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

  @Override
  public ClassAccessFlags getAccessFlags() {
    return accessFlags;
  }

  public DexTypeList getInterfaces() {
    return interfaces;
  }

  public void setInterfaces(DexTypeList interfaces) {
    this.interfaces = interfaces;
  }

  public DexString getSourceFile() {
    return sourceFile;
  }

  public void setSourceFile(DexString sourceFile) {
    this.sourceFile = sourceFile;
  }

  public Iterable<DexClassAndField> classFields() {
    return Iterables.transform(fields(), field -> DexClassAndField.create(this, field));
  }

  public Iterable<DexEncodedField> fields() {
    return fields(Predicates.alwaysTrue());
  }

  public Iterable<DexEncodedField> fields(final Predicate<? super DexEncodedField> predicate) {
    return fieldCollection.fields(predicate);
  }

  public Iterable<DexEncodedMember<?, ?>> members() {
    return Iterables.concat(fields(), methods());
  }

  public Iterable<DexEncodedMember<?, ?>> members(Predicate<DexEncodedMember<?, ?>> predicate) {
    return Iterables.concat(fields(predicate), methods(predicate));
  }

  public FieldCollection getFieldCollection() {
    return fieldCollection;
  }

  @Override
  public MethodCollection getMethodCollection() {
    return methodCollection;
  }

  public Iterable<DexClassAndMethod> classMethods() {
    return Iterables.transform(methods(), method -> DexClassAndMethod.create(this, method));
  }

  public Iterable<DexEncodedMethod> methods() {
    return methodCollection.methods();
  }

  public Iterable<DexEncodedMethod> methods(Predicate<? super DexEncodedMethod> predicate) {
    return methodCollection.methods(predicate);
  }

  @Override
  protected void collectMixedSectionItems(MixedSectionCollection mixedItems) {
    throw new Unreachable();
  }

  public Iterable<DexEncodedMethod> directMethods() {
    return methodCollection.directMethods();
  }

  public Iterable<DexEncodedMethod> directMethods(Predicate<? super DexEncodedMethod> predicate) {
    return Iterables.filter(directMethods(), predicate::test);
  }

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

  public void addDirectMethods(Collection<DexEncodedMethod> methods) {
    methodCollection.addDirectMethods(methods);
  }

  public DexEncodedMethod removeMethod(DexMethod method) {
    return methodCollection.removeMethod(method);
  }

  public void setDirectMethods(Collection<DexEncodedMethod> methods) {
    setDirectMethods(methods.toArray(DexEncodedMethod.EMPTY_ARRAY));
  }

  public void setDirectMethods(DexEncodedMethod[] methods) {
    methodCollection.setDirectMethods(methods);
  }

  public Iterable<DexEncodedMethod> virtualMethods() {
    return methodCollection.virtualMethods();
  }

  public Iterable<DexEncodedMethod> virtualMethods(Predicate<? super DexEncodedMethod> predicate) {
    return Iterables.filter(virtualMethods(), predicate::test);
  }

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

  public void addVirtualMethods(Collection<DexEncodedMethod> methods) {
    methodCollection.addVirtualMethods(methods);
  }

  public void setVirtualMethods(List<DexEncodedMethod> methods) {
    setVirtualMethods(methods.toArray(DexEncodedMethod.EMPTY_ARRAY));
  }

  public void setVirtualMethods(DexEncodedMethod[] methods) {
    methodCollection.setVirtualMethods(methods);
  }

  private boolean verifyNoAbstractMethodsOnNonAbstractClasses(
      Iterable<DexEncodedMethod> methods, InternalOptions options) {
    if (options.canHaveDalvikAbstractMethodOnNonAbstractClassVerificationBug() && !isAbstract()) {
      for (DexEncodedMethod method : methods) {
        assert !method.isAbstract()
            : "Non-abstract method on abstract class: `"
                + method.getReference().toSourceString()
                + "`";
      }
    }
    return true;
  }

  public void forEachMethod(Consumer<DexEncodedMethod> consumer) {
    methodCollection.forEachMethod(consumer);
  }

  public List<DexEncodedField> allFieldsSorted() {
    return fieldCollection.allFieldsSorted();
  }

  public List<DexEncodedMethod> allMethodsSorted() {
    return methodCollection.allMethodsSorted();
  }

  public void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
    methodCollection.virtualizeMethods(privateInstanceMethods);
  }

  /**
   * For all annotations on the class and all annotations on its methods and fields apply the
   * specified consumer.
   */
  public void forEachAnnotation(Consumer<DexAnnotation> consumer) {
    annotations().forEach(consumer);
    for (DexEncodedMethod method : methods()) {
      method.annotations().forEach(consumer);
      method.parameterAnnotationsList.forEachAnnotation(consumer);
    }
    for (DexEncodedField field : fields()) {
      field.annotations().forEach(consumer);
    }
  }

  public void forEachField(Consumer<DexEncodedField> consumer) {
    forEachFieldMatching(alwaysTrue(), consumer);
  }

  public void forEachFieldMatching(
      Predicate<? super DexEncodedField> predicate, Consumer<? super DexEncodedField> consumer) {
    fields(predicate).forEach(consumer);
  }

  public void forEachInstanceField(Consumer<DexEncodedField> consumer) {
    forEachInstanceFieldMatching(alwaysTrue(), consumer);
  }

  public void forEachInstanceFieldMatching(
      Predicate<DexEncodedField> predicate, Consumer<DexEncodedField> consumer) {
    instanceFields(predicate).forEach(consumer);
  }

  public void forEachStaticField(Consumer<DexEncodedField> consumer) {
    forEachStaticFieldMatching(alwaysTrue(), consumer);
  }

  public void forEachStaticFieldMatching(
      Predicate<DexEncodedField> predicate, Consumer<DexEncodedField> consumer) {
    staticFields(predicate).forEach(consumer);
  }

  public TraversalContinuation<?, ?> traverseFields(
      Function<DexEncodedField, TraversalContinuation<?, ?>> fn) {
    for (DexEncodedField field : fields()) {
      if (fn.apply(field).shouldBreak()) {
        return TraversalContinuation.doBreak();
      }
    }
    return TraversalContinuation.doContinue();
  }

  public List<DexEncodedField> staticFields() {
    return fieldCollection.staticFieldsAsList();
  }

  public Iterable<DexEncodedField> staticFields(Predicate<DexEncodedField> predicate) {
    return IterableUtils.filter(staticFields(), predicate);
  }

  public void appendStaticField(DexEncodedField field) {
    fieldCollection.appendStaticField(field);
  }

  public void appendStaticFields(Collection<DexEncodedField> fields) {
    fieldCollection.appendStaticFields(fields);
  }

  public DexEncodedField[] clearStaticFields() {
    List<DexEncodedField> previousFields = staticFields();
    fieldCollection.clearStaticFields();
    return previousFields.toArray(DexEncodedField.EMPTY_ARRAY);
  }

  public void setStaticFields(DexEncodedField[] fields) {
    fieldCollection.setStaticFields(fields);
  }

  public void setStaticFields(Collection<DexEncodedField> fields) {
    setStaticFields(fields.toArray(DexEncodedField.EMPTY_ARRAY));
  }

  public List<DexEncodedField> instanceFields() {
    return fieldCollection.instanceFieldsAsList();
  }

  public Iterable<DexEncodedField> instanceFields(Predicate<? super DexEncodedField> predicate) {
    return Iterables.filter(instanceFields(), predicate::test);
  }

  public void appendInstanceField(DexEncodedField field) {
    fieldCollection.appendInstanceField(field);
  }

  public void appendInstanceFields(Collection<DexEncodedField> fields) {
    fieldCollection.appendInstanceFields(fields);
  }

  public void setInstanceFields(DexEncodedField[] fields) {
    fieldCollection.setInstanceFields(fields);
  }

  public DexEncodedField[] clearInstanceFields() {
    List<DexEncodedField> previousFields = instanceFields();
    fieldCollection.clearInstanceFields();
    return previousFields.toArray(DexEncodedField.EMPTY_ARRAY);
  }

  /** Find method in this class matching {@param method}. */
  public DexClassAndField lookupClassField(DexField field) {
    return toClassFieldOrNull(lookupField(field));
  }

  /** Find field in this class matching {@param field}. */
  public DexEncodedField lookupField(DexField field) {
    return fieldCollection.lookupField(field);
  }

  /** Find static field in this class matching {@param field}. */
  public DexEncodedField lookupStaticField(DexField field) {
    return fieldCollection.lookupStaticField(field);
  }

  /** Find instance field in this class matching {@param field}. */
  public DexEncodedField lookupInstanceField(DexField field) {
    return fieldCollection.lookupInstanceField(field);
  }

  public DexEncodedField lookupUniqueInstanceFieldWithName(DexString name) {
    return internalLookupUniqueFieldThatMatches(field -> field.getName() == name, instanceFields());
  }

  public DexEncodedField lookupUniqueStaticFieldWithName(DexString name) {
    return internalLookupUniqueFieldThatMatches(field -> field.getName() == name, staticFields());
  }

  private static DexEncodedField internalLookupUniqueFieldThatMatches(
      Predicate<DexEncodedField> predicate, List<DexEncodedField> fields) {
    DexEncodedField result = null;
    for (DexEncodedField field : fields) {
      if (predicate.test(field)) {
        if (result != null) {
          return null;
        }
        result = field;
      }
    }
    return result;
  }

  private DexClassAndField toClassFieldOrNull(DexEncodedField field) {
    return field != null ? DexClassAndField.create(this, field) : null;
  }

  /** Find direct method in this class matching {@param method}. */
  public DexEncodedMethod lookupDirectMethod(DexMethod method) {
    return methodCollection.getDirectMethod(method);
  }

  /** Find direct method in this class matching {@param predicate}. */
  public DexEncodedMethod lookupDirectMethod(Predicate<DexEncodedMethod> predicate) {
    return methodCollection.getDirectMethod(predicate);
  }

  /** Find virtual method in this class matching {@param method}. */
  public DexEncodedMethod lookupVirtualMethod(DexMethod method) {
    return methodCollection.getVirtualMethod(method);
  }

  /** Find virtual method in this class matching {@param predicate}. */
  public DexEncodedMethod lookupVirtualMethod(Predicate<DexEncodedMethod> predicate) {
    return methodCollection.getVirtualMethod(predicate);
  }

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

  /** Find method in this class matching {@param method}. */
  public DexClassAndMethod lookupClassMethod(DexMethod method) {
    return toClassMethodOrNull(methodCollection.getMethod(method));
  }

  private DexClassAndMethod toClassMethodOrNull(DexEncodedMethod method) {
    return method != null ? DexClassAndMethod.create(this, method) : null;
  }

  /** Find method in this class matching {@param method}. */
  public DexEncodedMethod lookupMethod(DexMethod method) {
    return methodCollection.getMethod(method);
  }

  public DexEncodedMethod lookupMethod(DexProto methodProto, DexString methodName) {
    return methodCollection.getMethod(methodProto, methodName);
  }

  /** Find method in this class matching {@param method}. */
  public DexEncodedMethod lookupMethod(Predicate<DexEncodedMethod> predicate) {
    return methodCollection.getMethod(predicate);
  }

  public DexEncodedMethod lookupSignaturePolymorphicMethod(
      DexString methodName, DexItemFactory factory) {
    if (type != factory.methodHandleType && type != factory.varHandleType) {
      return null;
    }
    DexEncodedMethod matchingName = null;
    DexEncodedMethod signaturePolymorphicMethod = null;
    for (DexEncodedMethod method : virtualMethods()) {
      if (method.getReference().name == methodName) {
        if (matchingName != null) {
          // The jvm spec, section 5.4.3.3 details that there must be exactly one method with the
          // given name only.
          return null;
        }
        matchingName = method;
        if (isSignaturePolymorphicMethod(method, factory)) {
          signaturePolymorphicMethod = method;
        }
      }
    }
    return signaturePolymorphicMethod;
  }

  public static boolean isSignaturePolymorphicMethod(
      DexEncodedMethod method, DexItemFactory factory) {
    assert method.getHolderType() == factory.methodHandleType
        || method.getHolderType() == factory.varHandleType;
    return method.accessFlags.isVarargs()
        && method.accessFlags.isNative()
        && method.getReference().proto.parameters.size() == 1
        && method.getReference().proto.parameters.values[0] == factory.objectArrayType;
  }

  public boolean canBeInstantiatedByNewInstance() {
    return !isAbstract() && !isAnnotation() && !isInterface();
  }

  public boolean isAbstract() {
    return accessFlags.isAbstract();
  }

  public boolean isAnnotation() {
    return accessFlags.isAnnotation();
  }

  public boolean isFinal() {
    return accessFlags.isFinal();
  }

  public boolean isEffectivelyFinal(AppView<?> appView) {
    return isFinal();
  }

  @Override
  public boolean isInterface() {
    return accessFlags.isInterface();
  }

  public boolean isEnum() {
    return accessFlags.isEnum();
  }

  public boolean isRecord() {
    return accessFlags.isRecord();
  }

  public abstract void addDependencies(MixedSectionCollection collector);

  @Override
  public DexReference getReference() {
    return getType();
  }

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

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

  @Override
  public DexClass asDexClass() {
    return this;
  }

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

  @Override
  public DexClasspathClass asClasspathClass() {
    return null;
  }

  public abstract boolean isNotProgramClass();

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

  @Override
  public DexLibraryClass asLibraryClass() {
    return null;
  }

  public boolean isPrivate() {
    return accessFlags.isPrivate();
  }

  public boolean isPublic() {
    return accessFlags.isPublic();
  }

  @Override
  public boolean isStatic() {
    return accessFlags.isStatic();
  }

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

  public DexEncodedMethod getClassInitializer() {
    DexEncodedMethod classInitializer = methodCollection.getClassInitializer();
    assert classInitializer != DexEncodedMethod.SENTINEL;
    return classInitializer;
  }

  @Override
  public ClassReference getClassReference() {
    return Reference.classFromDescriptor(getType().toDescriptorString());
  }

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

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

  @Override
  public Origin getOrigin() {
    return this.origin;
  }

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

  public boolean hasSuperType() {
    return superType != null;
  }

  public DexType getSuperType() {
    return superType;
  }

  public boolean hasClassInitializer() {
    return getClassInitializer() != null;
  }

  public boolean hasDefaultInitializer() {
    return getDefaultInitializer() != null;
  }

  public DexEncodedMethod getInitializer(DexType[] parameters) {
    for (DexEncodedMethod method : directMethods()) {
      if (method.isInstanceInitializer()
          && Arrays.equals(method.getReference().proto.parameters.values, parameters)) {
        return method;
      }
    }
    return null;
  }

  public DexEncodedMethod getDefaultInitializer() {
    return getInitializer(DexType.EMPTY_ARRAY);
  }

  public boolean hasMissingSuperType(AppInfoWithClassHierarchy appInfo) {
    if (superType != null && appInfo.isMissingOrHasMissingSuperType(superType)) {
      return true;
    }
    for (DexType interfaceType : interfaces.values) {
      if (appInfo.isMissingOrHasMissingSuperType(interfaceType)) {
        return true;
      }
    }
    return false;
  }

  public boolean isResolvable(AppView<?> appView) {
    if (isResolvable.isUnknown()) {
      boolean resolvable;
      if (isLibraryClass()) {
        resolvable = AndroidApiLevelUtils.isApiSafeForReference(asLibraryClass(), appView);
      } else {
        resolvable = true;
        for (DexType supertype : allImmediateSupertypes()) {
          resolvable &= supertype.isResolvable(appView);
          if (!resolvable) {
            break;
          }
        }
      }
      isResolvable = OptionalBool.of(resolvable);
    }
    assert !isResolvable.isUnknown();
    return isResolvable.isTrue();
  }

  public boolean isSerializable(AppView<? extends AppInfoWithClassHierarchy> appView) {
    return appView.appInfo().isSerializable(type);
  }

  public boolean isExternalizable(AppView<? extends AppInfoWithClassHierarchy> appView) {
    return appView.appInfo().isExternalizable(type);
  }

  public boolean classInitializationMayHaveSideEffects(AppView<?> appView) {
    return classInitializationMayHaveSideEffects(appView, alwaysFalse());
  }

  public boolean classInitializationMayHaveSideEffects(
      AppView<?> appView, Predicate<DexType> ignore) {
    return internalClassOrInterfaceMayHaveInitializationSideEffects(
        appView, this, ignore, Sets.newIdentityHashSet());
  }

  public final boolean classInitializationMayHaveSideEffectsInContext(
      AppView<?> appView, Definition context) {
    // Types that are a super type of the current context are guaranteed to be initialized already.
    return classInitializationMayHaveSideEffects(
        appView, type -> appView.isSubtype(context.getContextType(), type).isTrue());
  }

  abstract boolean internalClassOrInterfaceMayHaveInitializationSideEffects(
      AppView<?> appView,
      DexClass initialAccessHolder,
      Predicate<DexType> ignore,
      Set<DexType> seen);

  public void forEachImmediateInterface(Consumer<DexType> fn) {
    for (DexType iface : interfaces.values) {
      fn.accept(iface);
    }
  }

  public void forEachImmediateSupertype(Consumer<DexType> fn) {
    if (superType != null) {
      fn.accept(superType);
    }
    forEachImmediateInterface(fn);
  }

  public void forEachImmediateSupertype(BiConsumer<DexType, Boolean> fn) {
    if (superType != null) {
      fn.accept(superType, false);
    }
    forEachImmediateInterface(iface -> fn.accept(iface, true));
  }

  public boolean validInterfaceSignatures() {
    return getClassSignature().superInterfaceSignatures().isEmpty()
        || interfaces.values.length == getClassSignature().superInterfaceSignatures.size();
  }

  public void forEachImmediateInterfaceWithSignature(
      BiConsumer<DexType, ClassTypeSignature> consumer) {
    assert validInterfaceSignatures();

    // If there is no generic signature information don't pass any type arguments.
    if (getClassSignature().superInterfaceSignatures().isEmpty()) {
      forEachImmediateInterface(
          superInterface ->
              consumer.accept(superInterface, new ClassTypeSignature(superInterface)));
      return;
    }

    Iterator<DexType> interfaceIterator = Arrays.asList(interfaces.values).iterator();
    Iterator<ClassTypeSignature> interfaceSignatureIterator =
        getClassSignature().superInterfaceSignatures().iterator();

    while (interfaceIterator.hasNext()) {
      assert interfaceSignatureIterator.hasNext();
      DexType superInterface = interfaceIterator.next();
      ClassTypeSignature superInterfaceSignatures = interfaceSignatureIterator.next();
      consumer.accept(superInterface, superInterfaceSignatures);
    }
  }

  public void forEachImmediateSupertypeWithSignature(
      BiConsumer<DexType, ClassTypeSignature> consumer) {
    if (superType != null) {
      consumer.accept(superType, classSignature.superClassSignature);
    }
    forEachImmediateInterfaceWithSignature(consumer);
  }

  public void forEachImmediateInterfaceWithAppliedTypeArguments(
      List<FieldTypeSignature> typeArguments,
      BiConsumer<DexType, List<FieldTypeSignature>> consumer) {
    assert validInterfaceSignatures();

    // If there is no generic signature information don't pass any type arguments.
    if (getClassSignature().superInterfaceSignatures().size() == 0) {
      forEachImmediateInterface(
          superInterface -> consumer.accept(superInterface, ImmutableList.of()));
      return;
    }

    Iterator<DexType> interfaceIterator = Arrays.asList(interfaces.values).iterator();
    Iterator<ClassTypeSignature> interfaceSignatureIterator =
        getClassSignature().superInterfaceSignatures().iterator();

    while (interfaceIterator.hasNext()) {
      assert interfaceSignatureIterator.hasNext();
      DexType superInterface = interfaceIterator.next();
      ClassTypeSignature superInterfaceSignatures = interfaceSignatureIterator.next();

      // With no type arguments erase the signatures.
      if (typeArguments.isEmpty() && superInterfaceSignatures.hasTypeVariableArguments()) {
        consumer.accept(superInterface, ImmutableList.of());
        continue;
      }

      consumer.accept(superInterface, applyTypeArguments(superInterfaceSignatures, typeArguments));
    }
    assert !interfaceSignatureIterator.hasNext();
  }

  public void forEachImmediateSupertypeWithAppliedTypeArguments(
      List<FieldTypeSignature> typeArguments,
      BiConsumer<DexType, List<FieldTypeSignature>> consumer) {
    if (superType != null) {
      consumer.accept(
          superType, applyTypeArguments(getClassSignature().superClassSignature, typeArguments));
    }
    forEachImmediateInterfaceWithAppliedTypeArguments(typeArguments, consumer);
  }

  private List<FieldTypeSignature> applyTypeArguments(
      ClassTypeSignature superInterfaceSignatures, List<FieldTypeSignature> appliedTypeArguments) {
    ImmutableList.Builder<FieldTypeSignature> superTypeArgumentsBuilder = ImmutableList.builder();
    if (superInterfaceSignatures.type.toSourceString().equals("java.util.Map")) {
      System.currentTimeMillis();
    }
    superInterfaceSignatures
        .typeArguments()
        .forEach(
            typeArgument -> {
              if (typeArgument.isTypeVariableSignature()) {
                for (int i = 0; i < getClassSignature().getFormalTypeParameters().size(); i++) {
                  FormalTypeParameter formalTypeParameter =
                      getClassSignature().getFormalTypeParameters().get(i);
                  if (formalTypeParameter
                      .getName()
                      .equals(typeArgument.asTypeVariableSignature().typeVariable())) {
                    if (i >= appliedTypeArguments.size()) {
                      assert false;
                    } else {
                      superTypeArgumentsBuilder.add(appliedTypeArguments.get(i));
                    }
                  }
                }
              } else {
                superTypeArgumentsBuilder.add(typeArgument);
              }
            });
    return superTypeArgumentsBuilder.build();
  }

  @Override
  public Iterable<DexType> allImmediateSupertypes() {
    Iterator<DexType> iterator =
        superType != null
            ? Iterators.concat(
                Iterators.singletonIterator(superType), Iterators.forArray(interfaces.values))
            : Iterators.forArray(interfaces.values);
    return () -> iterator;
  }

  public boolean definesFinalizer(DexItemFactory factory) {
    return lookupVirtualMethod(factory.objectMembers.finalize) != null;
  }

  public boolean defaultValuesForStaticFieldsMayTriggerAllocation() {
    return staticFields().stream()
        .anyMatch(
            field -> field.hasExplicitStaticValue() && field.getStaticValue().mayHaveSideEffects());
  }

  public List<InnerClassAttribute> getInnerClasses() {
    return innerClasses;
  }

  public void setInnerClasses(List<InnerClassAttribute> innerClasses) {
    this.innerClasses = innerClasses;
  }

  public boolean hasEnclosingMethodAttribute() {
    return enclosingMethod != null;
  }

  public EnclosingMethodAttribute getEnclosingMethodAttribute() {
    return enclosingMethod;
  }

  public void setEnclosingMethodAttribute(EnclosingMethodAttribute enclosingMethod) {
    this.enclosingMethod = enclosingMethod;
  }

  public void clearEnclosingMethodAttribute() {
    enclosingMethod = null;
  }

  public void removeEnclosingMethodAttribute(Predicate<EnclosingMethodAttribute> predicate) {
    if (enclosingMethod != null && predicate.test(enclosingMethod)) {
      enclosingMethod = null;
    }
  }

  public void clearInnerClasses() {
    innerClasses.clear();
  }

  public void clearClassSignature() {
    classSignature = ClassSignature.noSignature();
  }

  public void removeInnerClasses(Predicate<InnerClassAttribute> predicate) {
    innerClasses.removeIf(predicate);
  }

  public InnerClassAttribute getInnerClassAttributeForThisClass() {
    for (InnerClassAttribute innerClassAttribute : getInnerClasses()) {
      if (type == innerClassAttribute.getInner()) {
        return innerClassAttribute;
      }
    }
    return null;
  }

  public void replaceInnerClassAttributeForThisClass(InnerClassAttribute newInnerClassAttribute) {
    ListIterator<InnerClassAttribute> iterator = getInnerClasses().listIterator();
    while (iterator.hasNext()) {
      InnerClassAttribute innerClassAttribute = iterator.next();
      if (type == innerClassAttribute.getInner()) {
        iterator.set(newInnerClassAttribute);
        return;
      }
    }
    throw new Unreachable();
  }

  public ClassSignature getClassSignature() {
    return classSignature;
  }

  public void setClassSignature(ClassSignature classSignature) {
    this.classSignature = classSignature;
  }

  public void clearPermittedSubclasses() {
    permittedSubclasses.clear();
  }

  public boolean isLocalClass() {
    InnerClassAttribute innerClass = getInnerClassAttributeForThisClass();
    // The corresponding enclosing-method attribute might be not available, e.g., CF version 50.
    return innerClass != null && innerClass.getOuter() == null && innerClass.isNamed();
  }

  public boolean isMemberClass() {
    InnerClassAttribute innerClass = getInnerClassAttributeForThisClass();
    boolean isMember = innerClass != null && innerClass.getOuter() != null && innerClass.isNamed();
    assert !isMember || getEnclosingMethodAttribute() == null;
    return isMember;
  }

  public boolean isAnonymousClass() {
    InnerClassAttribute innerClass = getInnerClassAttributeForThisClass();
    // The corresponding enclosing-method attribute might be not available, e.g., CF version 50.
    // We can't rely on outer type either because it's not null prior to 51 and null since 51.
    return innerClass != null && innerClass.isAnonymous();
  }

  public boolean isInANest() {
    return isNestHost() || isNestMember();
  }

  public void clearNestHost() {
    nestHost = null;
  }

  public void clearNestMembers() {
    nestMembers.clear();
  }

  public void setNestHost(DexType type) {
    assert type != null;
    this.nestHost = new NestHostClassAttribute(type);
  }

  public void setNestHostAttribute(NestHostClassAttribute nestHostAttribute) {
    this.nestHost = nestHostAttribute;
  }

  public boolean isNestHost() {
    return !nestMembers.isEmpty();
  }

  public boolean isNestMember() {
    return nestHost != null;
  }

  public DexType getNestHost() {
    if (isNestMember()) {
      return nestHost.getNestHost();
    }
    if (isNestHost()) {
      return type;
    }
    return null;
  }

  public boolean isInSameNest(DexClass other) {
    return isInANest() && other.isInANest() && getNestHost() == other.getNestHost();
  }

  public void forEachNestMember(Consumer<DexType> consumer) {
    assert isNestHost();
    getNestMembersClassAttributes().forEach(member -> consumer.accept(member.getNestMember()));
  }

  public NestHostClassAttribute getNestHostClassAttribute() {
    return nestHost;
  }

  public boolean hasNestMemberAttributes() {
    return !nestMembers.isEmpty();
  }

  public List<NestMemberClassAttribute> getNestMembersClassAttributes() {
    return nestMembers;
  }

  public void setNestMemberAttributes(List<NestMemberClassAttribute> nestMemberAttributes) {
    this.nestMembers = nestMemberAttributes;
  }

  public void removeNestMemberAttributes(Predicate<NestMemberClassAttribute> predicate) {
    nestMembers.removeIf(predicate);
  }

  public boolean hasPermittedSubclassAttributes() {
    return !permittedSubclasses.isEmpty();
  }

  public List<PermittedSubclassAttribute> getPermittedSubclassAttributes() {
    return permittedSubclasses;
  }

  public List<RecordComponentInfo> getRecordComponents() {
    return recordComponents;
  }

  public void clearRecordComponents() {
    recordComponents.clear();
  }

  public void removeRecordComponents(Predicate<RecordComponentInfo> predicate) {
    if (!recordComponents.isEmpty()) {
      recordComponents.removeIf(predicate);
    }
  }

  /** Returns kotlin class info if the class is synthesized by kotlin compiler. */
  public abstract KotlinClassLevelInfo getKotlinInfo();

  public final String getSimpleName() {
    return getType().getSimpleName();
  }

  public final String getTypeName() {
    return getType().getTypeName();
  }

  public boolean hasStaticFields() {
    return fieldCollection.hasStaticFields();
  }

  public boolean hasInstanceFields() {
    return fieldCollection.hasInstanceFields();
  }

  public List<DexEncodedField> getDirectAndIndirectInstanceFields(AppView<?> appView) {
    List<DexEncodedField> result = new ArrayList<>();
    DexClass current = this;
    while (current != null && current.type != appView.dexItemFactory().objectType) {
      result.addAll(current.instanceFields());
      current = appView.definitionFor(current.superType);
    }
    return result;
  }

  public boolean isValid(InternalOptions options) {
    assert verifyNoAbstractMethodsOnNonAbstractClasses(virtualMethods(), options);
    assert !isInterface() || !getMethodCollection().hasVirtualMethods(DexEncodedMethod::isFinal);
    assert fieldCollection.verify();
    assert methodCollection.verify();
    return true;
  }

  public boolean hasStaticSynchronizedMethods() {
    for (DexEncodedMethod encodedMethod : directMethods()) {
      if (encodedMethod.isStatic() && encodedMethod.isSynchronized()) {
        return true;
      }
    }
    return false;
  }
}
