// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.importdeps;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.importdeps.ClassInfo.MemberInfo;
import java.util.Optional;
import javax.annotation.Nullable;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Handle;
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;

/** Checker to check whether a class has missing dependencies on its classpath. */
public class DepsCheckerClassVisitor extends ClassVisitor {

  private String internalName;
  private final ClassCache classCache;
  private final ResultCollector resultCollector;

  private final DepsCheckerAnnotationVisitor defaultAnnotationChecker =
      new DepsCheckerAnnotationVisitor();
  private final DepsCheckerFieldVisitor defaultFieldChecker = new DepsCheckerFieldVisitor();
  private final DepsCheckerMethodVisitor defaultMethodChecker = new DepsCheckerMethodVisitor();

  public DepsCheckerClassVisitor(ClassCache classCache, ResultCollector resultCollector) {
    super(Opcodes.ASM6);
    this.classCache = classCache;
    this.resultCollector = resultCollector;
  }

  @Override
  public void visit(
      int version,
      int access,
      String name,
      String signature,
      String superName,
      String[] interfaces) {
    checkState(internalName == null, "Cannot reuse this class visitor %s", getClass());
    this.internalName = name;
    checkInternalName(superName);
    checkInternalNameArray(interfaces);
    super.visit(version, access, name, signature, superName, interfaces);
  }

  @Override
  public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
    checkDescriptor(desc);
    return defaultAnnotationChecker;
  }

  @Override
  public FieldVisitor visitField(
      int access, String name, String desc, String signature, Object value) {
    checkDescriptor(desc);
    return defaultFieldChecker;
  }

  @Override
  public MethodVisitor visitMethod(
      int access, String name, String desc, String signature, String[] exceptions) {
    checkInternalNameArray(exceptions);
    checkDescriptor(desc);
    return defaultMethodChecker;
  }

  @Override
  public AnnotationVisitor visitTypeAnnotation(
      int typeRef, TypePath typePath, String desc, boolean visible) {
    checkDescriptor(desc);
    return defaultAnnotationChecker;
  }

  private void checkMember(String owner, String name, String desc) {
    try {
      if (checkInternalNameOrArrayDescriptor(owner)) {
        // The owner is an array descriptor.
        return; // Assume all methods of arrays exist by default.
      }
      checkDescriptor(desc);
      AbstractClassEntryState state = checkInternalName(owner);

      Optional<ClassInfo> classInfo = state.classInfo();
      if (!classInfo.isPresent()) {
        checkState(state.isMissingState(), "The state should be MissingState. %s", state);
        return; // The class is already missing.
      }
      MemberInfo member = MemberInfo.create(name, desc);
      if (!classInfo.get().containsMember(member)) {
        resultCollector.addMissingMember(classInfo.get(), member);
      }
    } catch (RuntimeException e) {
      System.err.printf(
          "A runtime exception occurred when checking the member: owner=%s, name=%s, desc=%s\n",
          owner, name, desc);
      throw e;
    }
  }

  private void checkDescriptor(String desc) {
    checkType(Type.getType(desc));
  }

  private void checkType(Type type) {
    switch (type.getSort()) {
      case Type.BOOLEAN:
      case Type.BYTE:
      case Type.CHAR:
      case Type.SHORT:
      case Type.INT:
      case Type.LONG:
      case Type.FLOAT:
      case Type.DOUBLE:
      case Type.VOID:
        return; // Ignore primitive types.
      case Type.ARRAY:
        checkType(type.getElementType());
        return;
      case Type.METHOD:
        for (Type argumentType : type.getArgumentTypes()) {
          checkType(argumentType);
        }
        checkType(type.getReturnType());
        return;
      case Type.OBJECT:
        checkInternalName(type.getInternalName());
        return;
      default:
        throw new UnsupportedOperationException("Unhandled type: " + type);
    }
  }

  /**
   * Checks the type, and returns {@literal true} if the type is an array descriptor, otherwise
   * {@literal false}
   */
  private boolean checkInternalNameOrArrayDescriptor(String type) {
    if (type.charAt(0) == '[') {
      checkDescriptor(type);
      return true;
    } else {
      checkInternalName(type);
      return false;
    }
  }

  private AbstractClassEntryState checkInternalName(String internalName) {
    checkArgument(
        internalName.length() > 0 && Character.isJavaIdentifierStart(internalName.charAt(0)),
        "The internal name is invalid. %s",
        internalName);
    AbstractClassEntryState state = classCache.getClassState(internalName);
    if (state.isMissingState()) {
      resultCollector.addMissingOrIncompleteClass(internalName, state);
    } else {
      if (state.isIncompleteState()) {
        state
            .asIncompleteState()
            .missingAncestors()
            .forEach(
                missingAncestor -> {
                  AbstractClassEntryState ancestorState = classCache.getClassState(missingAncestor);
                  checkState(
                      ancestorState.isMissingState(),
                      "The ancestor should be missing. %s",
                      ancestorState);
                  resultCollector.addMissingOrIncompleteClass(missingAncestor, ancestorState);
                  resultCollector.addMissingOrIncompleteClass(internalName, state);
                });
      }
      ClassInfo info = state.classInfo().get();
      if (!info.directDep()) {
        resultCollector.addIndirectDep(info.jarPath());
      }
    }
    return state;
  }

  private void checkInternalNameArray(@Nullable String[] internalNames) {
    if (internalNames == null) {
      return;
    }
    for (String internalName : internalNames) {
      checkInternalName(internalName);
    }
  }

  private static final ImmutableSet<Class<?>> PRIMITIVE_TYPES =
      ImmutableSet.of(
          Boolean.class,
          Byte.class,
          Short.class,
          Character.class,
          Integer.class,
          Long.class,
          Float.class,
          Double.class,
          String.class);

  /** Annotation checker to check for missing classes in the annotation body. */
  private class DepsCheckerAnnotationVisitor extends AnnotationVisitor {

    DepsCheckerAnnotationVisitor() {
      super(Opcodes.ASM6);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String name, String desc) {
      checkDescriptor(desc);
      return this; // Recursively reuse this annotation visitor.
    }

    @Override
    public void visit(String name, Object value) {
      if (value instanceof Type) {
        checkType(((Type) value)); // Class literals.
        return;
      }
      Class<?> clazz = value.getClass();
      if (PRIMITIVE_TYPES.contains(clazz)) {
        return;
      }
      checkState(
          clazz.isArray() && clazz.getComponentType().isPrimitive(),
          "Unexpected value %s of type %s",
          value,
          clazz);
    }

    @Override
    public AnnotationVisitor visitArray(String name) {
      return this; // Recursively reuse this annotation visitor.
    }

    @Override
    public void visitEnum(String name, String desc, String value) {
      checkMember(Type.getType(desc).getInternalName(), value, desc);
    }
  }

  /** Field checker to check for missing classes in the field declaration. */
  private class DepsCheckerFieldVisitor extends FieldVisitor {

    DepsCheckerFieldVisitor() {
      super(Opcodes.ASM6);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      checkDescriptor(desc);
      return defaultAnnotationChecker;
    }

    @Override
    public AnnotationVisitor visitTypeAnnotation(
        int typeRef, TypePath typePath, String desc, boolean visible) {
      checkDescriptor(desc);
      return defaultAnnotationChecker;
    }
  }

  /** Method visitor to check whether there are missing classes in the method body. */
  private class DepsCheckerMethodVisitor extends MethodVisitor {

    DepsCheckerMethodVisitor() {
      super(Opcodes.ASM6);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      checkDescriptor(desc);
      return defaultAnnotationChecker;
    }

    @Override
    public AnnotationVisitor visitTypeAnnotation(
        int typeRef, TypePath typePath, String desc, boolean visible) {
      checkDescriptor(desc);
      return defaultAnnotationChecker;
    }

    @Override
    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
      if ("Ljava/lang/Synthetic;".equals(desc)) {
        return null; // ASM sometimes makes up this annotation, so we can ignore it (b/78024300)
      }
      checkDescriptor(desc);
      return defaultAnnotationChecker;
    }

    @Override
    public void visitLocalVariable(
        String name, String desc, String signature, Label start, Label end, int index) {
      checkDescriptor(desc);
      super.visitLocalVariable(name, desc, signature, start, end, index);
    }

    @Override
    public void visitTypeInsn(int opcode, String type) {
      checkInternalNameOrArrayDescriptor(type);
      super.visitTypeInsn(opcode, type);
    }

    @Override
    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
      checkMember(owner, name, desc);
      super.visitFieldInsn(opcode, owner, name, desc);
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
      checkMember(owner, name, desc);
      super.visitMethodInsn(opcode, owner, name, desc, itf);
    }

    @Override
    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
      checkDescriptor(desc);
      checkHandle(bsm);
      for (Object bsmArg : bsmArgs) {
        if (bsmArg instanceof Type) {
          checkType(((Type) bsmArg)); // Class literals.
          continue;
        }
        if (PRIMITIVE_TYPES.contains(bsmArg.getClass())) {
          checkType(Type.getType(bsmArg.getClass()));
          continue;
        }
        if (bsmArg instanceof Handle) {
          checkHandle((Handle) bsmArg);
          continue;
        }
        throw new UnsupportedOperationException("Unsupported bsmarg type: " + bsmArg);
      }
      super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
    }

    private void checkHandle(Handle handle) {
      checkMember(handle.getOwner(), handle.getName(), handle.getDesc());
    }

    @Override
    public void visitMultiANewArrayInsn(String desc, int dims) {
      checkDescriptor(desc);
      super.visitMultiANewArrayInsn(desc, dims);
    }

    @Override
    public AnnotationVisitor visitTryCatchAnnotation(
        int typeRef, TypePath typePath, String desc, boolean visible) {
      checkDescriptor(desc);
      return defaultAnnotationChecker;
    }

    @Override
    public AnnotationVisitor visitLocalVariableAnnotation(
        int typeRef,
        TypePath typePath,
        Label[] start,
        Label[] end,
        int[] index,
        String desc,
        boolean visible) {
      checkDescriptor(desc);
      return defaultAnnotationChecker;
    }
  }
}
