// Copyright (c) 2020, 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.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult.INVALID_APPLICATION_COUNT;
import static com.android.tools.r8.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult.INVALID_INTERFACE_COUNT;
import static com.android.tools.r8.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult.INVALID_SUPER_TYPE;
import static com.android.tools.r8.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult.INVALID_TYPE_VARIABLE_UNDEFINED;
import static com.android.tools.r8.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult.VALID;
import static com.google.common.base.Predicates.alwaysFalse;

import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
import com.android.tools.r8.graph.GenericSignature.DexDefinitionSignature;
import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
import com.android.tools.r8.graph.GenericSignature.FormalTypeParameter;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.GenericSignature.ReturnType;
import com.android.tools.r8.graph.GenericSignature.TypeSignature;
import com.android.tools.r8.graph.GenericSignatureContextBuilder.TypeParameterContext;
import com.android.tools.r8.shaking.KeepClassInfo;
import com.android.tools.r8.shaking.KeepFieldInfo;
import com.android.tools.r8.shaking.KeepMethodInfo;
import com.android.tools.r8.utils.ListUtils;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class GenericSignatureCorrectnessHelper {

  private enum Mode {
    VERIFY,
    CLEAR_IF_INVALID;

    public boolean doNotVerify() {
      return clearIfInvalid();
    }

    public boolean clearIfInvalid() {
      return this == CLEAR_IF_INVALID;
    }
  }

  public enum SignatureEvaluationResult {
    INVALID_SUPER_TYPE,
    INVALID_INTERFACE_TYPE,
    INVALID_INTERFACE_COUNT,
    INVALID_APPLICATION_COUNT,
    INVALID_TYPE_VARIABLE_UNDEFINED,
    VALID;

    public boolean isValid() {
      return this == VALID;
    }

    public boolean isInvalid() {
      return this != VALID;
    }

    public SignatureEvaluationResult combine(SignatureEvaluationResult other) {
      return isInvalid() ? this : other;
    }

    public String getDescription() {
      switch (this) {
        case INVALID_APPLICATION_COUNT:
          return "The applied generic arguments have different count than the expected formals";
        case INVALID_INTERFACE_COUNT:
          return "The generic signature has a different number of interfaces than the class";
        case INVALID_SUPER_TYPE:
          return "The generic super type is not the same as the class super type";
        case INVALID_TYPE_VARIABLE_UNDEFINED:
          return "A type variable is not in scope";
        default:
          assert this.isValid();
          throw new Unreachable("Should not throw an error for a valid signature");
      }
    }
  }

  private final AppView<?> appView;
  private final Mode mode;
  private final GenericSignatureContextBuilder contextBuilder;

  private GenericSignatureCorrectnessHelper(
      AppView<?> appView, GenericSignatureContextBuilder contextBuilder, Mode mode) {
    this.appView = appView;
    this.contextBuilder = contextBuilder;
    this.mode = mode;
  }

  public static GenericSignatureCorrectnessHelper createForInitialCheck(
      AppView<?> appView, GenericSignatureContextBuilder contextBuilder) {
    return new GenericSignatureCorrectnessHelper(appView, contextBuilder, Mode.CLEAR_IF_INVALID);
  }

  public static GenericSignatureCorrectnessHelper createForVerification(
      AppView<?> appView, GenericSignatureContextBuilder contextBuilder) {
    return new GenericSignatureCorrectnessHelper(appView, contextBuilder, Mode.VERIFY);
  }

  public SignatureEvaluationResult run(List<DexProgramClass> programClasses) {
    if (appView.options().disableGenericSignatureValidation
        || !appView.options().parseSignatureAttribute()) {
      return VALID;
    }
    SignatureEvaluationResult evaluationResult = VALID;
    for (DexProgramClass clazz : programClasses) {
      evaluationResult = evaluationResult.combine(evaluateSignaturesForClass(clazz));
    }
    return evaluationResult;
  }

  public SignatureEvaluationResult evaluateSignaturesForClass(DexProgramClass clazz) {
    if (appView.options().disableGenericSignatureValidation
        || !appView.options().parseSignatureAttribute()) {
      return VALID;
    }

    TypeParameterContext typeParameterContext =
        contextBuilder.computeTypeParameterContext(appView, clazz.type, alwaysFalse());

    GenericSignatureContextEvaluator genericSignatureContextEvaluator =
        new GenericSignatureContextEvaluator(appView, mode, clazz);

    SignatureEvaluationResult result =
        genericSignatureContextEvaluator.evaluateClassSignatureForContext(typeParameterContext);
    if (result.isInvalid() && mode.clearIfInvalid()) {
      // Only report info messages for classes that are kept explicitly. This is to ensure we do not
      // spam the developer with messages they can do nothing about.
      KeepClassInfo classInfo = appView.getKeepInfo().getClassInfo(clazz);
      if (appView.hasLiveness() && !classInfo.isShrinkingAllowed(appView.options())) {
        // If/when this no longer holds it should be moved into the condition.
        assert !classInfo.isSignatureAttributeRemovalAllowed(appView.options());
        appView
            .options()
            .reporter
            .info(
                GenericSignatureValidationDiagnostic.invalidClassSignature(
                    clazz.getClassSignature().toString(),
                    clazz.getTypeName(),
                    clazz.getOrigin(),
                    result));
      }
      clazz.clearClassSignature();
    }
    for (DexEncodedMethod method : clazz.methods()) {
      result =
          result.combine(
              evaluate(
                  method::getGenericSignature,
                  methodSignature ->
                      genericSignatureContextEvaluator.visitMethodSignature(
                          methodSignature, typeParameterContext),
                  invalidResult -> {
                    // Only report info messages for methods that are kept explicitly. This is to
                    // ensure we do not spam the developer with messages they can do nothing about.
                    KeepMethodInfo methodInfo = appView.getKeepInfo().getMethodInfo(method, clazz);
                    if (appView.hasLiveness()
                        && !methodInfo.isShrinkingAllowed(appView.options())) {
                      // If/when this no longer holds it should be moved into the condition.
                      assert !methodInfo.isSignatureAttributeRemovalAllowed(appView.options());
                      appView
                          .options()
                          .reporter
                          .info(
                              GenericSignatureValidationDiagnostic.invalidMethodSignature(
                                  method.getGenericSignature().toString(),
                                  method.toSourceString(),
                                  clazz.getOrigin(),
                                  invalidResult));
                    }
                    method.clearGenericSignature();
                  }));
    }
    for (DexEncodedField field : clazz.fields()) {
      result =
          result.combine(
              evaluate(
                  field::getGenericSignature,
                  fieldSignature ->
                      genericSignatureContextEvaluator.visitFieldTypeSignature(
                          fieldSignature, typeParameterContext),
                  invalidResult -> {
                    KeepFieldInfo fieldInfo = appView.getKeepInfo().getFieldInfo(field, clazz);
                    // Only report info messages for fields that are kept explicitly. This is to
                    // ensure we do not spam the developer with messages they can do nothing about.
                    if (appView.hasLiveness() && !fieldInfo.isShrinkingAllowed(appView.options())) {
                      // If/when this no longer holds it should be moved into the condition.
                      assert !fieldInfo.isSignatureAttributeRemovalAllowed(appView.options());
                      appView
                          .options()
                          .reporter
                          .info(
                              GenericSignatureValidationDiagnostic.invalidFieldSignature(
                                  field.getGenericSignature().toString(),
                                  field.toSourceString(),
                                  clazz.getOrigin(),
                                  invalidResult));
                    }
                    field.clearGenericSignature();
                  }));
    }
    return result;
  }

  @SuppressWarnings("unchecked")
  private <T extends DexDefinitionSignature<?>> SignatureEvaluationResult evaluate(
      Supplier<T> getter,
      Function<T, SignatureEvaluationResult> evaluate,
      Consumer<SignatureEvaluationResult> invalidAction) {
    T signature = getter.get();
    if (signature.hasNoSignature() || signature.isInvalid()) {
      // Already marked as invalid, do nothing
      return VALID;
    }
    SignatureEvaluationResult signatureResult = evaluate.apply(signature);
    assert signatureResult.isValid() || mode.doNotVerify();
    if (signatureResult.isInvalid() && mode.clearIfInvalid()) {
      invalidAction.accept(signatureResult);
    }
    return signatureResult;
  }

  private static class GenericSignatureContextEvaluator {

    private final AppView<?> appView;
    private final DexProgramClass context;
    private final Mode mode;

    private GenericSignatureContextEvaluator(
        AppView<?> appView, Mode mode, DexProgramClass context) {
      this.appView = appView;
      this.mode = mode;
      this.context = context;
    }

    private SignatureEvaluationResult evaluateClassSignatureForContext(
        TypeParameterContext typeParameterContext) {
      ClassSignature classSignature = context.classSignature;
      if (classSignature.hasNoSignature() || classSignature.isInvalid()) {
        return VALID;
      }
      SignatureEvaluationResult signatureEvaluationResult =
          evaluateFormalTypeParameters(classSignature.formalTypeParameters, typeParameterContext);
      if (signatureEvaluationResult.isInvalid()) {
        return signatureEvaluationResult;
      }
      if (context.superType == appView.dexItemFactory().objectType
          && classSignature.superClassSignature().hasNoSignature()) {
        // We represent no signature as object.
      } else if (context.superType != classSignature.superClassSignature().type()) {
        assert mode.doNotVerify() : "Super type inconsistency in generic signature";
        return INVALID_SUPER_TYPE;
      }
      signatureEvaluationResult =
          evaluateTypeArgumentsAppliedToType(
              classSignature.superClassSignature().typeArguments(),
              context.superType,
              typeParameterContext);
      if (signatureEvaluationResult.isInvalid()) {
        return signatureEvaluationResult;
      }
      List<ClassTypeSignature> superInterfaces = classSignature.superInterfaceSignatures();
      if (context.interfaces.size() != superInterfaces.size()) {
        assert mode.doNotVerify();
        return INVALID_INTERFACE_COUNT;
      }
      DexType[] actualInterfaces = context.interfaces.values;
      for (int i = 0; i < actualInterfaces.length; i++) {
        signatureEvaluationResult =
            evaluateTypeArgumentsAppliedToType(
                superInterfaces.get(i).typeArguments(), actualInterfaces[i], typeParameterContext);
        if (signatureEvaluationResult.isInvalid()) {
          return signatureEvaluationResult;
        }
      }
      return VALID;
    }

    private SignatureEvaluationResult visitMethodSignature(
        MethodTypeSignature methodSignature, TypeParameterContext typeParameterContext) {
      // If the class context is invalid, we cannot reason about the method signatures.
      if (context.classSignature.isInvalid()) {
        return VALID;
      }
      TypeParameterContext methodContext =
          methodSignature.formalTypeParameters.isEmpty()
              ? typeParameterContext
              : typeParameterContext.addLiveParameters(
                  ListUtils.map(
                      methodSignature.getFormalTypeParameters(), FormalTypeParameter::getName));
      SignatureEvaluationResult evaluateResult =
          evaluateFormalTypeParameters(methodSignature.getFormalTypeParameters(), methodContext);
      if (evaluateResult.isInvalid()) {
        return evaluateResult;
      }
      evaluateResult = evaluateTypeArguments(methodSignature.typeSignatures, methodContext);
      if (evaluateResult.isInvalid()) {
        return evaluateResult;
      }
      evaluateResult = evaluateTypeArguments(methodSignature.throwsSignatures, methodContext);
      if (evaluateResult.isInvalid()) {
        return evaluateResult;
      }
      ReturnType returnType = methodSignature.returnType();
      if (!returnType.isVoidDescriptor()) {
        evaluateResult = evaluateTypeArgument(returnType.typeSignature(), methodContext);
        if (evaluateResult.isInvalid()) {
          return evaluateResult;
        }
      }
      return evaluateResult;
    }

    private SignatureEvaluationResult evaluateTypeArguments(
        List<TypeSignature> typeSignatures, TypeParameterContext typeParameterContext) {
      for (TypeSignature typeSignature : typeSignatures) {
        SignatureEvaluationResult signatureEvaluationResult =
            evaluateTypeArgument(typeSignature, typeParameterContext);
        if (signatureEvaluationResult.isInvalid()) {
          return signatureEvaluationResult;
        }
      }
      return VALID;
    }

    private SignatureEvaluationResult visitFieldTypeSignature(
        FieldTypeSignature fieldSignature, TypeParameterContext typeParameterContext) {
      // If the class context is invalid, we cannot reason about the method signatures.
      if (context.classSignature.isInvalid()) {
        return VALID;
      }
      return evaluateTypeArgument(fieldSignature, typeParameterContext);
    }

    private SignatureEvaluationResult evaluateFormalTypeParameters(
        List<FormalTypeParameter> typeParameters, TypeParameterContext typeParameterContext) {
      for (FormalTypeParameter typeParameter : typeParameters) {
        SignatureEvaluationResult evaluationResult =
            evaluateTypeParameter(typeParameter, typeParameterContext);
        if (evaluationResult.isInvalid()) {
          return evaluationResult;
        }
      }
      return VALID;
    }

    private SignatureEvaluationResult evaluateTypeParameter(
        FormalTypeParameter typeParameter, TypeParameterContext typeParameterContext) {
      SignatureEvaluationResult evaluationResult =
          evaluateTypeArgument(typeParameter.classBound, typeParameterContext);
      if (evaluationResult.isInvalid()) {
        return evaluationResult;
      }
      for (FieldTypeSignature interfaceBound : typeParameter.interfaceBounds) {
        evaluationResult = evaluateTypeArgument(interfaceBound, typeParameterContext);
        if (evaluationResult != VALID) {
          return evaluationResult;
        }
      }
      return VALID;
    }

    private SignatureEvaluationResult evaluateTypeArgument(
        TypeSignature typeSignature, TypeParameterContext typeParameterContext) {
      if (typeSignature.isBaseTypeSignature()) {
        return VALID;
      }
      FieldTypeSignature fieldTypeSignature = typeSignature.asFieldTypeSignature();
      if (fieldTypeSignature.hasNoSignature() || fieldTypeSignature.isStar()) {
        return VALID;
      }
      if (fieldTypeSignature.isTypeVariableSignature()) {
        // This is in an applied position, just check that the variable is registered.
        String typeVariable = fieldTypeSignature.asTypeVariableSignature().typeVariable();
        if (typeParameterContext.isLiveParameter(typeVariable)) {
          return VALID;
        }
        assert mode.doNotVerify();
        return INVALID_TYPE_VARIABLE_UNDEFINED;
      }
      if (fieldTypeSignature.isArrayTypeSignature()) {
        return evaluateTypeArgument(
            fieldTypeSignature.asArrayTypeSignature().elementSignature(), typeParameterContext);
      }
      assert fieldTypeSignature.isClassTypeSignature();
      return evaluateTypeArguments(fieldTypeSignature.asClassTypeSignature(), typeParameterContext);
    }

    private SignatureEvaluationResult evaluateTypeArguments(
        ClassTypeSignature classTypeSignature, TypeParameterContext typeParameterContext) {
      return evaluateTypeArgumentsAppliedToType(
          classTypeSignature.typeArguments, classTypeSignature.type(), typeParameterContext);
    }

    private SignatureEvaluationResult evaluateTypeArgumentsAppliedToType(
        List<FieldTypeSignature> typeArguments,
        DexType type,
        TypeParameterContext typeParameterContext) {
      for (FieldTypeSignature typeArgument : typeArguments) {
        SignatureEvaluationResult evaluationResult =
            evaluateTypeArgument(typeArgument, typeParameterContext);
        if (evaluationResult.isInvalid()) {
          assert mode.doNotVerify();
          return evaluationResult;
        }
      }
      // TODO(b/187035453): We should visit generic signatures in the enqueuer.
      DexClass clazz = appView.appInfo().definitionForWithoutExistenceAssert(type);
      if (clazz == null) {
        // We do not know if the application of arguments works or not.
        return VALID;
      }
      if (typeArguments.isEmpty()) {
        // When type arguments are empty we are using the raw type.
        return VALID;
      }
      if (typeArguments.size() != clazz.classSignature.getFormalTypeParameters().size()) {
        assert mode.doNotVerify();
        return INVALID_APPLICATION_COUNT;
      }
      return VALID;
    }
  }
}
