// Copyright (c) 2020, the Dart 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.

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/migration.dart';
import 'package:analyzer/src/generated/resolver.dart';

/// Information about a constructor element to instantiate.
///
/// If the target is a [ClassElement], the [element] is a raw
/// [ConstructorElement] from the class, and [typeParameters] are the
/// type parameters of the class.
///
/// If the target is a [TypeAliasElement] with an [InterfaceType] as the
/// aliased type, the [element] is a [ConstructorMember] created from the
/// [ConstructorElement] of the corresponding class, and substituting
/// the class type parameters with the type arguments specified in the alias,
/// explicit types or the type parameters of the alias. The [typeParameters]
/// are the type parameters of the alias.
class ConstructorElementToInfer {
  /// The type parameters used in [element].
  final List<TypeParameterElement> typeParameters;

  /// The element, might be [ConstructorMember].
  final ConstructorElement element;

  ConstructorElementToInfer(this.typeParameters, this.element);

  /// Return the equivalent generic function type that we could use to
  /// forward to the constructor, or for a non-generic type simply returns
  /// the constructor type.
  ///
  /// For example given the type `class C<T> { C(T arg); }`, the generic
  /// function type is `<T>(T) -> C<T>`.
  FunctionType get asType {
    return FunctionTypeImpl(
      typeFormals: typeParameters,
      parameters: element.parameters,
      returnType: element.returnType,
      nullabilitySuffix: NullabilitySuffix.none,
    );
  }
}

class InvocationInferenceHelper {
  final ResolverVisitor _resolver;
  final ErrorReporter _errorReporter;
  final TypeSystemImpl _typeSystem;
  final MigrationResolutionHooks? _migrationResolutionHooks;
  final bool _genericMetadataIsEnabled;

  List<DartType>? _typeArgumentTypes;
  FunctionType? _invokeType;

  InvocationInferenceHelper({
    required ResolverVisitor resolver,
    required ErrorReporter errorReporter,
    required TypeSystemImpl typeSystem,
    required MigrationResolutionHooks? migrationResolutionHooks,
  })  : _resolver = resolver,
        _errorReporter = errorReporter,
        _typeSystem = typeSystem,
        _migrationResolutionHooks = migrationResolutionHooks,
        _genericMetadataIsEnabled = resolver.definingLibrary.featureSet
            .isEnabled(Feature.generic_metadata);

  /// Compute the return type of the method or function represented by the given
  /// type that is being invoked.
  DartType computeInvokeReturnType(DartType? type) {
    if (type is FunctionType) {
      return type.returnType;
    } else {
      return DynamicTypeImpl.instance;
    }
  }

  /// If the constructor referenced by the [constructorName] is generic,
  /// and the [constructorName] does not have explicit type arguments,
  /// return the element and type parameters to infer. Otherwise return `null`.
  ConstructorElementToInfer? constructorElementToInfer({
    required ConstructorName constructorName,
    required LibraryElement definingLibrary,
  }) {
    List<TypeParameterElement>? typeParameters;
    ConstructorElement? rawElement;

    var typeName = constructorName.type;
    var typeArguments = typeName.typeArguments;
    var typeElement = typeName.name.staticElement;
    if (typeElement is ClassElement) {
      typeParameters = typeElement.typeParameters;
      if (typeParameters.isNotEmpty && typeArguments == null) {
        var constructorIdentifier = constructorName.name;
        if (constructorIdentifier == null) {
          rawElement = typeElement.unnamedConstructor;
        } else {
          var name = constructorIdentifier.name;
          rawElement = typeElement.getNamedConstructor(name);
          if (rawElement != null &&
              !rawElement.isAccessibleIn(definingLibrary)) {
            rawElement = null;
          }
        }
      }
    } else if (typeElement is TypeAliasElement) {
      typeParameters = typeElement.typeParameters;
      var aliasedType = typeElement.aliasedType;
      if (aliasedType is InterfaceType) {
        if (typeParameters.isNotEmpty && typeArguments == null) {
          var constructorIdentifier = constructorName.name;
          rawElement = aliasedType.lookUpConstructor(
            constructorIdentifier?.name,
            definingLibrary,
          );
        }
      }
    }

    if (typeParameters == null || rawElement == null) {
      return null;
    }
    rawElement = _resolver.toLegacyElement(rawElement);
    return ConstructorElementToInfer(typeParameters, rawElement);
  }

  FunctionType? inferArgumentTypesForGeneric(AstNode inferenceNode,
      DartType? uninstantiatedType, TypeArgumentList? typeArguments,
      {AstNode? errorNode,
      bool isConst = false,
      required DartType? contextReturnType}) {
    errorNode ??= inferenceNode;
    uninstantiatedType = _getFreshType(uninstantiatedType);
    if (typeArguments == null &&
        uninstantiatedType is FunctionType &&
        uninstantiatedType.typeFormals.isNotEmpty) {
      var typeArguments = _typeSystem.inferGenericFunctionOrType(
        typeParameters: uninstantiatedType.typeFormals,
        parameters: const <ParameterElement>[],
        declaredReturnType: uninstantiatedType.returnType,
        argumentTypes: const <DartType>[],
        contextReturnType: contextReturnType,
        downwards: true,
        isConst: isConst,
        errorReporter: _errorReporter,
        errorNode: errorNode,
        genericMetadataIsEnabled: _genericMetadataIsEnabled,
      );
      if (typeArguments != null) {
        return uninstantiatedType.instantiate(typeArguments);
      }
    }
    return null;
  }

  DartType? inferArgumentTypesForInvocation(
      InvocationExpression node, DartType? type,
      {required DartType? contextType}) {
    return inferArgumentTypesForGeneric(node, type, node.typeArguments,
            contextReturnType: contextType) ??
        node.staticInvokeType;
  }

  /// Given a possibly generic invocation like `o.m(args)` or `(f)(args)` try to
  /// infer the instantiated generic function type.
  ///
  /// This takes into account both the context type, as well as information from
  /// the argument types.
  void inferGenericInvocationExpression(
      InvocationExpressionImpl node, DartType? type,
      {required DartType? contextType}) {
    var arguments = node.argumentList;
    var freshType = _getFreshType(type);

    var inferred = inferGenericInvoke(
        node, freshType, node.typeArguments, arguments, node.function,
        contextReturnType: contextType);
    if (inferred != null && inferred != node.staticInvokeType) {
      // Fix up the parameter elements based on inferred method.
      arguments.correspondingStaticParameters =
          ResolverVisitor.resolveArgumentsToParameters(
        argumentList: arguments,
        parameters: inferred.parameters,
      );
      node.staticInvokeType = inferred;
    }
  }

  /// Given a possibly generic invocation or instance creation, such as
  /// `o.m(args)` or `(f)(args)` or `new T(args)` try to infer the instantiated
  /// generic function type.
  ///
  /// This takes into account both the context type, as well as information from
  /// the argument types.
  FunctionType? inferGenericInvoke(
      AstNode node,
      DartType? fnType,
      TypeArgumentList? typeArguments,
      ArgumentList argumentList,
      AstNode errorNode,
      {bool isConst = false,
      required DartType? contextReturnType}) {
    if (typeArguments == null &&
        fnType is FunctionType &&
        fnType.typeFormals.isNotEmpty) {
      // Get the parameters that correspond to the uninstantiated generic.
      var typeArgs = _inferUpwards(
        rawType: fnType,
        argumentList: argumentList,
        contextType: contextReturnType,
        isConst: isConst,
        errorNode: errorNode,
      );
      if (node is InvocationExpressionImpl) {
        node.typeArgumentTypes = typeArgs;
      }
      if (typeArgs != null) {
        return fnType.instantiate(typeArgs);
      }
      return fnType;
    }

    // There is currently no other place where we set type arguments
    // for FunctionExpressionInvocation(s), so set it here, if not inferred.
    if (node is FunctionExpressionInvocationImpl) {
      if (typeArguments != null) {
        var typeArgs =
            typeArguments.arguments.map((n) => n.typeOrThrow).toList();
        node.typeArgumentTypes = typeArgs;
      } else {
        node.typeArgumentTypes = const <DartType>[];
      }
    }

    return null;
  }

  /// Given an uninstantiated generic function type, referenced by the
  /// [identifier] in the tear-off [expression], try to infer the instantiated
  /// generic function type from the surrounding context.
  DartType inferTearOff(Expression expression, SimpleIdentifierImpl identifier,
      DartType tearOffType,
      {required DartType? contextType}) {
    if (contextType is FunctionType && tearOffType is FunctionType) {
      var typeArguments = _typeSystem.inferFunctionTypeInstantiation(
        contextType,
        tearOffType,
        errorReporter: _errorReporter,
        errorNode: expression,
        genericMetadataIsEnabled: _genericMetadataIsEnabled,
      )!;
      identifier.tearOffTypeArgumentTypes = typeArguments;
      if (typeArguments.isNotEmpty) {
        return tearOffType.instantiate(typeArguments);
      }
    }
    return tearOffType;
  }

  /// Record that the static type of the given node is the given type.
  ///
  /// @param expression the node whose type is to be recorded
  /// @param type the static type of the node
  void recordStaticType(ExpressionImpl expression, DartType type,
      {required DartType? contextType}) {
    var hooks = _migrationResolutionHooks;
    if (hooks != null) {
      type = hooks.modifyExpressionType(expression, type, contextType);
    }

    expression.staticType = type;
    if (_typeSystem.isBottom(type)) {
      _resolver.flowAnalysis.flow?.handleExit();
    }
  }

  /// Finish resolution of the [FunctionExpressionInvocation].
  ///
  /// We have already found the invoked [ExecutableElement], and the [rawType]
  /// is its not yet instantiated type. Here we perform downwards inference,
  /// resolution of arguments, and upwards inference.
  void resolveFunctionExpressionInvocation({
    required FunctionExpressionInvocationImpl node,
    required FunctionType rawType,
    required List<WhyNotPromotedGetter> whyNotPromotedList,
    required DartType? contextType,
  }) {
    _resolveInvocation(
      rawType: rawType,
      typeArgumentList: node.typeArguments,
      argumentList: node.argumentList,
      contextType: contextType,
      isConst: false,
      errorNode: node.function,
      whyNotPromotedList: whyNotPromotedList,
    );

    node.typeArgumentTypes = _typeArgumentTypes;
    node.staticInvokeType = _invokeType;
  }

  /// Finish resolution of the [MethodInvocation].
  ///
  /// We have already found the invoked [ExecutableElement], and the [rawType]
  /// is its not yet instantiated type. Here we perform downwards inference,
  /// resolution of arguments, and upwards inference.
  void resolveMethodInvocation({
    required MethodInvocationImpl node,
    required FunctionType rawType,
    required List<WhyNotPromotedGetter> whyNotPromotedList,
    required DartType? contextType,
  }) {
    _resolveInvocation(
      rawType: rawType,
      typeArgumentList: node.typeArguments,
      argumentList: node.argumentList,
      contextType: contextType,
      isConst: false,
      errorNode: node.function,
      whyNotPromotedList: whyNotPromotedList,
    );

    node.typeArgumentTypes = _typeArgumentTypes;
    node.staticInvokeType = _invokeType;

    var returnType = computeInvokeReturnType(_invokeType);
    var targetType = node.realTarget?.staticType;
    if (targetType != null) {
      returnType = _typeSystem.refineNumericInvocationType(
        targetType,
        node.methodName.staticElement,
        [
          for (var argument in node.argumentList.arguments) argument.typeOrThrow
        ],
        returnType,
      );
    }
    recordStaticType(node, returnType, contextType: contextType);
  }

  List<DartType>? _inferDownwards({
    required FunctionType rawType,
    required DartType? contextType,
    required bool isConst,
    required AstNode errorNode,
  }) {
    return _typeSystem.inferGenericFunctionOrType(
      typeParameters: rawType.typeFormals,
      parameters: const <ParameterElement>[],
      declaredReturnType: rawType.returnType,
      argumentTypes: const <DartType>[],
      contextReturnType: contextType,
      downwards: true,
      isConst: isConst,
      errorReporter: _errorReporter,
      errorNode: errorNode,
      genericMetadataIsEnabled: _genericMetadataIsEnabled,
    );
  }

  /// TODO(scheglov) Instead of [isConst] sanitize [contextType] before calling.
  List<DartType>? _inferUpwards({
    required FunctionType rawType,
    required DartType? contextType,
    required ArgumentList argumentList,
    required bool isConst,
    required AstNode errorNode,
  }) {
    rawType = _getFreshType(rawType) as FunctionType;

    // Get the parameters that correspond to the uninstantiated generic.
    List<ParameterElement?> rawParameters =
        ResolverVisitor.resolveArgumentsToParameters(
      argumentList: argumentList,
      parameters: rawType.parameters,
    );

    List<ParameterElement> params = <ParameterElement>[];
    List<DartType> argTypes = <DartType>[];
    for (int i = 0, length = rawParameters.length; i < length; i++) {
      ParameterElement? parameter = rawParameters[i];
      if (parameter != null) {
        params.add(parameter);
        argTypes.add(argumentList.arguments[i].typeOrThrow);
      }
    }
    var typeArgs = _typeSystem.inferGenericFunctionOrType(
      typeParameters: rawType.typeFormals,
      parameters: params,
      declaredReturnType: rawType.returnType,
      argumentTypes: argTypes,
      contextReturnType: contextType,
      isConst: isConst,
      errorReporter: _errorReporter,
      errorNode: errorNode,
      genericMetadataIsEnabled: _genericMetadataIsEnabled,
    );
    return typeArgs;
  }

  bool _isCallToIdentical(AstNode? invocation) {
    if (invocation is MethodInvocation) {
      var invokedMethod = invocation.methodName.staticElement;
      return invokedMethod != null &&
          invokedMethod.name == 'identical' &&
          invokedMethod.library!.isDartCore;
    }
    return false;
  }

  void _resolveArguments(
      ArgumentList argumentList,
      List<WhyNotPromotedGetter> whyNotPromotedList,
      List<ParameterElement> parameters,
      {required DartType? methodInvocationContext}) {
    _resolver.analyzeArgumentList(argumentList, parameters,
        isIdentical: _isCallToIdentical(argumentList.parent),
        whyNotPromotedList: whyNotPromotedList,
        methodInvocationContext: methodInvocationContext);
  }

  void _resolveInvocation({
    required FunctionType rawType,
    required DartType? contextType,
    required TypeArgumentList? typeArgumentList,
    required ArgumentListImpl argumentList,
    required bool isConst,
    required AstNode errorNode,
    required List<WhyNotPromotedGetter> whyNotPromotedList,
  }) {
    if (typeArgumentList != null) {
      _resolveInvocationWithTypeArguments(
        rawType: rawType,
        typeArgumentList: typeArgumentList,
        argumentList: argumentList,
        whyNotPromotedList: whyNotPromotedList,
        methodInvocationContext: contextType,
      );
    } else {
      _resolveInvocationWithoutTypeArguments(
        rawType: rawType,
        contextType: contextType,
        argumentList: argumentList,
        isConst: isConst,
        errorNode: errorNode,
        whyNotPromotedList: whyNotPromotedList,
      );
    }
    _setCorrespondingParameters(argumentList, _invokeType!);
  }

  void _resolveInvocationWithoutTypeArguments({
    required FunctionType rawType,
    required DartType? contextType,
    required ArgumentList argumentList,
    required bool isConst,
    required AstNode errorNode,
    required List<WhyNotPromotedGetter> whyNotPromotedList,
  }) {
    var typeParameters = rawType.typeFormals;

    if (typeParameters.isEmpty) {
      _resolveArguments(argumentList, whyNotPromotedList, rawType.parameters,
          methodInvocationContext: contextType);

      _typeArgumentTypes = const <DartType>[];
      _invokeType = rawType;
    } else {
      rawType = _getFreshType(rawType) as FunctionType;

      var downwardsTypeArguments = _inferDownwards(
        rawType: rawType,
        contextType: contextType,
        isConst: isConst,
        errorNode: errorNode,
      )!;

      var downwardsInvokeType = rawType.instantiate(downwardsTypeArguments);

      _resolveArguments(
          argumentList, whyNotPromotedList, downwardsInvokeType.parameters,
          methodInvocationContext: contextType);

      _typeArgumentTypes = _inferUpwards(
        rawType: rawType,
        argumentList: argumentList,
        contextType: contextType,
        isConst: isConst,
        errorNode: errorNode,
      );
      _invokeType = rawType.instantiate(_typeArgumentTypes!);
    }
  }

  void _resolveInvocationWithTypeArguments({
    required FunctionType rawType,
    required TypeArgumentList typeArgumentList,
    required ArgumentList argumentList,
    required List<WhyNotPromotedGetter> whyNotPromotedList,
    required DartType? methodInvocationContext,
  }) {
    var typeParameters = rawType.typeFormals;

    List<DartType> typeArguments;
    if (typeArgumentList.arguments.length != typeParameters.length) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
        typeArgumentList,
        [
          rawType,
          typeParameters.length,
          typeArgumentList.arguments.length,
        ],
      );
      typeArguments = List.filled(
        typeParameters.length,
        DynamicTypeImpl.instance,
      );
    } else {
      typeArguments = typeArgumentList.arguments
          .map((typeArgument) => typeArgument.typeOrThrow)
          .toList(growable: true);
    }

    var invokeType = rawType.instantiate(typeArguments);

    _resolveArguments(argumentList, whyNotPromotedList, invokeType.parameters,
        methodInvocationContext: methodInvocationContext);

    _typeArgumentTypes = typeArguments;
    _invokeType = invokeType;
  }

  void _setCorrespondingParameters(
    ArgumentListImpl argumentList,
    FunctionType invokeType,
  ) {
    var parameters = ResolverVisitor.resolveArgumentsToParameters(
      argumentList: argumentList,
      parameters: invokeType.parameters,
      errorReporter: _errorReporter,
    );
    argumentList.correspondingStaticParameters = parameters;
  }

  static DartType? _getFreshType(DartType? type) {
    if (type is FunctionType) {
      var parameters = getFreshTypeParameters(type.typeFormals);
      return parameters.applyToFunctionType(type);
    } else {
      return type;
    }
  }
}
