// 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 org.objectweb.asm.ClassReader.SKIP_FRAMES;
import static org.objectweb.asm.Opcodes.ACC_DEPRECATED;
import static org.objectweb.asm.Opcodes.ASM5;

import com.android.tools.r8.Resource;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
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.JarCode.ReparseContext;
import com.android.tools.r8.utils.InternalOptions;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
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.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.TypePath;

/**
 * Java/Jar class reader for constructing dex/graph structure.
 */
public class JarClassFileReader {

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

  private final JarApplicationReader application;
  private final Consumer<DexClass> classConsumer;

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

  public void read(String file, ClassKind classKind, InputStream input) throws IOException {
    ClassReader reader = new ClassReader(input);
    reader.accept(new CreateDexClassVisitor(
        file, classKind, reader.b, application, classConsumer), SKIP_FRAMES);
  }

  private static DexAccessFlags createAccessFlags(int access) {
    // Clear the "synthetic attribute" and "deprecated" flags if preset.
    return new DexAccessFlags(access & ~ACC_SYNTHETIC_ATTRIBUTE & ~ACC_DEPRECATED);
  }

  private static AnnotationVisitor createAnnotationVisitor(String desc, boolean visible,
      List<DexAnnotation> annotations,
      JarApplicationReader application) {
    assert annotations != null;
    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))));
  }

  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 extends ClassVisitor {
    private final String file;
    private final ClassKind classKind;
    private final JarApplicationReader application;
    private final Consumer<DexClass> classConsumer;
    private final ReparseContext context = new ReparseContext();

    // DexClass data.
    private DexType type;
    private DexAccessFlags accessFlags;
    private DexType superType;
    private DexTypeList interfaces;
    private DexString sourceFile;
    private List<DexType> memberClasses = null;
    private List<DexAnnotation> annotations = null;
    private List<DexAnnotationElement> defaultAnnotations = null;
    private DexAnnotation innerClassAnnotation = null;
    private DexAnnotation enclosingAnnotation = null;
    private final List<DexEncodedField> staticFields = new ArrayList<>();
    private final List<DexEncodedField> instanceFields = new ArrayList<>();
    private final List<DexEncodedMethod> directMethods = new ArrayList<>();
    private final List<DexEncodedMethod> virtualMethods = new ArrayList<>();

    public CreateDexClassVisitor(
        String file,
        ClassKind classKind,
        byte[] classCache,
        JarApplicationReader application,
        Consumer<DexClass> classConsumer) {
      super(ASM5);
      this.file = file;
      this.classKind = classKind;
      this.classConsumer = classConsumer;
      this.context.classCache = classCache;
      this.application = application;
    }

    @Override
    public void visitInnerClass(String name, String outerName, String innerName, int access) {
      if (type == application.getTypeFromName(name)) {
        // If the inner class is this class, record its original access flags and name in its
        // InnerClass annotation. We defer storing the actual annotation until we have found
        // a matching enclosing annotation.
        assert innerClassAnnotation == null;
        innerClassAnnotation = DexAnnotation.createInnerClassAnnotation(
            innerName, access, application.getFactory());
        // If this is a named inner class (in which case outerName and innerName are defined)
        // record the outer class in its EnclosingClass annotation.
        if (outerName != null && innerName != null) {
          assert enclosingAnnotation == null;
          enclosingAnnotation = DexAnnotation.createEnclosingClassAnnotation(
              application.getTypeFromName(outerName),
              application.getFactory());
        }
      } else if (outerName != null && innerName != null
          && type == application.getTypeFromName(outerName)) {
        // If the inner class is a member of this class, record it for the MemberClasses annotation.
        if (memberClasses == null) {
          memberClasses = new ArrayList<>();
        }
        memberClasses.add(application.getTypeFromName(name));
      }
    }

    @Override
    public void visitOuterClass(String owner, String name, String desc) {
      assert enclosingAnnotation == null;
      // This is called for anonymous inner classes defined in classes or in methods.
      DexType ownerType = application.getTypeFromName(owner);
      if (name == null) {
        enclosingAnnotation = DexAnnotation.createEnclosingClassAnnotation(
            ownerType, application.getFactory());
      } else {
        enclosingAnnotation = DexAnnotation.createEnclosingMethodAnnotation(
            application.getMethod(ownerType, name, desc), application.getFactory());
      }
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName,
        String[] interfaces) {
      accessFlags = createAccessFlags(access);
      // Unset the (in dex) non-existent ACC_SUPER flag on the class.
      assert Constants.ACC_SYNCHRONIZED == Opcodes.ACC_SUPER;
      accessFlags.unsetSynchronized();
      type = application.getTypeFromName(name);
      assert superName != null || name.equals(Constants.JAVA_LANG_OBJECT_NAME);
      superType = superName == null ? null : application.getTypeFromName(superName);
      this.interfaces = application.getTypeListFromNames(interfaces);
      if (signature != null && !signature.isEmpty()) {
        addAnnotation(DexAnnotation.createSignatureAnnotation(signature, application.getFactory()));
      }
    }

    @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) {
      return new CreateFieldVisitor(this, access, name, desc, signature, value);
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      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 visitAttribute(Attribute attr) {
      // Unknown attribute must only be ignored
    }

    @Override
    public void visitEnd() {
      if (memberClasses != null) {
        assert !memberClasses.isEmpty();
        addAnnotation(DexAnnotation.createMemberClassesAnnotation(
            memberClasses, application.getFactory()));
      }
      if (innerClassAnnotation != null) {
        if (enclosingAnnotation == null) {
          application.options.warningMissingEnclosingMember = true;
        } else {
          addAnnotation(innerClassAnnotation);
          addAnnotation(enclosingAnnotation);
        }
      }
      if (defaultAnnotations != null) {
        addAnnotation(DexAnnotation.createAnnotationDefaultAnnotation(
            type, defaultAnnotations, application.getFactory()));
      }
      DexClass clazz = classKind.create(
          type,
          Resource.Kind.CLASSFILE, 
          accessFlags,
          superType,
          interfaces,
          sourceFile,
          createAnnotationSet(annotations),
          staticFields.toArray(new DexEncodedField[staticFields.size()]),
          instanceFields.toArray(new DexEncodedField[instanceFields.size()]),
          directMethods.toArray(new DexEncodedMethod[directMethods.size()]),
          virtualMethods.toArray(new DexEncodedMethod[virtualMethods.size()]));
      if (classKind == ClassKind.PROGRAM) {
        context.owner = clazz.asProgramClass();
      }
      classConsumer.accept(clazz);
    }

    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;
    }
  }

  private static DexAnnotationSet createAnnotationSet(List<DexAnnotation> annotations) {
    return annotations == null || annotations.isEmpty()
        ? DexAnnotationSet.empty()
        : new DexAnnotationSet(annotations.toArray(new DexAnnotation[annotations.size()]));
  }

  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 List<DexAnnotation> annotations = null;

    public CreateFieldVisitor(CreateDexClassVisitor parent,
        int access, String name, String desc, String signature, Object value) {
      super(ASM5);
      this.parent = parent;
      this.access = access;
      this.name = name;
      this.desc = desc;
      this.value = value;
      if (signature != null && !signature.isEmpty()) {
        addAnnotation(DexAnnotation.createSignatureAnnotation(
            signature, parent.application.getFactory()));
      }
    }

    @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() {
      DexAccessFlags flags = createAccessFlags(access);
      DexField dexField = parent.application.getField(parent.type, name, desc);
      DexAnnotationSet annotationSet = createAnnotationSet(annotations);
      DexValue staticValue = flags.isStatic() ? getStaticValue(value, dexField.type) : null;
      DexEncodedField field = new DexEncodedField(dexField, flags, annotationSet, staticValue);
      if (flags.isStatic()) {
        parent.staticFields.add(field);
      } else {
        parent.instanceFields.add(field);
      }
    }

    private DexValue getStaticValue(Object value, DexType type) {
      if (value == null) {
        return DexValue.defaultForType(type, parent.application.getFactory());
      }
      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 void addAnnotation(DexAnnotation annotation) {
      getAnnotations().add(annotation);
    }

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

  private static class CreateMethodVisitor extends MethodVisitor {
    private final int access;
    private final String name;
    private final String desc;
    private final CreateDexClassVisitor parent;
    private final int parameterCount;
    private List<DexAnnotation> annotations = null;
    private DexValue defaultAnnotation = null;
    private int fakeParameterAnnotations = 0;
    private List<List<DexAnnotation>> parameterAnnotations = null;
    private List<DexValue> parameterNames = null;
    private List<DexValue> parameterFlags = null;

    public CreateMethodVisitor(int access, String name, String desc, String signature,
        String[] exceptions, CreateDexClassVisitor parent) {
      super(ASM5);
      this.access = access;
      this.name = name;
      this.desc = desc;
      this.parent = parent;
      parameterCount = Type.getArgumentTypes(desc).length;
      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()));
      }
      if (signature != null && !signature.isEmpty()) {
        addAnnotation(DexAnnotation.createSignatureAnnotation(
            signature, parent.application.getFactory()));
      }
    }

    @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 AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
      // ASM decided to workaround a javac bug that incorrectly deals with synthesized parameter
      // annotations. However, that leads us to have different behavior than javac+jvm and
      // dx+art. The workaround is to use a non-existing descriptor "Ljava/lang/Synthetic;" for
      // exactly this case. In order to remove the workaround we ignore all annotations
      // with that descriptor. If javac is fixed, the ASM workaround will not be hit and we will
      // never see this non-existing annotation descriptor. ASM uses the same check to make
      // sure to undo their workaround for the javac bug in their MethodWriter.
      if (desc.equals("Ljava/lang/Synthetic;")) {
        // We can iterate through all the parameters twice. Once for visible and once for
        // invisible parameter annotations. We only record the number of fake parameter
        // annotations once.
        if (parameterAnnotations == null) {
          fakeParameterAnnotations++;
        }
        return null;
      }
      if (parameterAnnotations == null) {
        int adjustedParameterCount = parameterCount - fakeParameterAnnotations;
        parameterAnnotations = new ArrayList<>(adjustedParameterCount);
        for (int i = 0; i < adjustedParameterCount; i++) {
          parameterAnnotations.add(new ArrayList<>());
        }
      }
      assert mv == null;
      return createAnnotationVisitor(desc, visible,
          parameterAnnotations.get(parameter - fakeParameterAnnotations), 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 visitEnd() {
      DexMethod method = parent.application.getMethod(parent.type, name, desc);
      DexAccessFlags flags = createMethodAccessFlags(access);
      Code code = null;
      if (!flags.isAbstract()
          && !flags.isNative()
          && parent.classKind == ClassKind.PROGRAM) {
        code = new JarCode(method, parent.context, parent.application);
      }
      DexAnnotationSetRefList parameterAnnotationSets;
      if (parameterAnnotations == null) {
        parameterAnnotationSets = DexAnnotationSetRefList.empty();
      } else {
        DexAnnotationSet[] sets = new DexAnnotationSet[parameterAnnotations.size()];
        for (int i = 0; i < parameterAnnotations.size(); i++) {
          sets[i] = createAnnotationSet(parameterAnnotations.get(i));
        }
        parameterAnnotationSets = new DexAnnotationSetRefList(sets);
      }
      InternalOptions internalOptions = parent.application.options;
      if (parameterNames != null && internalOptions.allowParameterName
          && internalOptions.canUseParameterNameAnnotations()) {
        assert parameterFlags != null;
        if (parameterNames.size() != parameterCount) {
          internalOptions.warningInvalidParameterAnnotations =
              "Invalid parameter count in MethodParameters attributes of "
                  + method.toSourceString() + " from '" + parent.file + "'. Found "
                  + parameterNames.size() + " while expecting " + parameterCount + "."
                  + " This is likely due to proguard having removed a parameter.";
        }
        getAnnotations().add(DexAnnotation.createMethodParametersAnnotation(
            parameterNames.toArray(new DexValue[parameterNames.size()]),
            parameterFlags.toArray(new DexValue[parameterFlags.size()]),
            parent.application.getFactory()));
      }
      DexEncodedMethod dexMethod = new DexEncodedMethod(method, flags,
          createAnnotationSet(annotations), parameterAnnotationSets, code);
      if (flags.isStatic() || flags.isConstructor() || flags.isPrivate()) {
        parent.directMethods.add(dexMethod);
      } else {
        parent.virtualMethods.add(dexMethod);
      }
      if (defaultAnnotation != null) {
        parent.addDefaultAnnotation(name, defaultAnnotation);
      }
    }

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

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

    private DexAccessFlags createMethodAccessFlags(int access) {
      DexAccessFlags flags = createAccessFlags(access);
      // Set just the dex specific declared-synchronized flag if the method is synchronized.
      // TODO(zerny): Should declared sync also be set if it is native?
      if (flags.isSynchronized() && !flags.isNative()) {
        flags.unsetSynchronized();
        flags.setDeclaredSynchronized();
      }
      // Set the constructor bit on instance and class initializers.
      if (name.equals(Constants.INSTANCE_INITIALIZER_NAME) || name.equals(
          Constants.CLASS_INITIALIZER_NAME)) {
        flags.setConstructor();
      }
      return flags;
    }
  }

  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(ASM5);
      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(new DexValue[values.size()])));
      });
    }

    @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);
    }
  }
}
