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

/// A visitor that finds code that assumes a later version of the SDK than the
/// minimum version required by the SDK constraints in `pubspec.yaml`.
class SdkConstraintVerifier extends RecursiveAstVisitor<void> {
  /// The error reporter to be used to report errors.
  final ErrorReporter _errorReporter;

  /// The element representing the library containing the unit to be verified.
  final LibraryElement _containingLibrary;

  /// The typ provider used to access SDK types.
  final TypeProvider _typeProvider;

  /// The version constraint for the SDK.
  final VersionConstraint _versionConstraint;

  /// A cached flag indicating whether references to the constant-update-2018
  /// features need to be checked. Use [checkConstantUpdate2018] to access this
  /// field.
  bool? _checkConstantUpdate2018;

  /// A cached flag indicating whether uses of extension method features need to
  /// be checked. Use [checkExtensionMethods] to access this field.
  bool? _checkExtensionMethods;

  /// A cached flag indicating whether references to Future and Stream need to
  /// be checked. Use [checkFutureAndStream] to access this field.
  bool? _checkFutureAndStream;

  /// A cached flag indicating whether references to set literals need to
  /// be checked. Use [checkSetLiterals] to access this field.
  bool? _checkSetLiterals;

  /// A flag indicating whether we are visiting code inside a set literal. Used
  /// to prevent over-reporting uses of set literals.
  bool _inSetLiteral = false;

  /// A cached flag indicating whether references to the ui-as-code features
  /// need to be checked. Use [checkUiAsCode] to access this field.
  bool? _checkUiAsCode;

  /// A flag indicating whether we are visiting code inside one of the
  /// ui-as-code features. Used to prevent over-reporting uses of these
  /// features.
  bool _inUiAsCode = false;

  /// Initialize a newly created verifier to use the given [_errorReporter] to
  /// report errors.
  SdkConstraintVerifier(this._errorReporter, this._containingLibrary,
      this._typeProvider, this._versionConstraint);

  /// Return a range covering every version up to, but not including, 2.1.0.
  VersionRange get before_2_1_0 =>
      VersionRange(max: Version.parse('2.1.0'), includeMax: false);

  /// Return a range covering every version up to, but not including, 2.2.0.
  VersionRange get before_2_2_0 =>
      VersionRange(max: Version.parse('2.2.0'), includeMax: false);

  /// Return a range covering every version up to, but not including, 2.2.2.
  VersionRange get before_2_2_2 =>
      VersionRange(max: Version.parse('2.2.2'), includeMax: false);

  /// Return a range covering every version up to, but not including, 2.5.0.
  VersionRange get before_2_5_0 =>
      VersionRange(max: Version.parse('2.5.0'), includeMax: false);

  /// Return a range covering every version up to, but not including, 2.6.0.
  VersionRange get before_2_6_0 =>
      VersionRange(max: Version.parse('2.6.0'), includeMax: false);

  /// Return `true` if references to the constant-update-2018 features need to
  /// be checked.
  bool get checkConstantUpdate2018 => _checkConstantUpdate2018 ??=
      !before_2_5_0.intersect(_versionConstraint).isEmpty;

  /// Return `true` if references to the extension method features need to
  /// be checked.
  bool get checkExtensionMethods => _checkExtensionMethods ??=
      !before_2_6_0.intersect(_versionConstraint).isEmpty;

  /// Return `true` if references to Future and Stream need to be checked.
  bool get checkFutureAndStream => _checkFutureAndStream ??=
      !before_2_1_0.intersect(_versionConstraint).isEmpty;

  /// Return `true` if references to the non-nullable features need to be
  /// checked.
  bool get checkNnbd => !_containingLibrary.isNonNullableByDefault;

  /// Return `true` if references to set literals need to be checked.
  bool get checkSetLiterals =>
      _checkSetLiterals ??= !before_2_2_0.intersect(_versionConstraint).isEmpty;

  /// Return `true` if references to the ui-as-code features (control flow and
  /// spread collections) need to be checked.
  bool get checkUiAsCode =>
      _checkUiAsCode ??= !before_2_2_2.intersect(_versionConstraint).isEmpty;

  @override
  void visitAsExpression(AsExpression node) {
    if (checkConstantUpdate2018 &&
        (node as AsExpressionImpl).inConstantContext) {
      _errorReporter.reportErrorForNode(
          HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT, node);
    }
    super.visitAsExpression(node);
  }

  @override
  void visitBinaryExpression(BinaryExpression node) {
    if (checkConstantUpdate2018) {
      TokenType operatorType = node.operator.type;
      if (operatorType == TokenType.GT_GT_GT) {
        _errorReporter.reportErrorForToken(
            HintCode.SDK_VERSION_GT_GT_GT_OPERATOR, node.operator);
      } else if ((operatorType == TokenType.AMPERSAND ||
              operatorType == TokenType.BAR ||
              operatorType == TokenType.CARET) &&
          (node as BinaryExpressionImpl).inConstantContext) {
        if (node.leftOperand.staticType!.isDartCoreBool) {
          _errorReporter.reportErrorForToken(
              HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT,
              node.operator,
              [node.operator.lexeme]);
        }
      } else if (operatorType == TokenType.EQ_EQ &&
          (node as BinaryExpressionImpl).inConstantContext) {
        bool primitive(Expression node) {
          DartType type = node.staticType!;
          return type.isDartCoreBool ||
              type.isDartCoreDouble ||
              type.isDartCoreInt ||
              type.isDartCoreNull ||
              type.isDartCoreString;
        }

        if (!primitive(node.leftOperand) || !primitive(node.rightOperand)) {
          _errorReporter.reportErrorForToken(
              HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT,
              node.operator);
        }
      }
    }
    super.visitBinaryExpression(node);
  }

  @override
  void visitExtensionDeclaration(ExtensionDeclaration node) {
    if (checkExtensionMethods) {
      _errorReporter.reportErrorForToken(
          HintCode.SDK_VERSION_EXTENSION_METHODS, node.extensionKeyword);
    }
    super.visitExtensionDeclaration(node);
  }

  @override
  void visitExtensionOverride(ExtensionOverride node) {
    if (checkExtensionMethods) {
      _errorReporter.reportErrorForNode(
          HintCode.SDK_VERSION_EXTENSION_METHODS, node.extensionName);
    }
    super.visitExtensionOverride(node);
  }

  @override
  void visitForElement(ForElement node) {
    _validateUiAsCode(node);
    _validateUiAsCodeInConstContext(node);
    bool wasInUiAsCode = _inUiAsCode;
    _inUiAsCode = true;
    super.visitForElement(node);
    _inUiAsCode = wasInUiAsCode;
  }

  @override
  void visitHideCombinator(HideCombinator node) {
    // Don't flag references to either `Future` or `Stream` within a combinator.
  }

  @override
  void visitIfElement(IfElement node) {
    _validateUiAsCode(node);
    _validateUiAsCodeInConstContext(node);
    bool wasInUiAsCode = _inUiAsCode;
    _inUiAsCode = true;
    super.visitIfElement(node);
    _inUiAsCode = wasInUiAsCode;
  }

  @override
  void visitIsExpression(IsExpression node) {
    if (checkConstantUpdate2018 &&
        (node as IsExpressionImpl).inConstantContext) {
      _errorReporter.reportErrorForNode(
          HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT, node);
    }
    super.visitIsExpression(node);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    if (checkConstantUpdate2018 && node.isOperator && node.name.name == '>>>') {
      _errorReporter.reportErrorForNode(
          HintCode.SDK_VERSION_GT_GT_GT_OPERATOR, node.name);
    }
    super.visitMethodDeclaration(node);
  }

  @override
  void visitSetOrMapLiteral(SetOrMapLiteral node) {
    if (node.isSet && checkSetLiterals && !_inSetLiteral) {
      _errorReporter.reportErrorForNode(HintCode.SDK_VERSION_SET_LITERAL, node);
    }
    bool wasInSetLiteral = _inSetLiteral;
    _inSetLiteral = true;
    super.visitSetOrMapLiteral(node);
    _inSetLiteral = wasInSetLiteral;
  }

  @override
  void visitShowCombinator(ShowCombinator node) {
    // Don't flag references to either `Future` or `Stream` within a combinator.
  }

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    if (node.inDeclarationContext()) {
      return;
    }
    var element = node.staticElement;
    if (checkFutureAndStream &&
        element is ClassElement &&
        (element == _typeProvider.futureElement ||
            element == _typeProvider.streamElement)) {
      for (LibraryElement importedLibrary
          in _containingLibrary.importedLibraries) {
        if (!importedLibrary.isDartCore) {
          var namespace = importedLibrary.exportNamespace;
          if (namespace.get(element.name) != null) {
            return;
          }
        }
      }
      _errorReporter.reportErrorForNode(
          HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE, node, [element.name]);
    } else if (checkNnbd && element == _typeProvider.neverType.element) {
      _errorReporter.reportErrorForNode(HintCode.SDK_VERSION_NEVER, node);
    }
  }

  @override
  void visitSpreadElement(SpreadElement node) {
    _validateUiAsCode(node);
    _validateUiAsCodeInConstContext(node);
    bool wasInUiAsCode = _inUiAsCode;
    _inUiAsCode = true;
    super.visitSpreadElement(node);
    _inUiAsCode = wasInUiAsCode;
  }

  /// Given that the [node] is only valid when the ui-as-code feature is
  /// enabled, check that the code will not be executed with a version of the
  /// SDK that does not support the feature.
  void _validateUiAsCode(AstNode node) {
    if (checkUiAsCode && !_inUiAsCode) {
      _errorReporter.reportErrorForNode(HintCode.SDK_VERSION_UI_AS_CODE, node);
    }
  }

  /// Given that the [node] is only valid when the ui-as-code feature is
  /// enabled in a const context, check that the code will not be executed with
  /// a version of the SDK that does not support the feature.
  void _validateUiAsCodeInConstContext(AstNode node) {
    if (checkConstantUpdate2018 &&
        !_inUiAsCode &&
        node.thisOrAncestorOfType<TypedLiteral>()!.isConst) {
      _errorReporter.reportErrorForNode(
          HintCode.SDK_VERSION_UI_AS_CODE_IN_CONST_CONTEXT, node);
    }
  }
}
