// 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/extensions.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.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.inConstantContext) {
        if (node.leftOperand.typeOrThrow.isDartCoreBool) {
          _errorReporter.reportErrorForToken(
              HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT,
              node.operator,
              [node.operator.lexeme]);
        }
      } else if (operatorType == TokenType.EQ_EQ && node.inConstantContext) {
        bool primitive(Expression node) {
          DartType type = node.typeOrThrow;
          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.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);
    }
  }
}
