// 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.ASM7);
    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;
    if (superName != null) {
      // module-info and java.lang.Object have null superName
      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);

      if (!resultCollector.getCheckMissingMembers()) {
        return;  // No point in doing the expensive stuff below
      }

      // TODO(kmb): Consider removing this entirely so we don't have to track members at all
      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.ASM7);
    }

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

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

    @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 visitLdcInsn(Object value) {
      if (value instanceof Type) {
        checkType((Type) value); // Class literals
      } else if (value instanceof Handle) {
        checkHandle((Handle) value);
      } else {
        checkState(PRIMITIVE_TYPES.contains(value.getClass()));
      }
      super.visitLdcInsn(value);
    }

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