// Copyright (c) 2019, 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/ast/token.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';

/// Verifier for [CollectionElement]s in list, set, or map literals.
class LiteralElementVerifier {
  final TypeProvider typeProvider;
  final TypeSystem typeSystem;
  final ErrorReporter errorReporter;
  final FeatureSet featureSet;
  final bool Function(Expression) checkForUseOfVoidResult;

  final bool forList;
  final bool forSet;
  final DartType elementType;

  final bool forMap;
  final DartType mapKeyType;
  final DartType mapValueType;

  LiteralElementVerifier(
    this.typeProvider,
    this.typeSystem,
    this.errorReporter,
    this.checkForUseOfVoidResult, {
    this.forList = false,
    this.forSet = false,
    this.elementType,
    this.forMap = false,
    this.mapKeyType,
    this.mapValueType,
    this.featureSet,
  });

  void verify(CollectionElement element) {
    _verifyElement(element);
  }

  /// Check that the given [type] is assignable to the [elementType], otherwise
  /// report the list or set error on the [errorNode].
  void _checkAssignableToElementType(DartType type, AstNode errorNode) {
    if (!typeSystem.isAssignableTo(type, elementType, featureSet: featureSet)) {
      var errorCode = forList
          ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
          : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
      errorReporter.reportTypeErrorForNode(
        errorCode,
        errorNode,
        [type, elementType],
      );
    }
  }

  /// Verify that the given [element] can be assigned to the [elementType] of
  /// the enclosing list, set, of map literal.
  void _verifyElement(CollectionElement element) {
    if (element is Expression) {
      if (forList || forSet) {
        if (!elementType.isVoid && checkForUseOfVoidResult(element)) {
          return;
        }
        _checkAssignableToElementType(element.staticType, element);
      } else {
        errorReporter.reportErrorForNode(
            CompileTimeErrorCode.EXPRESSION_IN_MAP, element);
      }
    } else if (element is ForElement) {
      _verifyElement(element.body);
    } else if (element is IfElement) {
      _verifyElement(element.thenElement);
      _verifyElement(element.elseElement);
    } else if (element is MapLiteralEntry) {
      if (forMap) {
        _verifyMapLiteralEntry(element);
      } else {
        errorReporter.reportErrorForNode(
            CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, element);
      }
    } else if (element is SpreadElement) {
      var isNullAware = element.spreadOperator.type ==
          TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
      Expression expression = element.expression;
      if (forList || forSet) {
        _verifySpreadForListOrSet(isNullAware, expression);
      } else if (forMap) {
        _verifySpreadForMap(isNullAware, expression);
      }
    }
  }

  /// Verify that the [entry]'s key and value are assignable to [mapKeyType]
  /// and [mapValueType].
  void _verifyMapLiteralEntry(MapLiteralEntry entry) {
    if (!mapKeyType.isVoid && checkForUseOfVoidResult(entry.key)) {
      return;
    }

    if (!mapValueType.isVoid && checkForUseOfVoidResult(entry.value)) {
      return;
    }

    var keyType = entry.key.staticType;
    if (!typeSystem.isAssignableTo(keyType, mapKeyType,
        featureSet: featureSet)) {
      errorReporter.reportTypeErrorForNode(
        StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
        entry.key,
        [keyType, mapKeyType],
      );
    }

    var valueType = entry.value.staticType;
    if (!typeSystem.isAssignableTo(valueType, mapValueType,
        featureSet: featureSet)) {
      errorReporter.reportTypeErrorForNode(
        StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
        entry.value,
        [valueType, mapValueType],
      );
    }
  }

  /// Verify that the type of the elements of the given [expression] can be
  /// assigned to the [elementType] of the enclosing collection.
  void _verifySpreadForListOrSet(bool isNullAware, Expression expression) {
    var expressionType = expression.staticType;
    if (expressionType.isDynamic) return;

    if (expressionType.isDartCoreNull) {
      if (!isNullAware) {
        errorReporter.reportErrorForNode(
          CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD,
          expression,
        );
      }
      return;
    }

    InterfaceType iterableType;
    var iterableDynamicType = (typeProvider.iterableDynamicType as TypeImpl)
        .withNullability(NullabilitySuffix.question);
    if (expressionType is InterfaceTypeImpl &&
        typeSystem.isSubtypeOf(expressionType, iterableDynamicType)) {
      iterableType = expressionType.asInstanceOf(
        iterableDynamicType.element,
      );
    }

    if (iterableType == null) {
      return errorReporter.reportErrorForNode(
        CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
        expression,
      );
    }

    var iterableElementType = iterableType.typeArguments[0];
    if (!typeSystem.isAssignableTo(iterableElementType, elementType,
        featureSet: featureSet)) {
      var errorCode = forList
          ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
          : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
      errorReporter.reportTypeErrorForNode(
        errorCode,
        expression,
        [iterableElementType, elementType],
      );
    }
  }

  /// Verify that the [expression] is a subtype of `Map<Object, Object>`, and
  /// its key and values are assignable to [mapKeyType] and [mapValueType].
  void _verifySpreadForMap(bool isNullAware, Expression expression) {
    var expressionType = expression.staticType;
    if (expressionType.isDynamic) return;

    if (expressionType.isDartCoreNull) {
      if (!isNullAware) {
        errorReporter.reportErrorForNode(
          CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD,
          expression,
        );
      }
      return;
    }

    InterfaceType mapType;
    var mapObjectObjectType = typeProvider.mapObjectObjectType;
    if (expressionType is InterfaceTypeImpl &&
        typeSystem.isSubtypeOf(expressionType, mapObjectObjectType)) {
      mapType = expressionType.asInstanceOf(mapObjectObjectType.element);
    }

    if (mapType == null) {
      return errorReporter.reportErrorForNode(
        CompileTimeErrorCode.NOT_MAP_SPREAD,
        expression,
      );
    }

    var keyType = mapType.typeArguments[0];
    if (!typeSystem.isAssignableTo(keyType, mapKeyType,
        featureSet: featureSet)) {
      errorReporter.reportTypeErrorForNode(
        StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
        expression,
        [keyType, mapKeyType],
      );
    }

    var valueType = mapType.typeArguments[1];
    if (!typeSystem.isAssignableTo(valueType, mapValueType,
        featureSet: featureSet)) {
      errorReporter.reportTypeErrorForNode(
        StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
        expression,
        [valueType, mapValueType],
      );
    }
  }
}
