// 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.utils.InternalOptions.ASM_VERSION;
import static org.objectweb.asm.ClassReader.SKIP_CODE;
import static org.objectweb.asm.ClassReader.SKIP_DEBUG;
import static org.objectweb.asm.ClassReader.SKIP_FRAMES;
import static org.objectweb.asm.Opcodes.ACC_DEPRECATED;

import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass.ChecksumSupplier;
import com.android.tools.r8.graph.DexValue.DexValueAnnotation;
import com.android.tools.r8.graph.DexValue.DexValueArray;
import com.android.tools.r8.graph.DexValue.DexValueBoolean;
import com.android.tools.r8.graph.DexValue.DexValueByte;
import com.android.tools.r8.graph.DexValue.DexValueChar;
import com.android.tools.r8.graph.DexValue.DexValueDouble;
import com.android.tools.r8.graph.DexValue.DexValueEnum;
import com.android.tools.r8.graph.DexValue.DexValueFloat;
import com.android.tools.r8.graph.DexValue.DexValueInt;
import com.android.tools.r8.graph.DexValue.DexValueLong;
import com.android.tools.r8.graph.DexValue.DexValueNull;
import com.android.tools.r8.graph.DexValue.DexValueShort;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.jar.CfApplicationWriter;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.synthesis.SyntheticMarker;
import com.android.tools.r8.utils.AsmUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.FieldSignatureEquivalence;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.zip.CRC32;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.RecordComponentVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.TypePath;

/** Java/Jar class reader for constructing dex/graph structure. */
public class JarClassFileReader<T extends DexClass> {

  private static final byte[] CLASSFILE_HEADER = ByteBuffer.allocate(4).putInt(0xCAFEBABE).array();

  // Hidden ASM "synthetic attribute" bit we need to clear.
  private static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;

  private final JarApplicationReader application;
  private final Consumer<T> classConsumer;
  private final ClassKind<T> classKind;

  public JarClassFileReader(
      JarApplicationReader application, Consumer<T> classConsumer, ClassKind<T> classKind) {
    this.application = application;
    this.classConsumer = classConsumer;
    this.classKind = classKind;
  }

  public void read(ProgramResource resource) throws ResourceException {
    read(resource.getOrigin(), resource.getBytes());
  }

  public void read(Origin origin, byte[] bytes) {
    ExceptionUtils.withOriginAttachmentHandler(origin, () -> internalRead(origin, bytes));
  }

  public void internalRead(Origin origin, byte[] bytes) {
    if (bytes.length < CLASSFILE_HEADER.length) {
      throw new CompilationError("Invalid empty classfile", origin);
    }
    for (int i = 0; i < CLASSFILE_HEADER.length; i++) {
      if (bytes[i] != CLASSFILE_HEADER[i]) {
        throw new CompilationError("Invalid classfile header", origin);
      }
    }

    ClassReader reader = new ClassReader(bytes);

    int parsingOptions = SKIP_FRAMES | SKIP_CODE;

    // If the source-file and source-debug-extension attributes are not kept we can skip all debug
    // related attributes when parsing the class structure.
    if (application.options.getProguardConfiguration() != null) {
      ProguardKeepAttributes keep =
          application.options.getProguardConfiguration().getKeepAttributes();
      if (!keep.sourceFile && !keep.sourceDebugExtension && !keep.methodParameters) {
        parsingOptions |= SKIP_DEBUG;
      }
    }
    if (classKind != ClassKind.PROGRAM) {
      parsingOptions |= SKIP_DEBUG;
    }
    reader.accept(
        new CreateDexClassVisitor<>(origin, classKind, reader.b, application, classConsumer),
        new Attribute[] {SyntheticMarker.getMarkerAttributePrototype()},
        parsingOptions);

    // Read marker.
    if (reader.getItemCount() > CfApplicationWriter.MARKER_STRING_CONSTANT_POOL_INDEX
        && reader.getItem(CfApplicationWriter.MARKER_STRING_CONSTANT_POOL_INDEX) > 0) {
      try {
        Object maybeMarker =
            reader.readConst(
                CfApplicationWriter.MARKER_STRING_CONSTANT_POOL_INDEX,
                new char[reader.getMaxStringLength()]);
        if (maybeMarker instanceof String) {
          application.getFactory().createString((String) maybeMarker);
        }
      } catch (IllegalArgumentException e) {
        // Ignore if the type of the constant is not something readConst() allows.
      }
    }
  }

  private static int cleanAccessFlags(int access) {
    // Clear the "synthetic attribute" and "deprecated" attribute-flags if present.
    return access & ~ACC_SYNTHETIC_ATTRIBUTE & ~ACC_DEPRECATED;
  }

  public static FieldAccessFlags createFieldAccessFlags(int access) {
    return FieldAccessFlags.fromCfAccessFlags(cleanAccessFlags(access));
  }

  public static MethodAccessFlags createMethodAccessFlags(String name, int access) {
    boolean isConstructor =
        name.equals(Constants.INSTANCE_INITIALIZER_NAME)
            || name.equals(Constants.CLASS_INITIALIZER_NAME);
    return MethodAccessFlags.fromCfAccessFlags(cleanAccessFlags(access), isConstructor);
  }

  private static AnnotationVisitor createAnnotationVisitor(String desc, boolean visible,
      List<DexAnnotation> annotations,
      JarApplicationReader application) {
    assert annotations != null;
    if (visible || retainCompileTimeAnnotation(desc, application)) {
      int visiblity = visible ? DexAnnotation.VISIBILITY_RUNTIME : DexAnnotation.VISIBILITY_BUILD;
      return new CreateAnnotationVisitor(
          application,
          (names, values) ->
              annotations.add(
                  new DexAnnotation(
                      visiblity, createEncodedAnnotation(desc, names, values, application))));
    }
    return null;
  }

  private static boolean retainCompileTimeAnnotation(
      String desc, JarApplicationReader application) {
    return DexAnnotation.retainCompileTimeAnnotation(
        application.getTypeFromDescriptor(desc), application.options);
  }

  private static DexEncodedAnnotation createEncodedAnnotation(String desc,
      List<DexString> names, List<DexValue> values, JarApplicationReader application) {
    assert (names == null && values.isEmpty())
        || (names != null && !names.isEmpty() && names.size() == values.size());
    DexAnnotationElement[] elements = new DexAnnotationElement[values.size()];
    for (int i = 0; i < values.size(); i++) {
      elements[i] = new DexAnnotationElement(names.get(i), values.get(i));
    }
    return new DexEncodedAnnotation(application.getTypeFromDescriptor(desc), elements);
  }

  private static class CreateDexClassVisitor<T extends DexClass> extends ClassVisitor {

    private final Origin origin;
    private final ClassKind<T> classKind;
    private final JarApplicationReader application;
    private final Consumer<T> classConsumer;
    private final ReparseContext context = new ReparseContext();

    // DexClass data.
    private CfVersion version;
    private boolean deprecated;
    private DexType type;
    private ClassAccessFlags accessFlags;
    private DexType superType;
    private DexTypeList interfaces;
    private DexString sourceFile;
    private NestHostClassAttribute nestHost = null;
    private final List<NestMemberClassAttribute> nestMembers = new ArrayList<>();
    private final Set<DexField> recordComponents = Sets.newIdentityHashSet();
    private EnclosingMethodAttribute enclosingMember = null;
    private final List<InnerClassAttribute> innerClasses = new ArrayList<>();
    private ClassSignature classSignature = ClassSignature.noSignature();
    private List<DexAnnotation> annotations = null;
    private List<DexAnnotationElement> defaultAnnotations = null;
    private final List<DexEncodedField> staticFields = new ArrayList<>();
    private final List<DexEncodedField> instanceFields = new ArrayList<>();
    private final Set<Wrapper<DexField>> fieldSignatures = new HashSet<>();
    private final List<DexEncodedMethod> directMethods = new ArrayList<>();
    private final List<DexEncodedMethod> virtualMethods = new ArrayList<>();
    private final Set<Wrapper<DexMethod>> methodSignatures = new HashSet<>();
    private boolean hasReachabilitySensitiveMethod = false;
    private SyntheticMarker syntheticMarker = null;

    public CreateDexClassVisitor(
        Origin origin,
        ClassKind<T> classKind,
        byte[] classCache,
        JarApplicationReader application,
        Consumer<T> classConsumer) {
      super(ASM_VERSION);
      this.origin = origin;
      this.classKind = classKind;
      this.classConsumer = classConsumer;
      this.context.classCache = classCache;
      this.application = application;
    }

    @Override
    public void visitAttribute(Attribute attribute) {
      SyntheticMarker marker = SyntheticMarker.readMarkerAttribute(attribute);
      if (marker != null) {
        assert syntheticMarker == null;
        syntheticMarker = marker;
      }
    }

    @Override
    public void visitInnerClass(String name, String outerName, String innerName, int access) {
      if (outerName != null && innerName != null) {
        String separator = DescriptorUtils.computeInnerClassSeparator(outerName, name, innerName);
        if (separator == null && version.isLessThan(CfVersion.V9)) {
          application.options.reporter.info(
              new StringDiagnostic(
                  StringUtils.lines(
                      "Malformed inner-class attribute:",
                      "\touterTypeInternal: " + outerName,
                      "\tinnerTypeInternal: " + name,
                      "\tinnerName: " + innerName),
                  origin));
        }
      }
      innerClasses.add(
          new InnerClassAttribute(
              access,
              application.getTypeFromName(name),
              outerName == null ? null : application.getTypeFromName(outerName),
              innerName == null ? null : application.getString(innerName)));
    }

    @Override
    public void visitOuterClass(String owner, String name, String desc) {
      // This is called for anonymous and local inner classes defined in classes or in methods.
      assert enclosingMember == null;
      DexType ownerType = application.getTypeFromName(owner);
      enclosingMember =
          name == null || name.equals("<clinit>")
              ? new EnclosingMethodAttribute(ownerType)
              : new EnclosingMethodAttribute(application.getMethod(ownerType, name, desc));
    }

    @Override
    public void visitNestHost(String nestHost) {
      assert this.nestHost == null && nestMembers.isEmpty();
      DexType nestHostType = application.getTypeFromName(nestHost);
      this.nestHost = new NestHostClassAttribute(nestHostType);
    }

    @Override
    public void visitNestMember(String nestMember) {
      assert nestHost == null;
      DexType nestMemberType = application.getTypeFromName(nestMember);
      nestMembers.add(new NestMemberClassAttribute(nestMemberType));
    }

    private String illegalClassFilePrefix(ClassAccessFlags accessFlags, String name) {
      return "Illegal class file: "
          + (accessFlags.isInterface() ? "Interface" : "Class")
          + " "
          + name;
    }

    private String illegalClassFilePostfix(CfVersion version) {
      return "Class file version " + version;
    }

    private String illegalClassFileMessage(
        ClassAccessFlags accessFlags, String name, CfVersion version, String message) {
      return illegalClassFilePrefix(accessFlags, name)
          + " " + message
          + ". " + illegalClassFilePostfix(version) + ".";
    }

    @Override
    public RecordComponentVisitor visitRecordComponent(
        String name, String descriptor, String signature) {
      assert name != null;
      assert descriptor != null;
      // Javac generated record components are only the instance fields, so we just reuse the field
      // to avoid duplicating the field and field signature rewriting logic.
      DexField field =
          application
              .getFactory()
              .createField(
                  type, application.getTypeFromDescriptor(descriptor), application.getString(name));
      recordComponents.add(field);
      return super.visitRecordComponent(name, descriptor, signature);
    }

    @Override
    public void visitPermittedSubclass(String permittedSubclass) {
      if (classKind == ClassKind.PROGRAM) {
        throw new CompilationError("Sealed classes are not supported as program classes", origin);
      }
      // For library and classpath just ignore the permitted subclasses, as the compiler is not
      // validating the code with respect to sealed classes.
    }

    @Override
    public void visit(
        int rawVersion,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      version = CfVersion.fromRaw(rawVersion);
      if (InternalOptions.SUPPORTED_CF_VERSION.isLessThan(version)) {
        throw new CompilationError("Unsupported class file version: " + version, origin);
      }
      if (version.isGreaterThanOrEqualTo(InternalOptions.EXPERIMENTAL_CF_VERSION)) {
        application.options.warningExperimentalClassFileVersion(origin);
      }
      this.deprecated = AsmUtils.isDeprecated(access);
      accessFlags = ClassAccessFlags.fromCfAccessFlags(cleanAccessFlags(access));
      type = application.getTypeFromName(name);
      // Check if constraints from
      // https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1 are met.
      if (!accessFlags.areValid(version, name.endsWith("/package-info"))) {
        throw new CompilationError(
            illegalClassFileMessage(
                accessFlags,
                name,
                version,
                "has invalid access flags. Found: " + accessFlags.toString()),
            origin);
      }
      if (superName == null && !name.equals(Constants.JAVA_LANG_OBJECT_NAME)) {
        throw new CompilationError(
            illegalClassFileMessage(accessFlags, name, version, "is missing a super type"), origin);
      }
      if (accessFlags.isInterface()
          && !Objects.equals(superName, Constants.JAVA_LANG_OBJECT_NAME)) {
        throw new CompilationError(
            illegalClassFileMessage(
                accessFlags,
                name,
                version,
                "must extend class java.lang.Object. Found: " + superName),
            origin);
      }
      checkName(name);
      assert superName != null || name.equals(Constants.JAVA_LANG_OBJECT_NAME);
      superType = superName == null ? null : application.getTypeFromName(superName);
      this.interfaces = application.getTypeListFromNames(interfaces);
      if (application.options.parseSignatureAttribute()) {
        classSignature =
            GenericSignature.parseClassSignature(
                name, signature, origin, application.getFactory(), application.options.reporter);
      }
    }

    @Override
    public void visitSource(String source, String debug) {
      if (source != null) {
        sourceFile = application.getString(source);
      }
      if (debug != null) {
        getAnnotations().add(
            DexAnnotation.createSourceDebugExtensionAnnotation(
                new DexValueString(application.getString(debug)), application.getFactory()));
      }
    }

    @Override
    public FieldVisitor visitField(
        int access, String name, String desc, String signature, Object value) {
      if (classKind == ClassKind.LIBRARY) {
        FieldAccessFlags flags = createFieldAccessFlags(access);
        if (flags.isPrivate()) {
          return null;
        }
      }
      checkName(name);
      return new CreateFieldVisitor(
          this, access, name, desc, signature, classKind == ClassKind.LIBRARY ? null : value);
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      if (classKind == ClassKind.LIBRARY) {
        MethodAccessFlags flags = createMethodAccessFlags(name, access);
        if ((flags.isStatic() && flags.isConstructor()) || flags.isPrivate()) {
          return null;
        }
      }
      checkName(name);
      return new CreateMethodVisitor(access, name, desc, signature, exceptions, this);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      return createAnnotationVisitor(desc, visible, getAnnotations(), application);
    }

    @Override
    public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc,
        boolean visible) {
      // Java 8 type annotations are not supported by Dex, thus ignore them.
      return null;
    }

    @Override
    public void visitEnd() {
      if (defaultAnnotations != null) {
        addAnnotation(DexAnnotation.createAnnotationDefaultAnnotation(
            type, defaultAnnotations, application.getFactory()));
      }
      checkReachabilitySensitivity();
      checkRecord();
      T clazz =
          classKind.create(
              type,
              Kind.CF,
              origin,
              accessFlags,
              superType,
              interfaces,
              sourceFile,
              nestHost,
              nestMembers,
              enclosingMember,
              innerClasses,
              classSignature,
              createAnnotationSet(annotations, application.options),
              staticFields.toArray(DexEncodedField.EMPTY_ARRAY),
              instanceFields.toArray(DexEncodedField.EMPTY_ARRAY),
              directMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
              virtualMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
              application.getFactory().getSkipNameValidationForTesting(),
              getChecksumSupplier(classKind),
              syntheticMarker);
      InnerClassAttribute innerClassAttribute = clazz.getInnerClassAttributeForThisClass();
      // A member class should not be a local or anonymous class.
      if (innerClassAttribute != null && innerClassAttribute.getOuter() != null) {
        if (innerClassAttribute.isAnonymous()) {
          assert innerClassAttribute.getInnerName() == null;
          // If the enclosing member is not null, the intention would be an anonymous class, and
          // thus the outer-class reference should have been null.  If the enclosing member is null,
          // it is likely due to the missing enclosing member.  In either case, we can recover
          // InnerClasses attribute by erasing the outer-class reference.
          InnerClassAttribute recoveredAttribute = new InnerClassAttribute(
              innerClassAttribute.getAccess(), innerClassAttribute.getInner(), null, null);
          clazz.replaceInnerClassAttributeForThisClass(recoveredAttribute);
        } else if (enclosingMember != null) {
          assert innerClassAttribute.isNamed();
          // It is unclear whether the intention was a member class or a local class. Fail hard.
          throw new CompilationError(
              StringUtils.lines(
                  "A member class cannot also be a (non-member) local class at the same time.",
                  "This is likely due to invalid EnclosingMethod and InnerClasses attributes:",
                  enclosingMember.toString(),
                  innerClassAttribute.toString()),
              origin);
        }
      }
      if (enclosingMember == null
          && (clazz.isLocalClass() || clazz.isAnonymousClass())
          && CfVersion.V1_6.isLessThan(version)) {
        application.options.warningMissingEnclosingMember(clazz.type, clazz.origin, version);
      }
      if (!clazz.isLibraryClass()) {
        context.owner = clazz;
      }
      if (clazz.isProgramClass()) {
        DexProgramClass programClass = clazz.asProgramClass();
        programClass.setInitialClassFileVersion(version);
        if (deprecated) {
          programClass.setDeprecated();
        }
      }
      classConsumer.accept(clazz);
    }

    private void checkRecord() {
      if (!application.options.shouldDesugarRecords()) {
        return;
      }
      if (!accessFlags.isRecord()) {
        return;
      }
      application.setHasReadRecordReferenceFromProgramClass();
      // TODO(b/169645628): Change this logic if we start stripping the record components.
      // Another approach would be to mark a bit in fields that are record components instead.
      String message = "Records are expected to have one record component per instance field.";
      if (recordComponents.size() != instanceFields.size()) {
        throw new CompilationError(message, origin);
      }
      for (DexEncodedField instanceField : instanceFields) {
        if (!recordComponents.contains(instanceField.getReference())) {
          throw new CompilationError(
              message + " Unmatched field " + instanceField.getReference() + ".", origin);
        }
      }
    }

    private ChecksumSupplier getChecksumSupplier(ClassKind<T> classKind) {
      if (application.options.encodeChecksums && classKind == ClassKind.PROGRAM) {
        CRC32 crc = new CRC32();
        crc.update(this.context.classCache, 0, this.context.classCache.length);
        final long value = crc.getValue();
        return clazz -> value;
      }
      return DexProgramClass::invalidChecksumRequest;
    }

    private void checkName(String name) {
      if (!application.getFactory().getSkipNameValidationForTesting()
          && !DexString.isValidSimpleName(application.options.getMinApiLevel(), name)) {
        throw new CompilationError("Space characters in SimpleName '"
          + name + "' are not allowed prior to DEX version 040");
      }
    }

    // If anything is marked reachability sensitive, all methods need to be parsed including
    // locals information. This propagates the reachability sensitivity bit so that if any field
    // or method is annotated, all methods get parsed with locals information.
    private void checkReachabilitySensitivity() {
      if (hasReachabilitySensitiveMethod || hasReachabilitySensitiveField()) {
        for (DexEncodedMethod method : Iterables.concat(directMethods, virtualMethods)) {
          Code code = method.getCode();
          if (code != null && code.isCfCode()) {
            code.asLazyCfCode().markReachabilitySensitive();
          }
        }
      }
    }

    private boolean hasReachabilitySensitiveField() {
      DexType reachabilitySensitive = application.getFactory().annotationReachabilitySensitive;
      for (DexEncodedField field : Iterables.concat(instanceFields, staticFields)) {
        for (DexAnnotation annotation : field.annotations().annotations) {
          if (annotation.annotation.type == reachabilitySensitive) {
            return true;
          }
        }
      }
      return false;
    }

    private void addDefaultAnnotation(String name, DexValue value) {
      if (defaultAnnotations == null) {
        defaultAnnotations = new ArrayList<>();
      }
      defaultAnnotations.add(new DexAnnotationElement(application.getString(name), value));
    }

    private void addAnnotation(DexAnnotation annotation) {
      getAnnotations().add(annotation);
    }

    private List<DexAnnotation> getAnnotations() {
      if (annotations == null) {
        annotations = new ArrayList<>();
      }
      return annotations;
    }

    public boolean isInANest() {
      return !nestMembers.isEmpty() || nestHost != null;
    }
  }

  private static DexAnnotationSet createAnnotationSet(
      List<DexAnnotation> annotations, InternalOptions options) {
    if (annotations == null || annotations.isEmpty()) {
      return DexAnnotationSet.empty();
    }
    if (options.isGeneratingDex()) {
      DexType dupType = DexAnnotationSet.findDuplicateEntryType(annotations);
      if (dupType != null) {
        throw new CompilationError(
            "Multiple annotations of type `" + dupType.toSourceString() + "`");
      }
    }
    return DexAnnotationSet.create(annotations.toArray(DexAnnotation.EMPTY_ARRAY));
  }

  private static class CreateFieldVisitor extends FieldVisitor {

    private final CreateDexClassVisitor<?> parent;
    private final int access;
    private final String name;
    private final String desc;
    private final Object value;
    private final FieldTypeSignature fieldSignature;
    private List<DexAnnotation> annotations = null;

    public CreateFieldVisitor(
        CreateDexClassVisitor<?> parent,
        int access,
        String name,
        String desc,
        String signature,
        Object value) {
      super(ASM_VERSION);
      this.parent = parent;
      this.access = access;
      this.name = name;
      this.desc = desc;
      this.value = value;
      this.fieldSignature =
          parent.application.options.parseSignatureAttribute()
              ? GenericSignature.parseFieldTypeSignature(
                  name,
                  signature,
                  parent.origin,
                  parent.application.getFactory(),
                  parent.application.options.reporter)
              : FieldTypeSignature.noSignature();
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      return createAnnotationVisitor(desc, visible, getAnnotations(), parent.application);
    }

    @Override
    public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc,
        boolean visible) {
      // Java 8 type annotations are not supported by Dex, thus ignore them.
      return null;
    }

    @Override
    public void visitEnd() {
      FieldAccessFlags flags = createFieldAccessFlags(access);
      DexField dexField = parent.application.getField(parent.type, name, desc);
      parent.application.checkFieldForRecord(dexField);
      Wrapper<DexField> signature = FieldSignatureEquivalence.get().wrap(dexField);
      if (parent.fieldSignatures.add(signature)) {
        DexAnnotationSet annotationSet =
            createAnnotationSet(annotations, parent.application.options);
        DexValue staticValue = flags.isStatic() ? getStaticValue(value, dexField.type) : null;
        DexEncodedField field =
            DexEncodedField.builder()
                .setField(dexField)
                .setAccessFlags(flags)
                .setGenericSignature(fieldSignature)
                .setAnnotations(annotationSet)
                .setStaticValue(staticValue)
                .setDeprecated(AsmUtils.isDeprecated(access))
                .disableAndroidApiLevelCheck()
                .build();
        if (flags.isStatic()) {
          parent.staticFields.add(field);
        } else {
          parent.instanceFields.add(field);
        }
      } else {
        parent.application.options.reporter.warning(
            new StringDiagnostic(
                String.format("Field `%s` has multiple definitions", dexField.toSourceString())));
      }
    }

    private DexValue getStaticValue(Object value, DexType type) {
      if (value == null) {
        return null;
      }
      DexItemFactory factory = parent.application.getFactory();
      if (type == factory.booleanType) {
        int i = (Integer) value;
        assert 0 <= i && i <= 1;
        return DexValueBoolean.create(i == 1);
      }
      if (type == factory.byteType) {
        return DexValueByte.create(((Integer) value).byteValue());
      }
      if (type == factory.shortType) {
        return DexValueShort.create(((Integer) value).shortValue());
      }
      if (type == factory.charType) {
        return DexValueChar.create((char) ((Integer) value).intValue());
      }
      if (type == factory.intType) {
        return DexValueInt.create((Integer) value);
      }
      if (type == factory.floatType) {
        return DexValueFloat.create((Float) value);
      }
      if (type == factory.longType) {
        return DexValueLong.create((Long) value);
      }
      if (type == factory.doubleType) {
        return DexValueDouble.create((Double) value);
      }
      if (type == factory.stringType) {
        return new DexValueString(factory.createString((String) value));
      }
      throw new Unreachable("Unexpected static-value type " + type);
    }

    private List<DexAnnotation> getAnnotations() {
      if (annotations == null) {
        annotations = new ArrayList<>();
      }
      return annotations;
    }
  }

  private static class CreateMethodVisitor extends MethodVisitor {

    private final String name;
    final CreateDexClassVisitor<?> parent;
    private final int parameterCount;
    private List<DexAnnotation> annotations = null;
    private DexValue defaultAnnotation = null;
    private int annotableParameterCount = -1;
    private List<List<DexAnnotation>> parameterAnnotationsLists = null;
    private List<DexValue> parameterNames = null;
    private List<DexValue> parameterFlags = null;
    private final MethodTypeSignature genericSignature;
    final DexMethod method;
    final MethodAccessFlags flags;
    final boolean deprecated;
    Code code = null;

    public CreateMethodVisitor(
        int access,
        String name,
        String desc,
        String signature,
        String[] exceptions,
        CreateDexClassVisitor<?> parent) {
      super(ASM_VERSION);
      this.name = name;
      this.parent = parent;
      this.method = parent.application.getMethod(parent.type, name, desc);
      this.flags = createMethodAccessFlags(name, access);
      this.deprecated = AsmUtils.isDeprecated(access);
      parameterCount = DescriptorUtils.getArgumentCount(desc);
      if (exceptions != null && exceptions.length > 0) {
        DexValue[] values = new DexValue[exceptions.length];
        for (int i = 0; i < exceptions.length; i++) {
          values[i] = new DexValueType(parent.application.getTypeFromName(exceptions[i]));
        }
        addAnnotation(DexAnnotation.createThrowsAnnotation(
            values, parent.application.getFactory()));
      }
      genericSignature =
          parent.application.options.parseSignatureAttribute()
              ? GenericSignature.parseMethodSignature(
                  name,
                  signature,
                  parent.origin,
                  parent.application.getFactory(),
                  parent.application.options.reporter)
              : MethodTypeSignature.noSignature();
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      return createAnnotationVisitor(desc, visible, getAnnotations(), parent.application);
    }

    @Override
    public AnnotationVisitor visitAnnotationDefault() {
      return new CreateAnnotationVisitor(parent.application, (names, elements) -> {
        assert elements.size() == 1;
        defaultAnnotation = elements.get(0);
      });
    }

    @Override
    public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc,
        boolean visible) {
      // Java 8 type annotations are not supported by Dex, thus ignore them.
      return null;
    }

    @Override
    public void visitAnnotableParameterCount(int parameterCount, boolean visible) {
      if (annotableParameterCount != -1) {
        // TODO(113565942): We assume that the runtime visible and runtime invisible parameter
        // count is always the same. It doesn't have to be according to the classfile format, so
        // we really should split it into two sets.
        assert annotableParameterCount == parameterCount;
      }
      annotableParameterCount = parameterCount;
    }

    @Override
    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
      if (parameterAnnotationsLists == null) {
        if (annotableParameterCount == -1) {
          annotableParameterCount = parameterCount;
        }
        parameterAnnotationsLists = new ArrayList<>(annotableParameterCount);
        for (int i = 0; i < annotableParameterCount; i++) {
          parameterAnnotationsLists.add(new ArrayList<>());
        }
      }
      assert mv == null;
      return createAnnotationVisitor(desc, visible,
          parameterAnnotationsLists.get(parameter), parent.application);
    }

    @Override
    public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String desc,
        boolean visible) {
      // Java 8 type annotations are not supported by Dex, thus ignore them.
      return null;
    }

    @Override
    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath,
        Label[] start, Label[] end, int[] index, String desc, boolean visible) {
      // Java 8 type annotations are not supported by Dex, thus ignore them.
      return null;
    }

    @Override
    public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String desc,
        boolean visible) {
      // Java 8 type annotations are not supported by Dex, thus ignore them.
      return null;
    }

    @Override
    public void visitParameter(String name, int access) {
      if (parameterNames == null) {
        assert parameterFlags == null;
        parameterNames = new ArrayList<>(parameterCount);
        parameterFlags = new ArrayList<>(parameterCount);
      }
      parameterNames.add(new DexValueString(parent.application.getFactory().createString(name)));
      parameterFlags.add(DexValueInt.create(access));
      super.visitParameter(name, access);
    }

    @Override
    public void visitCode() {
      throw new Unreachable("visitCode() should not be called when SKIP_CODE is set");
    }

    private boolean classRequiresCode() {
      return parent.classKind == ClassKind.PROGRAM
          || (!parent.application.options.canUseNestBasedAccess()
              && parent.classKind == ClassKind.CLASSPATH
              && parent.isInANest());
    }

    @Override
    public void visitEnd() {
      InternalOptions options = parent.application.options;
      parent.application.checkMethodForRecord(method);
      if (!flags.isAbstract() && !flags.isNative() && classRequiresCode()) {
        code = new LazyCfCode(method, parent.origin, parent.context, parent.application);
      }
      ParameterAnnotationsList parameterAnnotationsList;
      if (parameterAnnotationsLists == null) {
        parameterAnnotationsList = ParameterAnnotationsList.empty();
      } else {
        DexAnnotationSet[] sets = new DexAnnotationSet[parameterAnnotationsLists.size()];
        for (int i = 0; i < parameterAnnotationsLists.size(); i++) {
          sets[i] = createAnnotationSet(parameterAnnotationsLists.get(i), options);
        }
        parameterAnnotationsList = ParameterAnnotationsList.create(sets);
      }
      if (parameterNames != null) {
        assert parameterFlags != null;
        if (parameterNames.size() != parameterCount) {
          options.warningInvalidParameterAnnotations(
              method, parent.origin, parameterCount, parameterNames.size());
        }
        getAnnotations().add(DexAnnotation.createMethodParametersAnnotation(
            parameterNames.toArray(DexValue.EMPTY_ARRAY),
            parameterFlags.toArray(DexValue.EMPTY_ARRAY),
            parent.application.getFactory()));
      }
      DexEncodedMethod dexMethod =
          DexEncodedMethod.builder()
              .setMethod(method)
              .setAccessFlags(flags)
              .setGenericSignature(genericSignature)
              .setAnnotations(createAnnotationSet(annotations, options))
              .setParameterAnnotations(parameterAnnotationsList)
              .setCode(code)
              .setClassFileVersion(parent.version)
              .setDeprecated(deprecated)
              .disableParameterAnnotationListCheck()
              .disableAndroidApiLevelCheck()
              .build();
      Wrapper<DexMethod> signature = MethodSignatureEquivalence.get().wrap(method);
      if (parent.methodSignatures.add(signature)) {
        parent.hasReachabilitySensitiveMethod |= isReachabilitySensitive();
        if (flags.isStatic() || flags.isConstructor() || flags.isPrivate()) {
          parent.directMethods.add(dexMethod);
        } else {
          parent.virtualMethods.add(dexMethod);
        }
      } else {
        options.reporter.warning(
            new StringDiagnostic(
                String.format(
                    "Ignoring an implementation of the method `%s` because it has multiple "
                        + "definitions",
                    method.toSourceString())));
      }
      if (defaultAnnotation != null) {
        parent.addDefaultAnnotation(name, defaultAnnotation);
      }
    }

    private boolean isReachabilitySensitive() {
      DexType reachabilitySensitive =
          parent.application.getFactory().annotationReachabilitySensitive;
      for (DexAnnotation annotation : getAnnotations()) {
        if (annotation.annotation.type == reachabilitySensitive) {
          return true;
        }
      }
      return false;
    }

    private List<DexAnnotation> getAnnotations() {
      if (annotations == null) {
        annotations = new ArrayList<>();
      }
      return annotations;
    }

    private void addAnnotation(DexAnnotation annotation) {
      getAnnotations().add(annotation);
    }
  }

  private static class CreateAnnotationVisitor extends AnnotationVisitor {

    private final JarApplicationReader application;
    private final BiConsumer<List<DexString>, List<DexValue>> onVisitEnd;
    private List<DexString> names = null;
    private final List<DexValue> values = new ArrayList<>();

    public CreateAnnotationVisitor(
        JarApplicationReader application, BiConsumer<List<DexString>, List<DexValue>> onVisitEnd) {
      super(ASM_VERSION);
      this.application = application;
      this.onVisitEnd = onVisitEnd;
    }

    @Override
    public void visit(String name, Object value) {
      addElement(name, getDexValue(value));
    }

    @Override
    public void visitEnum(String name, String desc, String value) {
      DexType owner = application.getTypeFromDescriptor(desc);
      addElement(name, new DexValueEnum(application.getField(owner, value, desc)));
    }

    @Override
    public AnnotationVisitor visitAnnotation(String name, String desc) {
      return new CreateAnnotationVisitor(application, (names, values) ->
          addElement(name, new DexValueAnnotation(
              createEncodedAnnotation(desc, names, values, application))));
    }

    @Override
    public AnnotationVisitor visitArray(String name) {
      return new CreateAnnotationVisitor(application, (names, values) -> {
        assert names == null;
        addElement(name, new DexValueArray(values.toArray(DexValue.EMPTY_ARRAY)));
      });
    }

    @Override
    public void visitEnd() {
      onVisitEnd.accept(names, values);
    }

    private void addElement(String name, DexValue value) {
      if (name != null) {
        if (names == null) {
          names = new ArrayList<>();
        }
        names.add(application.getString(name));
      }
      values.add(value);
    }

    private static DexValueArray getDexValueArray(Object value) {
      if (value instanceof byte[]) {
        byte[] values = (byte[]) value;
        DexValue[] elements = new DexValue[values.length];
        for (int i = 0; i < values.length; i++) {
          elements[i] = DexValueByte.create(values[i]);
        }
        return new DexValueArray(elements);
      } else if (value instanceof boolean[]) {
        boolean[] values = (boolean[]) value;
        DexValue[] elements = new DexValue[values.length];
        for (int i = 0; i < values.length; i++) {
          elements[i] = DexValueBoolean.create(values[i]);
        }
        return new DexValueArray(elements);
      } else if (value instanceof char[]) {
        char[] values = (char[]) value;
        DexValue[] elements = new DexValue[values.length];
        for (int i = 0; i < values.length; i++) {
          elements[i] = DexValueChar.create(values[i]);
        }
        return new DexValueArray(elements);
      } else if (value instanceof short[]) {
        short[] values = (short[]) value;
        DexValue[] elements = new DexValue[values.length];
        for (int i = 0; i < values.length; i++) {
          elements[i] = DexValueShort.create(values[i]);
        }
        return new DexValueArray(elements);
      } else if (value instanceof int[]) {
        int[] values = (int[]) value;
        DexValue[] elements = new DexValue[values.length];
        for (int i = 0; i < values.length; i++) {
          elements[i] = DexValueInt.create(values[i]);
        }
        return new DexValueArray(elements);
      } else if (value instanceof long[]) {
        long[] values = (long[]) value;
        DexValue[] elements = new DexValue[values.length];
        for (int i = 0; i < values.length; i++) {
          elements[i] = DexValueLong.create(values[i]);
        }
        return new DexValueArray(elements);
      } else if (value instanceof float[]) {
        float[] values = (float[]) value;
        DexValue[] elements = new DexValue[values.length];
        for (int i = 0; i < values.length; i++) {
          elements[i] = DexValueFloat.create(values[i]);
        }
        return new DexValueArray(elements);
      } else if (value instanceof double[]) {
        double[] values = (double[]) value;
        DexValue[] elements = new DexValue[values.length];
        for (int i = 0; i < values.length; i++) {
          elements[i] = DexValueDouble.create(values[i]);
        }
        return new DexValueArray(elements);
      }
      throw new Unreachable("Unexpected type of annotation value: " + value);
    }

    private DexValue getDexValue(Object value) {
      if (value == null) {
        return DexValueNull.NULL;
      }
      if (value instanceof Byte) {
        return DexValueByte.create((Byte) value);
      } else if (value instanceof Boolean) {
        return DexValueBoolean.create((Boolean) value);
      } else if (value instanceof Character) {
        return DexValueChar.create((Character) value);
      } else if (value instanceof Short) {
        return DexValueShort.create((Short) value);
      } else if (value instanceof Integer) {
        return DexValueInt.create((Integer) value);
      } else if (value instanceof Long) {
        return DexValueLong.create((Long) value);
      } else if (value instanceof Float) {
        return DexValueFloat.create((Float) value);
      } else if (value instanceof Double) {
        return DexValueDouble.create((Double) value);
      } else if (value instanceof String) {
        return new DexValueString(application.getString((String) value));
      } else if (value instanceof Type) {
        return new DexValueType(application.getTypeFromDescriptor(((Type) value).getDescriptor()));
      }
      return getDexValueArray(value);
    }
  }

  public static class ReparseContext {

    // This will hold the content of the whole class. Once all the methods of the class are swapped
    // from this to the actual JarCode, no other references would be left and the content can be
    // GC'd.
    public byte[] classCache;
    public DexClass owner;
    public final List<Code> codeList = new ArrayList<>();
  }
}
