// 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/ast/extensions.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';

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

  late 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) {
      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.typeOrThrow;

    void reportTypeError() {
      if (enclosingExecutable.catchErrorOnErrorReturnType != null) {
        _errorReporter.reportErrorForNode(
          HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR,
          expression,
          [S, T],
        );
      } else 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.isAssignableTo(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.futureType(flatten_S);
        if (!_typeSystem.isAssignableTo(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.typeOrThrow;

    void reportTypeError() {
      if (enclosingExecutable.catchErrorOnErrorReturnType != null) {
        _errorReporter.reportErrorForNode(
          HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR,
          expression,
          [S, T],
        );
      } else 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.isAssignableTo(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.isAssignableTo(S, T_v) &&
            !_typeSystem.isSubtypeOf(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.isSubtypeOf(lowerBound, returnType);
  }

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

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