// 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/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/element/type.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/error/analyzer_error_code.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/error_verifier.dart';
import 'package:meta/meta.dart';

class ReturnTypeVerifier {
  final TypeProviderImpl _typeProvider;
  final TypeSystemImpl _typeSystem;
  final ErrorReporter _errorReporter;

  EnclosingExecutableContext enclosingExecutable;

  ReturnTypeVerifier({
    @required TypeProviderImpl typeProvider,
    @required TypeSystemImpl typeSystem,
    @required ErrorReporter errorReporter,
  })  : _typeProvider = typeProvider,
        _typeSystem = typeSystem,
        _errorReporter = errorReporter;

  DartType get _flattenedReturnType {
    var returnType = enclosingExecutable.returnType;
    if (enclosingExecutable.isSynchronous) {
      return returnType;
    } else {
      return _typeSystem.flatten(returnType);
    }
  }

  void verifyExpressionFunctionBody(ExpressionFunctionBody node) {
    // This enables concise declarations of void functions.
    if (_flattenedReturnType.isVoid) {
      return;
    }

    return _checkReturnExpression(node.expression);
  }

  void verifyReturnStatement(ReturnStatement statement) {
    var expression = statement.expression;

    if (enclosingExecutable.isGenerativeConstructor) {
      if (expression != null) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR,
          expression,
        );
      }
      return;
    }

    if (enclosingExecutable.isGenerator) {
      if (expression != null) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_IN_GENERATOR,
          statement,
          [enclosingExecutable.isAsynchronous ? 'async*' : 'sync*'],
        );
      }
      return;
    }

    if (expression == null) {
      _checkReturnWithoutValue(statement);
      return;
    }

    _checkReturnExpression(expression);
  }

  void verifyReturnType(TypeAnnotation returnType) {
    // If no declared type, then the type is `dynamic`, which is valid.
    if (returnType == null) {
      return;
    }

    void checkElement(
      ClassElement expectedElement,
      AnalyzerErrorCode errorCode,
    ) {
      void reportError() {
        enclosingExecutable.hasLegalReturnType = false;
        _errorReporter.reportErrorForNode(errorCode, returnType);
      }

      // It is a compile-time error if the declared return type of
      // a function marked `sync*` or `async*` is `void`.
      if (enclosingExecutable.isGenerator) {
        if (enclosingExecutable.returnType.isVoid) {
          return reportError();
        }
      }

      // It is a compile-time error if the declared return type of
      // a function marked `...` is not a supertype of `...`.
      if (!_isLegalReturnType(expectedElement)) {
        return reportError();
      }
    }

    if (enclosingExecutable.isAsynchronous) {
      if (enclosingExecutable.isGenerator) {
        checkElement(
          _typeProvider.streamElement,
          CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
        );
      } else {
        checkElement(
          _typeProvider.futureElement,
          CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE,
        );
      }
    } else if (enclosingExecutable.isGenerator) {
      checkElement(
        _typeProvider.iterableElement,
        CompileTimeErrorCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE,
      );
    }
  }

  /// Check that a type mismatch between the type of the [expression] and
  /// the expected return type of the enclosing executable.
  void _checkReturnExpression(Expression expression) {
    if (!enclosingExecutable.hasLegalReturnType) {
      // ILLEGAL_ASYNC_RETURN_TYPE has already been reported, meaning the
      // _declared_ return type is illegal; don't confuse by also reporting
      // that the type being returned here does not match that illegal return
      // type.
      return;
    }

    if (_typeSystem.isNonNullableByDefault) {
      _checkReturnExpression_nullSafety(expression);
    } else {
      _checkReturnExpression_legacy(expression);
    }
  }

  void _checkReturnExpression_legacy(Expression expression) {
    // `T` is the declared return type.
    // `S` is the static type of the expression.
    var T = enclosingExecutable.returnType;
    var S = expression.staticType;

    void reportTypeError() {
      if (enclosingExecutable.isClosure) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
          expression,
          [S, T],
        );
      } else if (enclosingExecutable.isConstructor) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR,
          expression,
          [S, T, enclosingExecutable.displayName],
        );
      } else if (enclosingExecutable.isFunction) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION,
          expression,
          [S, T, enclosingExecutable.displayName],
        );
      } else if (enclosingExecutable.isMethod) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_METHOD,
          expression,
          [S, T, enclosingExecutable.displayName],
        );
      }
    }

    if (enclosingExecutable.isSynchronous) {
      // It is a compile-time error if `T` is `void`,
      // and `S` is neither `void`, `dynamic`, nor `Null`.
      if (T.isVoid) {
        if (!_isVoidDynamicOrNull(S)) {
          reportTypeError();
          return;
        }
      }
      // It is a compile-time error if `S` is `void`,
      // and `T` is neither `void`, `dynamic`, nor `Null`.
      if (S.isVoid) {
        if (!_isVoidDynamicOrNull(T)) {
          reportTypeError();
          return;
        }
      }
      // It is a compile-time error if `S` is not `void`,
      // and `S` is not assignable to `T`.
      if (!S.isVoid) {
        if (!_typeSystem.isAssignableTo2(S, T)) {
          reportTypeError();
          return;
        }
      }
      // OK
      return;
    }

    if (enclosingExecutable.isAsynchronous) {
      var flatten_T = _typeSystem.flatten(T);
      var flatten_S = _typeSystem.flatten(S);
      // It is a compile-time error if `T` is `void`,
      // and `flatten(S)` is neither `void`, `dynamic`, nor `Null`.
      //
      // Note, the specification was not implemented correctly, and
      // implementing it now would be a breaking change. So, the code below
      // intentionally does not implement the specification.
      // https://github.com/dart-lang/sdk/issues/41803#issuecomment-635852474
      if (T.isVoid) {
        if (!_isVoidDynamicOrNull(flatten_S)) {
          reportTypeError();
          return;
        }
      }
      // It is a compile-time error if `flatten(S)` is `void`,
      // and `flatten(T)` is neither `void`, `dynamic`, nor `Null`.
      if (flatten_S.isVoid) {
        if (!_isVoidDynamicOrNull(flatten_T)) {
          reportTypeError();
          return;
        }
      }
      // It is a compile-time error if `flatten(S)` is not `void`,
      // and `Future<flatten(S)>` is not assignable to `T`.
      if (!flatten_S.isVoid) {
        var future_flatten_S = _typeProvider.futureType2(flatten_S);
        if (!_typeSystem.isAssignableTo2(future_flatten_S, T)) {
          reportTypeError();
          return;
        }
        // OK
        return;
      }
    }
  }

  void _checkReturnExpression_nullSafety(Expression expression) {
    // `T` is the declared return type.
    // `S` is the static type of the expression.
    var T = enclosingExecutable.returnType;
    var S = expression.staticType;

    void reportTypeError() {
      if (enclosingExecutable.isClosure) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
          expression,
          [S, T],
        );
      } else if (enclosingExecutable.isConstructor) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR,
          expression,
          [S, T, enclosingExecutable.displayName],
        );
      } else if (enclosingExecutable.isFunction) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION,
          expression,
          [S, T, enclosingExecutable.displayName],
        );
      } else if (enclosingExecutable.isMethod) {
        _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_METHOD,
          expression,
          [S, T, enclosingExecutable.displayName],
        );
      }
    }

    if (enclosingExecutable.isSynchronous) {
      // It is a compile-time error if `T` is `void`,
      // and `S` is neither `void`, `dynamic`, nor `Null`.
      if (T.isVoid) {
        if (!_isVoidDynamicOrNull(S)) {
          reportTypeError();
          return;
        }
      }
      // It is a compile-time error if `S` is `void`,
      // and `T` is neither `void` nor `dynamic`.
      if (S.isVoid) {
        if (!_isVoidDynamic(T)) {
          reportTypeError();
          return;
        }
      }
      // It is a compile-time error if `S` is not `void`,
      // and `S` is not assignable to `T`.
      if (!S.isVoid) {
        if (!_typeSystem.isAssignableTo2(S, T)) {
          reportTypeError();
          return;
        }
      }
      // OK
      return;
    }

    if (enclosingExecutable.isAsynchronous) {
      var T_v = _typeSystem.futureValueType(T);
      var flatten_S = _typeSystem.flatten(S);
      // It is a compile-time error if `flatten(T)` is `void`,
      // and `flatten(S)` is neither `void`, `dynamic`, nor `Null`.
      if (T_v.isVoid) {
        if (!_isVoidDynamicOrNull(flatten_S)) {
          reportTypeError();
          return;
        }
      }
      // It is a compile-time error if `flatten(S)` is `void`,
      // and `flatten(T)` is neither `void`, `dynamic`.
      if (flatten_S.isVoid) {
        if (!_isVoidDynamic(T_v)) {
          reportTypeError();
          return;
        }
      }
      // It is a compile-time error if `flatten(S)` is not `void`,
      // and `Future<flatten(S)>` is not assignable to `T`.
      if (!flatten_S.isVoid) {
        if (!_typeSystem.isAssignableTo2(S, T_v) &&
            !_typeSystem.isSubtypeOf2(flatten_S, T_v)) {
          reportTypeError();
          return;
        }
        // OK
        return;
      }
    }
  }

  void _checkReturnWithoutValue(ReturnStatement statement) {
    if (_typeSystem.isNonNullableByDefault) {
      var T = enclosingExecutable.returnType;
      if (enclosingExecutable.isSynchronous) {
        if (_isVoidDynamicOrNull(T)) {
          return;
        }
      } else {
        var T_v = _typeSystem.futureValueType(T);
        if (_isVoidDynamicOrNull(T_v)) {
          return;
        }
      }
    } else {
      var returnType = _flattenedReturnType;
      if (_isVoidDynamicOrNull(returnType)) {
        return;
      }
    }

    _errorReporter.reportErrorForToken(
      CompileTimeErrorCode.RETURN_WITHOUT_VALUE,
      statement.returnKeyword,
    );
  }

  bool _isLegalReturnType(ClassElement expectedElement) {
    DartType returnType = enclosingExecutable.returnType;
    //
    // When checking an async/sync*/async* method, we know the exact type
    // that will be returned (e.g. Future, Iterable, or Stream).
    //
    // For example an `async` function body will return a `Future<T>` for
    // some `T` (possibly `dynamic`).
    //
    // We allow the declared return type to be a supertype of that
    // (e.g. `dynamic`, `Object`), or Future<S> for some S.
    // (We assume the T <: S relation is checked elsewhere.)
    //
    // We do not allow user-defined subtypes of Future, because an `async`
    // method will never return those.
    //
    // To check for this, we ensure that `Future<bottom> <: returnType`.
    //
    // Similar logic applies for sync* and async*.
    //
    var lowerBound = expectedElement.instantiate(
      typeArguments: [NeverTypeImpl.instance],
      nullabilitySuffix: NullabilitySuffix.star,
    );
    return _typeSystem.isSubtypeOf2(lowerBound, returnType);
  }

  static bool _isVoidDynamic(DartType type) {
    return type.isVoid || type.isDynamic;
  }

  static bool _isVoidDynamicOrNull(DartType type) {
    return type.isVoid || type.isDynamic || type.isDartCoreNull;
  }
}
