// Copyright (c) 2014, 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.

// Many functions here are mostly camelcase, with an occasional underscore to
// separate phrases.
// ignore_for_file: non_constant_identifier_names

import 'dart:math' as math;

import 'package:_fe_analyzer_shared/src/parser/quote.dart'
    show analyzeQuote, Quote, firstQuoteLength, lastQuoteLength;
import 'package:_fe_analyzer_shared/src/scanner/characters.dart' as char;
import 'package:analysis_server/lsp_protocol/protocol.dart'
    show SemanticTokenTypes, SemanticTokenModifiers;
import 'package:analysis_server/src/lsp/constants.dart'
    show CustomSemanticTokenModifiers, CustomSemanticTokenTypes;
import 'package:analysis_server/src/lsp/semantic_tokens/encoder.dart'
    show SemanticTokenInfo;
import 'package:analysis_server/src/lsp/semantic_tokens/mapping.dart'
    show highlightRegionTokenModifiers, highlightRegionTokenTypes;
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/source/source_range.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/extensions.dart';
import 'package:analyzer/src/utilities/extensions/ast.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;

/// A computer for [HighlightRegion]s and LSP [SemanticTokenInfo] in a Dart [CompilationUnit].
class DartUnitHighlightsComputer {
  final CompilationUnit _unit;
  final SourceRange? range;

  final _regions = <HighlightRegion>[];
  final _semanticTokens = <SemanticTokenInfo>[];
  bool _computeRegions = false;
  bool _computeSemanticTokens = false;

  /// Creates a computer for [HighlightRegion]s and LSP [SemanticTokenInfo] in a
  /// Dart [CompilationUnit].
  ///
  /// If [range] is supplied, tokens outside of this range will not be included
  /// in results.
  DartUnitHighlightsComputer(this._unit, {this.range});

  /// Returns the computed highlight regions, not `null`.
  List<HighlightRegion> compute() {
    _reset();
    _computeRegions = true;
    _unit.accept(_DartUnitHighlightsComputerVisitor(this));
    _addCommentRanges();
    return _regions;
  }

  /// Returns the computed semantic tokens, not `null`.
  List<SemanticTokenInfo> computeSemanticTokens() {
    _reset();
    _computeSemanticTokens = true;
    _unit.accept(_DartUnitHighlightsComputerVisitor(this));
    _addCommentRanges();
    return _semanticTokens;
  }

  void _addCommentRanges() {
    Token? token = _unit.beginToken;
    while (token != null) {
      Token? commentToken = token.precedingComments;
      while (commentToken != null) {
        HighlightRegionType? highlightType;
        if (commentToken.type == TokenType.MULTI_LINE_COMMENT) {
          if (commentToken.lexeme.startsWith('/**')) {
            highlightType = HighlightRegionType.COMMENT_DOCUMENTATION;
          } else {
            highlightType = HighlightRegionType.COMMENT_BLOCK;
          }
        }
        if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
          if (commentToken.lexeme.startsWith('///')) {
            highlightType = HighlightRegionType.COMMENT_DOCUMENTATION;
          } else {
            highlightType = HighlightRegionType.COMMENT_END_OF_LINE;
          }
        }
        if (highlightType != null) {
          _addRegion_token(commentToken, highlightType);
        }
        commentToken = commentToken.next;
      }
      if (token.isEof) {
        // Only exit the loop *after* processing the EOF token as it may
        // have preceding comments.
        break;
      }
      token = token.next;
    }
  }

  void _addIdentifierRegion({
    required AstNode parent,
    required Token nameToken,
    required Element? element,
  }) {
    if (_addIdentifierRegion_keyword(nameToken)) {
      return;
    }
    if (_addIdentifierRegion_class(parent, nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_extension(nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_constructor(parent, nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_getterSetterDeclaration(
      parent,
      nameToken,
      element,
    )) {
      return;
    }
    if (_addIdentifierRegion_field(parent, nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_function(parent, nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_importPrefix(nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_label(parent, nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_localVariable(nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_method(parent, nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_parameter(parent, nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_typeAlias(nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_typeParameter(nameToken, element)) {
      return;
    }
    if (_addIdentifierRegion_unresolvedInstanceMemberReference(
      parent,
      nameToken,
      element,
    )) {
      return;
    }
    _addRegion_token(nameToken, HighlightRegionType.IDENTIFIER_DEFAULT);
  }

  void _addIdentifierRegion_annotation(Annotation node) {
    var arguments = node.arguments;
    if (arguments == null) {
      _addRegion_node(node, HighlightRegionType.ANNOTATION);
    } else {
      _addRegion_nodeStart_tokenEnd(
        node,
        arguments.beginToken,
        HighlightRegionType.ANNOTATION,
      );
      _addRegion_token(arguments.endToken, HighlightRegionType.ANNOTATION);
    }
  }

  bool _addIdentifierRegion_class(
    AstNode parent,
    Token nameToken,
    Element? element,
  ) {
    if (element is! InterfaceElement) {
      return false;
    }
    // prepare type
    HighlightRegionType type;
    SemanticTokenTypes? semanticType;
    Set<SemanticTokenModifiers>? semanticModifiers;
    var grandParent = parent.parent;
    if (parent is NamedType &&
        grandParent is ConstructorName &&
        grandParent.parent is InstanceCreationExpression) {
      // new Class()
      type = HighlightRegionType.CONSTRUCTOR;
      semanticType = SemanticTokenTypes.class_;
      semanticModifiers = {CustomSemanticTokenModifiers.constructor};
    } else if (element is EnumElement) {
      type = HighlightRegionType.ENUM;
    } else if (element is ExtensionTypeElement) {
      type = HighlightRegionType.EXTENSION_TYPE;
    } else {
      type = HighlightRegionType.CLASS;
      if (parent is ConstructorDeclaration) {
        semanticModifiers = {
          CustomSemanticTokenModifiers.constructor,
          SemanticTokenModifiers.declaration,
        };
      }
    }

    // add region
    return _addRegion_token(
      nameToken,
      type,
      semanticTokenType: semanticType,
      semanticTokenModifiers: semanticModifiers,
      additionalSemanticTokenModifiers:
          _isAnnotationIdentifier(parent)
              ? {CustomSemanticTokenModifiers.annotation}
              : null,
    );
  }

  bool _addIdentifierRegion_constructor(
    AstNode parent,
    Token nameToken,
    Element? element,
  ) {
    if (element is! ConstructorElement) {
      return false;
    }
    return _addRegion_token(
      nameToken,
      HighlightRegionType.CONSTRUCTOR,
      // For semantic tokens, constructor names are coloured like methods but
      // have a modifier applied.
      semanticTokenType: SemanticTokenTypes.method,
      semanticTokenModifiers: {
        CustomSemanticTokenModifiers.constructor,
        if (_isAnnotationIdentifier(parent))
          CustomSemanticTokenModifiers.annotation,
      },
    );
  }

  bool _addIdentifierRegion_extension(Token nameToken, Element? element) {
    if (element is! ExtensionElement) {
      return false;
    }

    return _addRegion_token(nameToken, HighlightRegionType.EXTENSION);
  }

  bool _addIdentifierRegion_field(
    AstNode parent,
    Token nameToken,
    Element? element,
  ) {
    // Compute the type of the identifier.
    HighlightRegionType? type;
    if (element is FieldElement) {
      if (element.isEnumConstant) {
        type = HighlightRegionType.ENUM_CONSTANT;
      } else if (element.isStatic) {
        type = HighlightRegionType.STATIC_FIELD_DECLARATION;
      } else {
        type = HighlightRegionType.INSTANCE_FIELD_REFERENCE;
      }
    } else if (element is TopLevelVariableElement) {
      type = HighlightRegionType.TOP_LEVEL_VARIABLE_DECLARATION;
    } else if (element is GetterElement) {
      var accessor = element;
      var variable = accessor.variable3;
      if (variable is TopLevelVariableElement) {
        type = HighlightRegionType.TOP_LEVEL_GETTER_REFERENCE;
      } else if (variable is FieldElement && variable.isEnumConstant) {
        type = HighlightRegionType.ENUM_CONSTANT;
      } else if (accessor.isStatic) {
        type = HighlightRegionType.STATIC_GETTER_REFERENCE;
      } else {
        type = HighlightRegionType.INSTANCE_GETTER_REFERENCE;
      }
    } else if (element is SetterElement) {
      var accessor = element;
      var variable = accessor.variable3;
      if (variable is TopLevelVariableElement) {
        type = HighlightRegionType.TOP_LEVEL_SETTER_REFERENCE;
      } else if (variable is FieldElement && variable.isEnumConstant) {
        type = HighlightRegionType.ENUM_CONSTANT;
      } else if (accessor.isStatic) {
        type = HighlightRegionType.STATIC_SETTER_REFERENCE;
      } else {
        type = HighlightRegionType.INSTANCE_SETTER_REFERENCE;
      }
    } else if (element == null) {
      DartType? staticType;
      if (parent is PropertyAccess && nameToken == parent.propertyName.token) {
        staticType = parent.realTarget.staticType;
      } else if (parent.enclosingInstanceElement case ExtensionElement(
        :var extendedType,
      ) when parent is! PrefixedIdentifier) {
        staticType = extendedType;
      }
      // Handle tokens that are references to record fields.
      if (staticType is RecordType) {
        type =
            staticType.fieldByName(nameToken.lexeme) != null
                ? HighlightRegionType.INSTANCE_GETTER_REFERENCE
                : HighlightRegionType.UNRESOLVED_INSTANCE_MEMBER_REFERENCE;
      }
    }
    // Add the highlight region.
    if (type != null) {
      return _addRegion_token(
        nameToken,
        type,
        additionalSemanticTokenModifiers:
            _isAnnotationIdentifier(parent)
                ? {CustomSemanticTokenModifiers.annotation}
                : null,
      );
    }
    return false;
  }

  bool _addIdentifierRegion_function(
    AstNode parent,
    Token nameToken,
    Element? element,
  ) {
    if (element is! TopLevelFunctionElement &&
        element is! LocalFunctionElement) {
      return false;
    }
    var isInvocation =
        parent is MethodInvocation && parent.methodName.token == nameToken;
    HighlightRegionType type;
    var isTopLevel = element is TopLevelFunctionElement;
    type =
        isTopLevel
            ? isInvocation
                ? HighlightRegionType.TOP_LEVEL_FUNCTION_REFERENCE
                : HighlightRegionType.TOP_LEVEL_FUNCTION_TEAR_OFF
            : isInvocation
            ? HighlightRegionType.LOCAL_FUNCTION_REFERENCE
            : HighlightRegionType.LOCAL_FUNCTION_TEAR_OFF;
    return _addRegion_token(nameToken, type);
  }

  bool _addIdentifierRegion_getterSetterDeclaration(
    AstNode parent,
    Token nameToken,
    Element? element,
  ) {
    // should be declaration
    if (!(parent is MethodDeclaration || parent is FunctionDeclaration)) {
      return false;
    }
    var isTopLevel = parent.parent is CompilationUnit;
    HighlightRegionType type;
    if (element is GetterElement) {
      if (isTopLevel) {
        type = HighlightRegionType.TOP_LEVEL_GETTER_DECLARATION;
      } else if (element.isStatic) {
        type = HighlightRegionType.STATIC_GETTER_DECLARATION;
      } else {
        type = HighlightRegionType.INSTANCE_GETTER_DECLARATION;
      }
    } else if (element is SetterElement) {
      if (isTopLevel) {
        type = HighlightRegionType.TOP_LEVEL_SETTER_DECLARATION;
      } else if (element.isStatic) {
        type = HighlightRegionType.STATIC_SETTER_DECLARATION;
      } else {
        type = HighlightRegionType.INSTANCE_SETTER_DECLARATION;
      }
    } else {
      // should be property accessor
      return false;
    }
    return _addRegion_token(nameToken, type);
  }

  bool _addIdentifierRegion_importPrefix(Token nameToken, Element? element) {
    if (element is! PrefixElement) {
      return false;
    }
    return _addRegion_token(nameToken, HighlightRegionType.IMPORT_PREFIX);
  }

  bool _addIdentifierRegion_keyword(Token nameToken) {
    var name = nameToken.lexeme;
    if (name == 'void') {
      return _addRegion_token(
        nameToken,
        HighlightRegionType.KEYWORD,
        semanticTokenModifiers: {CustomSemanticTokenModifiers.void_},
      );
    }
    return false;
  }

  bool _addIdentifierRegion_label(
    AstNode parent,
    Token nameToken,
    Element? element,
  ) {
    if (element is! LabelElement) {
      return false;
    }
    return _addRegion_token(
      nameToken,
      HighlightRegionType.LABEL,
      semanticTokenModifiers:
          parent is! BreakStatement
              ? {SemanticTokenModifiers.declaration}
              : null,
    );
  }

  bool _addIdentifierRegion_localVariable(Token nameToken, Element? element) {
    if (element is! LocalVariableElement) {
      return false;
    }
    // OK
    var type =
        element.type is DynamicType
            ? HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_REFERENCE
            : HighlightRegionType.LOCAL_VARIABLE_REFERENCE;
    return _addRegion_token(nameToken, type);
  }

  bool _addIdentifierRegion_method(
    AstNode parent,
    Token nameToken,
    Element? element,
  ) {
    if (element is! MethodElement) {
      return false;
    }
    var isStatic = element.isStatic;
    var isInvocation =
        (parent is MethodInvocation && parent.methodName.token == nameToken) ||
        (parent is DotShorthandInvocation &&
            parent.memberName.token == nameToken);
    // OK
    HighlightRegionType type;
    if (isStatic) {
      type =
          isInvocation
              ? HighlightRegionType.STATIC_METHOD_REFERENCE
              : HighlightRegionType.STATIC_METHOD_TEAR_OFF;
    } else {
      type =
          isInvocation
              ? HighlightRegionType.INSTANCE_METHOD_REFERENCE
              : HighlightRegionType.INSTANCE_METHOD_TEAR_OFF;
    }
    return _addRegion_token(nameToken, type);
  }

  bool _addIdentifierRegion_parameter(
    AstNode parent,
    Token nameToken,
    Element? element,
  ) {
    if (element is! FormalParameterElement) {
      return false;
    }
    var type =
        element.type is DynamicType
            ? HighlightRegionType.DYNAMIC_PARAMETER_REFERENCE
            : HighlightRegionType.PARAMETER_REFERENCE;
    var modifiers =
        parent is Label ? {CustomSemanticTokenModifiers.label} : null;
    return _addRegion_token(nameToken, type, semanticTokenModifiers: modifiers);
  }

  bool _addIdentifierRegion_typeAlias(Token nameToken, Element? element) {
    if (element is TypeAliasElement) {
      var type =
          element.aliasedType is FunctionType
              ? HighlightRegionType.FUNCTION_TYPE_ALIAS
              : HighlightRegionType.TYPE_ALIAS;
      return _addRegion_token(nameToken, type);
    }
    return false;
  }

  bool _addIdentifierRegion_typeParameter(Token nameToken, Element? element) {
    if (element is! TypeParameterElement) {
      return false;
    }
    return _addRegion_token(
      nameToken,
      HighlightRegionType.TYPE_PARAMETER,
      additionalSemanticTokenModifiers: _additionalModifiersForElement(element),
    );
  }

  bool _addIdentifierRegion_unresolvedInstanceMemberReference(
    AstNode parent,
    Token nameToken,
    Element? element,
  ) {
    // unresolved
    if (element != null) {
      return false;
    }
    // invoke / get / set
    var decorate = false;
    if (parent is MethodInvocation) {
      var target = parent.realTarget;
      if (parent.methodName.token == nameToken &&
          target != null &&
          _isDynamicExpression(target)) {
        decorate = true;
      }
    } else {
      if (parent is PrefixedIdentifier) {
        decorate = parent.identifier.token == nameToken;
      } else if (parent is PropertyAccess) {
        decorate = parent.propertyName.token == nameToken;
      }
    }
    if (decorate) {
      _addRegion_token(
        nameToken,
        HighlightRegionType.UNRESOLVED_INSTANCE_MEMBER_REFERENCE,
      );
      return true;
    }
    return false;
  }

  /// Returns a set of additional semantic token modifiers that apply to
  /// [element].
  Set<SemanticTokenModifiers>? _additionalModifiersForElement(
    Element? element,
  ) {
    return (element?.isWildcardVariable ?? false)
        ? {CustomSemanticTokenModifiers.wildcard}
        : null;
  }

  /// Adds a highlight region/semantic token for the given [offset]/[length].
  ///
  /// If [semanticTokenType] or [semanticTokenModifiers] are not provided, the
  /// values from the default LSP mapping for [type] (also used for plugins)
  /// will be used instead. If [additionalSemanticTokenModifiers] are provided,
  /// they will always be added in addition to [semanticTokenModifiers]/the
  /// defaults.
  ///
  /// If the computer has a [range] set, tokens that fall outside of that range
  /// will not be recorded.
  void _addRegion(
    int offset,
    int length,
    HighlightRegionType type, {
    SemanticTokenTypes? semanticTokenType,
    Set<SemanticTokenModifiers>? semanticTokenModifiers,
    Set<SemanticTokenModifiers>? additionalSemanticTokenModifiers,
  }) {
    var range = this.range;
    if (range != null) {
      var end = offset + length;
      // Skip token if it ends before the range of starts after the range.
      if (end < range.offset || offset > range.end) {
        return;
      }
    }
    if (_computeRegions) {
      _regions.add(HighlightRegion(type, offset, length));
    }
    if (_computeSemanticTokens) {
      // Use default mappings if an overridden type/modifiers were not supplied.
      semanticTokenType ??= highlightRegionTokenTypes[type];
      semanticTokenModifiers ??= highlightRegionTokenModifiers[type];

      if (additionalSemanticTokenModifiers != null &&
          additionalSemanticTokenModifiers.isNotEmpty) {
        semanticTokenModifiers = {
          ...?semanticTokenModifiers,
          ...additionalSemanticTokenModifiers,
        };
      }
      if (semanticTokenType != null) {
        _semanticTokens.add(
          SemanticTokenInfo(
            offset,
            length,
            semanticTokenType,
            semanticTokenModifiers,
          ),
        );
      }
    }
  }

  bool _addRegion_node(
    AstNode node,
    HighlightRegionType type, {
    SemanticTokenTypes? semanticTokenType,
    Set<SemanticTokenModifiers>? semanticTokenModifiers,
  }) {
    var offset = node.offset;
    var length = node.length;
    _addRegion(
      offset,
      length,
      type,
      semanticTokenType: semanticTokenType,
      semanticTokenModifiers: semanticTokenModifiers,
    );
    return true;
  }

  void _addRegion_nodeStart_tokenEnd(
    AstNode a,
    Token b,
    HighlightRegionType type,
  ) {
    var offset = a.offset;
    var end = b.end;
    _addRegion(offset, end - offset, type);
  }

  bool _addRegion_token(
    Token? token,
    HighlightRegionType type, {
    SemanticTokenTypes? semanticTokenType,
    Set<SemanticTokenModifiers>? semanticTokenModifiers,
    Set<SemanticTokenModifiers>? additionalSemanticTokenModifiers,
  }) {
    if (token != null) {
      var offset = token.offset;
      var length = token.length;
      _addRegion(
        offset,
        length,
        type,
        semanticTokenType: semanticTokenType,
        semanticTokenModifiers: semanticTokenModifiers,
        additionalSemanticTokenModifiers: additionalSemanticTokenModifiers,
      );
    }
    return true;
  }

  void _addRegion_tokenStart_tokenEnd(
    Token a,
    Token b,
    HighlightRegionType type,
  ) {
    var offset = a.offset;
    var end = b.end;
    _addRegion(offset, end - offset, type);
  }

  /// Checks whether [parent] is the identifier part of an annotation.
  bool _isAnnotationIdentifier(AstNode? parent) {
    if (parent is Annotation) {
      return true;
    } else if (parent is PrefixedIdentifier && parent.parent is Annotation) {
      return true;
    } else {
      return false;
    }
  }

  void _reset() {
    _computeRegions = false;
    _computeSemanticTokens = false;
    _regions.clear();
    _semanticTokens.clear();
  }

  static bool _isDynamicExpression(Expression e) {
    var type = e.staticType;
    return type != null && type is DynamicType || type is InvalidType;
  }
}

/// An AST visitor for [DartUnitHighlightsComputer].
class _DartUnitHighlightsComputerVisitor extends RecursiveAstVisitor<void> {
  final DartUnitHighlightsComputer computer;

  _DartUnitHighlightsComputerVisitor(this.computer);

  @override
  void visitAnnotation(Annotation node) {
    computer._addIdentifierRegion_annotation(node);
    super.visitAnnotation(node);
  }

  @override
  void visitAsExpression(AsExpression node) {
    computer._addRegion_token(node.asOperator, HighlightRegionType.BUILT_IN);
    super.visitAsExpression(node);
  }

  @override
  void visitAssertStatement(AssertStatement node) {
    computer._addRegion_token(
      node.assertKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitAssertStatement(node);
  }

  @override
  void visitAssignedVariablePattern(AssignedVariablePattern node) {
    computer._addRegion_token(
      node.name,
      HighlightRegionType.LOCAL_VARIABLE_REFERENCE,
    );
    super.visitAssignedVariablePattern(node);
  }

  @override
  void visitAugmentedExpression(AugmentedExpression node) {
    computer._addRegion_token(
      node.augmentedKeyword,
      HighlightRegionType.KEYWORD,
    );
    super.visitAugmentedExpression(node);
  }

  @override
  void visitAugmentedInvocation(AugmentedInvocation node) {
    computer._addRegion_token(
      node.augmentedKeyword,
      HighlightRegionType.KEYWORD,
    );
    super.visitAugmentedInvocation(node);
  }

  @override
  void visitAwaitExpression(AwaitExpression node) {
    computer._addRegion_token(
      node.awaitKeyword,
      HighlightRegionType.BUILT_IN,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitAwaitExpression(node);
  }

  @override
  void visitBlockFunctionBody(BlockFunctionBody node) {
    _addRegions_functionBody(node);
    super.visitBlockFunctionBody(node);
  }

  @override
  void visitBooleanLiteral(BooleanLiteral node) {
    computer._addRegion_node(node, HighlightRegionType.KEYWORD);
    computer._addRegion_node(node, HighlightRegionType.LITERAL_BOOLEAN);
    super.visitBooleanLiteral(node);
  }

  @override
  void visitBreakStatement(BreakStatement node) {
    computer._addRegion_token(
      node.breakKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitBreakStatement(node);
  }

  @override
  void visitCaseClause(CaseClause node) {
    computer._addRegion_token(
      node.caseKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitCaseClause(node);
  }

  @override
  void visitCastPattern(CastPattern node) {
    computer._addRegion_token(node.asToken, HighlightRegionType.BUILT_IN);
    super.visitCastPattern(node);
  }

  @override
  void visitCatchClause(CatchClause node) {
    computer._addRegion_token(
      node.catchKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    computer._addRegion_token(
      node.onKeyword,
      HighlightRegionType.BUILT_IN,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );

    var exceptionParameter = node.exceptionParameter;
    if (exceptionParameter != null) {
      computer._addRegion_token(
        exceptionParameter.name,
        HighlightRegionType.LOCAL_VARIABLE_DECLARATION,
        additionalSemanticTokenModifiers: _additionalModifiersForElement(
          exceptionParameter.declaredElement2,
        ),
      );
    }
    var stackTraceParameter = node.stackTraceParameter;
    if (stackTraceParameter != null) {
      computer._addRegion_token(
        stackTraceParameter.name,
        HighlightRegionType.LOCAL_VARIABLE_DECLARATION,
        additionalSemanticTokenModifiers: _additionalModifiersForElement(
          stackTraceParameter.declaredElement2,
        ),
      );
    }

    super.visitCatchClause(node);
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    computer._addRegion_token(
      node.augmentKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.abstractKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(node.sealedKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(node.baseKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(
      node.interfaceKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(node.finalKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(node.mixinKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(node.classKeyword, HighlightRegionType.KEYWORD);
    computer._addRegion_token(
      node.name,
      HighlightRegionType.CLASS,
      semanticTokenModifiers: {SemanticTokenModifiers.declaration},
    );
    super.visitClassDeclaration(node);
  }

  @override
  void visitClassTypeAlias(ClassTypeAlias node) {
    // TODO(brianwilkerson): Update the interface to expose the token.
    // computer._addRegion_token(
    //     node.augmentKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(
      node.abstractKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(node.sealedKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(node.baseKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(
      node.interfaceKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(node.finalKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(node.mixinKeyword, HighlightRegionType.BUILT_IN);
    super.visitClassTypeAlias(node);
  }

  @override
  void visitConstantPattern(ConstantPattern node) {
    computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
    super.visitConstantPattern(node);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    computer._addRegion_token(
      node.augmentKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.externalKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.factoryKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
    computer._addRegion_token(
      node.name,
      HighlightRegionType.CONSTRUCTOR,
      semanticTokenType: SemanticTokenTypes.method,
      semanticTokenModifiers: {
        CustomSemanticTokenModifiers.constructor,
        SemanticTokenModifiers.declaration,
      },
    );
    super.visitConstructorDeclaration(node);
  }

  @override
  void visitConstructorReference(ConstructorReference node) {
    var constructorName = node.constructorName;
    constructorName.type.accept(this);

    // We have a `ConstructorReference` only when it is resolved.
    // TODO(scheglov): The `ConstructorName` in a tear-off always has a name,
    //  but this is not expressed via types.
    computer._addRegion_node(
      constructorName.name!,
      HighlightRegionType.CONSTRUCTOR_TEAR_OFF,
    );
  }

  @override
  void visitConstructorSelector(ConstructorSelector node) {
    computer._addRegion_node(node.name, HighlightRegionType.CONSTRUCTOR);
  }

  @override
  void visitContinueStatement(ContinueStatement node) {
    computer._addRegion_token(
      node.continueKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitContinueStatement(node);
  }

  @override
  void visitDeclaredIdentifier(DeclaredIdentifier node) {
    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);

    computer._addRegion_token(
      node.name,
      HighlightRegionType.LOCAL_VARIABLE_DECLARATION,
      additionalSemanticTokenModifiers: _additionalModifiersForElement(
        node.declaredElement2,
      ),
    );

    super.visitDeclaredIdentifier(node);
  }

  @override
  void visitDeclaredVariablePattern(DeclaredVariablePattern node) {
    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);
    computer._addRegion_token(
      node.name,
      HighlightRegionType.LOCAL_VARIABLE_DECLARATION,
    );
    super.visitDeclaredVariablePattern(node);
  }

  @override
  void visitDefaultFormalParameter(DefaultFormalParameter node) {
    computer._addRegion_token(
      node.requiredKeyword,
      HighlightRegionType.KEYWORD,
    );
    super.visitDefaultFormalParameter(node);
  }

  @override
  void visitDoStatement(DoStatement node) {
    computer._addRegion_token(
      node.doKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    computer._addRegion_token(
      node.whileKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitDoStatement(node);
  }

  @override
  void visitDotShorthandPropertyAccess(DotShorthandPropertyAccess node) {
    var element = node.propertyName.element;
    if (element is ConstructorElement) {
      computer._addRegion_node(
        node.propertyName,
        HighlightRegionType.CONSTRUCTOR_TEAR_OFF,
      );
    } else {
      computer._addIdentifierRegion(
        parent: node,
        nameToken: node.propertyName.token,
        element: element,
      );
    }
  }

  @override
  void visitDoubleLiteral(DoubleLiteral node) {
    computer._addRegion_node(node, HighlightRegionType.LITERAL_DOUBLE);
    super.visitDoubleLiteral(node);
  }

  @override
  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
    computer._addRegion_token(node.name, HighlightRegionType.ENUM_CONSTANT);
    node.visitChildren(this);
  }

  @override
  void visitEnumDeclaration(EnumDeclaration node) {
    // TODO(brianwilkerson): Uncomment the following lines when the token is
    //  supported.
    // computer._addRegion_token(
    //     node.augmentKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(node.enumKeyword, HighlightRegionType.KEYWORD);
    computer._addRegion_token(node.name, HighlightRegionType.ENUM);
    super.visitEnumDeclaration(node);
  }

  @override
  void visitExportDirective(ExportDirective node) {
    computer._addRegion_node(node, HighlightRegionType.DIRECTIVE);
    computer._addRegion_token(node.exportKeyword, HighlightRegionType.BUILT_IN);
    _addRegions_configurations(node.configurations);
    super.visitExportDirective(node);
  }

  @override
  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
    _addRegions_functionBody(node);
    super.visitExpressionFunctionBody(node);
  }

  @override
  void visitExtendsClause(ExtendsClause node) {
    computer._addRegion_token(node.extendsKeyword, HighlightRegionType.KEYWORD);
    super.visitExtendsClause(node);
  }

  @override
  void visitExtensionDeclaration(ExtensionDeclaration node) {
    computer._addRegion_token(
      node.augmentKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.extensionKeyword,
      HighlightRegionType.KEYWORD,
    );
    computer._addRegion_token(node.name, HighlightRegionType.EXTENSION);
    super.visitExtensionDeclaration(node);
  }

  @override
  void visitExtensionOnClause(ExtensionOnClause node) {
    computer._addRegion_token(node.onKeyword, HighlightRegionType.BUILT_IN);
    super.visitExtensionOnClause(node);
  }

  @override
  void visitExtensionOverride(ExtensionOverride node) {
    computer._addRegion_token(node.name, HighlightRegionType.EXTENSION);

    super.visitExtensionOverride(node);
  }

  @override
  void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) {
    computer._addRegion_token(
      node.extensionKeyword,
      HighlightRegionType.BUILT_IN,
    );

    computer._addRegion_token(node.typeKeyword, HighlightRegionType.BUILT_IN);

    computer._addRegion_token(node.constKeyword, HighlightRegionType.BUILT_IN);

    computer._addRegion_token(
      node.name,
      HighlightRegionType.EXTENSION_TYPE,
      semanticTokenModifiers: {SemanticTokenModifiers.declaration},
    );

    super.visitExtensionTypeDeclaration(node);
  }

  @override
  void visitFieldDeclaration(FieldDeclaration node) {
    // TODO(brianwilkerson): Update the interface to expose the token.
    // computer._addRegion_token(
    //     node.augmentKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(
      node.abstractKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.externalKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(node.staticKeyword, HighlightRegionType.BUILT_IN);

    super.visitFieldDeclaration(node);
  }

  @override
  void visitFieldFormalParameter(FieldFormalParameter node) {
    computer._addRegion_token(
      node.requiredKeyword,
      HighlightRegionType.KEYWORD,
    );

    computer._addRegion_token(node.thisKeyword, HighlightRegionType.KEYWORD);

    computer._addRegion_token(
      node.name,
      HighlightRegionType.INSTANCE_FIELD_REFERENCE,
      additionalSemanticTokenModifiers: _additionalModifiersForElement(
        node.declaredFragment?.element,
      ),
    );

    super.visitFieldFormalParameter(node);
  }

  @override
  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
    computer._addRegion_token(
      node.inKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitForEachPartsWithDeclaration(node);
  }

  @override
  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
    computer._addRegion_token(
      node.inKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitForEachPartsWithIdentifier(node);
  }

  @override
  void visitForEachPartsWithPattern(ForEachPartsWithPattern node) {
    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);
    super.visitForEachPartsWithPattern(node);
  }

  @override
  void visitForElement(ForElement node) {
    computer._addRegion_token(
      node.awaitKeyword,
      HighlightRegionType.BUILT_IN,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    computer._addRegion_token(
      node.forKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitForElement(node);
  }

  @override
  void visitForStatement(ForStatement node) {
    computer._addRegion_token(
      node.awaitKeyword,
      HighlightRegionType.BUILT_IN,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    computer._addRegion_token(
      node.forKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitForStatement(node);
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    computer._addRegion_token(
      node.augmentKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.externalKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.propertyKeyword,
      HighlightRegionType.BUILT_IN,
    );

    HighlightRegionType nameType;
    if (node.isGetter) {
      nameType = HighlightRegionType.TOP_LEVEL_GETTER_DECLARATION;
    } else if (node.isSetter) {
      nameType = HighlightRegionType.TOP_LEVEL_SETTER_DECLARATION;
    } else if (node.parent is CompilationUnit) {
      nameType = HighlightRegionType.TOP_LEVEL_FUNCTION_DECLARATION;
    } else {
      nameType = HighlightRegionType.LOCAL_FUNCTION_DECLARATION;
    }
    computer._addRegion_token(node.name, nameType);

    super.visitFunctionDeclaration(node);
  }

  @override
  void visitFunctionTypeAlias(FunctionTypeAlias node) {
    computer._addRegion_token(
      node.typedefKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.name,
      HighlightRegionType.FUNCTION_TYPE_ALIAS,
    );
    super.visitFunctionTypeAlias(node);
  }

  @override
  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    computer._addRegion_token(
      node.requiredKeyword,
      HighlightRegionType.KEYWORD,
    );
    computer._addRegion_token(
      node.name,
      HighlightRegionType.PARAMETER_DECLARATION,
    );
    super.visitFunctionTypedFormalParameter(node);
  }

  @override
  void visitGenericFunctionType(GenericFunctionType node) {
    computer._addRegion_token(
      node.functionKeyword,
      HighlightRegionType.BUILT_IN,
    );
    super.visitGenericFunctionType(node);
  }

  @override
  void visitGenericTypeAlias(GenericTypeAlias node) {
    computer._addRegion_token(
      node.typedefKeyword,
      HighlightRegionType.BUILT_IN,
    );

    HighlightRegionType nameType;
    if (node.functionType != null) {
      nameType = HighlightRegionType.FUNCTION_TYPE_ALIAS;
    } else {
      nameType = HighlightRegionType.TYPE_ALIAS;
    }
    computer._addRegion_token(node.name, nameType);

    super.visitGenericTypeAlias(node);
  }

  @override
  void visitHideCombinator(HideCombinator node) {
    computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN);
    super.visitHideCombinator(node);
  }

  @override
  void visitIfElement(IfElement node) {
    computer._addRegion_token(
      node.ifKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    computer._addRegion_token(
      node.elseKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitIfElement(node);
  }

  @override
  void visitIfStatement(IfStatement node) {
    computer._addRegion_token(
      node.ifKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    computer._addRegion_token(
      node.elseKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitIfStatement(node);
  }

  @override
  void visitImplementsClause(ImplementsClause node) {
    computer._addRegion_token(
      node.implementsKeyword,
      HighlightRegionType.BUILT_IN,
    );
    super.visitImplementsClause(node);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    computer._addRegion_node(node, HighlightRegionType.DIRECTIVE);
    computer._addRegion_token(node.importKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(
      node.deferredKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(node.asKeyword, HighlightRegionType.BUILT_IN);
    _addRegions_configurations(node.configurations);
    super.visitImportDirective(node);
  }

  @override
  void visitImportPrefixReference(ImportPrefixReference node) {
    computer._addRegion_token(node.name, HighlightRegionType.IMPORT_PREFIX);
  }

  @override
  void visitInstanceCreationExpression(InstanceCreationExpression node) {
    if (node.keyword != null) {
      computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);
    }
    super.visitInstanceCreationExpression(node);
  }

  @override
  void visitIntegerLiteral(IntegerLiteral node) {
    computer._addRegion_node(node, HighlightRegionType.LITERAL_INTEGER);
    super.visitIntegerLiteral(node);
  }

  @override
  void visitInterpolationExpression(InterpolationExpression node) {
    if (computer._computeSemanticTokens) {
      // Interpolation expressions may include uncolored code, but clients may
      // be providing their own basic coloring for strings that would leak
      // into those uncolored parts so we mark them up to allow the client to
      // reset the coloring if required.
      //
      // Using the String token type with a modifier would work for VS Code but
      // would cause other editors that don't know about the modifier (and also
      // do not have their own local coloring) to color the tokens as a string,
      // which is exactly what we'd like to avoid).

      computer._addRegion_node(
        node,
        // The HighlightRegionType here is not used because of the
        // computer._computeSemanticTokens check above.
        HighlightRegionType.LITERAL_STRING,
        semanticTokenType: CustomSemanticTokenTypes.source,
        semanticTokenModifiers: {CustomSemanticTokenModifiers.interpolation},
      );
    }
    super.visitInterpolationExpression(node);
  }

  @override
  void visitInterpolationString(InterpolationString node) {
    computer._addRegion_node(node, HighlightRegionType.LITERAL_STRING);
    if (computer._computeSemanticTokens) {
      var string = node.contents.lexeme;
      var parent = node.parent as StringInterpolation;
      _addRegions_stringEscapes(
        string,
        parent.quote,
        node.offset,
        0,
        string.length,
      );
    }
    super.visitInterpolationString(node);
  }

  @override
  void visitIsExpression(IsExpression node) {
    computer._addRegion_token(node.isOperator, HighlightRegionType.KEYWORD);
    super.visitIsExpression(node);
  }

  @override
  void visitLibraryDirective(LibraryDirective node) {
    computer._addRegion_node(node, HighlightRegionType.DIRECTIVE);
    computer._addRegion_token(
      node.libraryKeyword,
      HighlightRegionType.BUILT_IN,
    );
    super.visitLibraryDirective(node);
  }

  @override
  void visitLibraryIdentifier(LibraryIdentifier node) {
    computer._addRegion_node(node, HighlightRegionType.LIBRARY_NAME);
    null;
  }

  @override
  void visitListLiteral(ListLiteral node) {
    computer._addRegion_node(node, HighlightRegionType.LITERAL_LIST);
    computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
    super.visitListLiteral(node);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    computer._addRegion_token(
      node.augmentKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.externalKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.modifierKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.operatorKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.propertyKeyword,
      HighlightRegionType.BUILT_IN,
    );

    HighlightRegionType nameType;
    if (node.isGetter) {
      nameType =
          node.isStatic
              ? HighlightRegionType.STATIC_GETTER_DECLARATION
              : HighlightRegionType.INSTANCE_GETTER_DECLARATION;
    } else if (node.isSetter) {
      nameType =
          node.isStatic
              ? HighlightRegionType.STATIC_SETTER_DECLARATION
              : HighlightRegionType.INSTANCE_SETTER_DECLARATION;
    } else {
      nameType =
          node.isStatic
              ? HighlightRegionType.STATIC_METHOD_DECLARATION
              : HighlightRegionType.INSTANCE_METHOD_DECLARATION;
    }
    computer._addRegion_token(node.name, nameType);

    super.visitMethodDeclaration(node);
  }

  @override
  void visitMixinDeclaration(MixinDeclaration node) {
    computer._addRegion_token(
      node.augmentKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(node.baseKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(node.mixinKeyword, HighlightRegionType.BUILT_IN);
    computer._addRegion_token(node.name, HighlightRegionType.MIXIN);
    super.visitMixinDeclaration(node);
  }

  @override
  void visitMixinOnClause(MixinOnClause node) {
    computer._addRegion_token(node.onKeyword, HighlightRegionType.BUILT_IN);
    super.visitMixinOnClause(node);
  }

  @override
  void visitNamedType(NamedType node) {
    if (node.importPrefix case var importPrefix?) {
      computer._addRegion_token(
        importPrefix.name,
        HighlightRegionType.IMPORT_PREFIX,
      );
    }

    var type = node.type;
    if (type != null) {
      var isDynamic = type is DynamicType && node.name.lexeme == 'dynamic';
      var isNever = type is NeverType;
      if (isDynamic || isNever) {
        computer._addRegion_token(
          node.name,
          isDynamic
              ? HighlightRegionType.TYPE_NAME_DYNAMIC
              : HighlightRegionType.CLASS,
          semanticTokenType: SemanticTokenTypes.type,
        );
        return;
      }
    }

    computer._addIdentifierRegion(
      parent: node,
      nameToken: node.name,
      element: node.element2,
    );

    node.typeArguments?.accept(this);
  }

  @override
  void visitNativeClause(NativeClause node) {
    computer._addRegion_token(node.nativeKeyword, HighlightRegionType.BUILT_IN);
    super.visitNativeClause(node);
  }

  @override
  void visitNativeFunctionBody(NativeFunctionBody node) {
    computer._addRegion_token(node.nativeKeyword, HighlightRegionType.BUILT_IN);
    super.visitNativeFunctionBody(node);
  }

  @override
  void visitNullLiteral(NullLiteral node) {
    computer._addRegion_token(node.literal, HighlightRegionType.KEYWORD);
    super.visitNullLiteral(node);
  }

  @override
  void visitPartDirective(PartDirective node) {
    computer._addRegion_node(node, HighlightRegionType.DIRECTIVE);
    computer._addRegion_token(node.partKeyword, HighlightRegionType.BUILT_IN);
    super.visitPartDirective(node);
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    computer._addRegion_node(node, HighlightRegionType.DIRECTIVE);
    computer._addRegion_tokenStart_tokenEnd(
      node.partKeyword,
      node.ofKeyword,
      HighlightRegionType.BUILT_IN,
    );
    super.visitPartOfDirective(node);
  }

  @override
  void visitPatternField(PatternField node) {
    var name = node.name?.name;
    if (name != null) {
      // Patterns can be method tear-offs as well as getters:
      // https://github.com/dart-lang/sdk/issues/59976#issuecomment-2613558317
      var type = switch (node.element2) {
        MethodElement() => HighlightRegionType.INSTANCE_METHOD_TEAR_OFF,
        _ => HighlightRegionType.INSTANCE_GETTER_REFERENCE,
      };

      computer._addRegion_token(name, type);
    }
    super.visitPatternField(node);
  }

  @override
  void visitPatternVariableDeclaration(PatternVariableDeclaration node) {
    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);
    super.visitPatternVariableDeclaration(node);
  }

  @override
  void visitRecordLiteral(RecordLiteral node) {
    computer._addRegion_node(node, HighlightRegionType.LITERAL_RECORD);
    computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);

    for (var field in node.fields) {
      if (field is NamedExpression) {
        computer._addRegion_token(
          field.name.label.token,
          HighlightRegionType.PARAMETER_REFERENCE,
        );
        field.expression.accept(this);
      } else {
        field.accept(this);
      }
    }
  }

  @override
  void visitRecordTypeAnnotation(RecordTypeAnnotation node) {
    for (var field in node.fields) {
      computer._addRegion_token(field.name, HighlightRegionType.FIELD);
    }

    super.visitRecordTypeAnnotation(node);
  }

  @override
  void visitRepresentationConstructorName(RepresentationConstructorName node) {
    computer._addRegion_token(
      node.name,
      HighlightRegionType.CONSTRUCTOR,
      semanticTokenType: SemanticTokenTypes.method,
      semanticTokenModifiers: {
        CustomSemanticTokenModifiers.constructor,
        SemanticTokenModifiers.declaration,
      },
    );

    super.visitRepresentationConstructorName(node);
  }

  @override
  void visitRepresentationDeclaration(RepresentationDeclaration node) {
    computer._addRegion_token(
      node.fieldName,
      HighlightRegionType.INSTANCE_FIELD_DECLARATION,
    );

    super.visitRepresentationDeclaration(node);
  }

  @override
  void visitRethrowExpression(RethrowExpression node) {
    computer._addRegion_token(
      node.rethrowKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitRethrowExpression(node);
  }

  @override
  void visitReturnStatement(ReturnStatement node) {
    computer._addRegion_token(
      node.returnKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitReturnStatement(node);
  }

  @override
  void visitSetOrMapLiteral(SetOrMapLiteral node) {
    if (node.isMap) {
      computer._addRegion_node(node, HighlightRegionType.LITERAL_MAP);
      // TODO(brianwilkerson): Add a highlight region for set literals. This
      //  would be a breaking change, but would be consistent with list and map
      //  literals.
      //    } else if (node.isSet) {
      //    computer._addRegion_node(node, HighlightRegionType.LITERAL_SET);
    }
    computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
    super.visitSetOrMapLiteral(node);
  }

  @override
  void visitShowCombinator(ShowCombinator node) {
    computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN);
    super.visitShowCombinator(node);
  }

  @override
  void visitSimpleFormalParameter(SimpleFormalParameter node) {
    computer._addRegion_token(
      node.requiredKeyword,
      HighlightRegionType.KEYWORD,
    );

    var declaredElement = node.declaredFragment!.element;
    computer._addRegion_token(
      node.name,
      declaredElement.type is DynamicType
          ? HighlightRegionType.DYNAMIC_PARAMETER_DECLARATION
          : HighlightRegionType.PARAMETER_DECLARATION,
      additionalSemanticTokenModifiers: _additionalModifiersForElement(
        declaredElement,
      ),
    );

    super.visitSimpleFormalParameter(node);
  }

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    var parent = node.parent;
    if (parent != null) {
      computer._addIdentifierRegion(
        parent: parent,
        nameToken: node.token,
        element: node.writeOrReadElement2,
      );
    }
    super.visitSimpleIdentifier(node);
  }

  @override
  void visitSimpleStringLiteral(SimpleStringLiteral node) {
    computer._addRegion_node(node, HighlightRegionType.LITERAL_STRING);
    if (computer._computeSemanticTokens) {
      var string = node.literal.lexeme;
      var quote = analyzeQuote(string);
      var startIndex = firstQuoteLength(string, quote);
      var endIndex = string.length - lastQuoteLength(quote);
      _addRegions_stringEscapes(
        string,
        quote,
        node.offset,
        startIndex,
        endIndex,
      );
    }
    super.visitSimpleStringLiteral(node);
  }

  @override
  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
    computer._addRegion_token(node.superKeyword, HighlightRegionType.KEYWORD);
    super.visitSuperConstructorInvocation(node);
  }

  @override
  void visitSuperExpression(SuperExpression node) {
    computer._addRegion_token(node.superKeyword, HighlightRegionType.KEYWORD);
    super.visitSuperExpression(node);
  }

  @override
  void visitSuperFormalParameter(SuperFormalParameter node) {
    computer._addRegion_token(
      node.requiredKeyword,
      HighlightRegionType.KEYWORD,
    );

    computer._addRegion_token(node.superKeyword, HighlightRegionType.KEYWORD);

    computer._addRegion_token(
      node.name,
      node.declaredFragment?.element.type is DynamicType
          ? HighlightRegionType.DYNAMIC_PARAMETER_DECLARATION
          : HighlightRegionType.PARAMETER_DECLARATION,
    );

    super.visitSuperFormalParameter(node);
  }

  @override
  void visitSwitchCase(SwitchCase node) {
    computer._addRegion_token(
      node.keyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitSwitchCase(node);
  }

  @override
  void visitSwitchDefault(SwitchDefault node) {
    computer._addRegion_token(
      node.keyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitSwitchDefault(node);
  }

  @override
  void visitSwitchExpression(SwitchExpression node) {
    computer._addRegion_token(node.switchKeyword, HighlightRegionType.KEYWORD);
    super.visitSwitchExpression(node);
  }

  @override
  void visitSwitchPatternCase(SwitchPatternCase node) {
    computer._addRegion_token(
      node.keyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitSwitchPatternCase(node);
  }

  @override
  void visitSwitchStatement(SwitchStatement node) {
    computer._addRegion_token(
      node.switchKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitSwitchStatement(node);
  }

  @override
  void visitThisExpression(ThisExpression node) {
    computer._addRegion_token(node.thisKeyword, HighlightRegionType.KEYWORD);
    super.visitThisExpression(node);
  }

  @override
  void visitThrowExpression(ThrowExpression node) {
    computer._addRegion_token(
      node.throwKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitThrowExpression(node);
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    computer._addRegion_token(
      node.augmentKeyword,
      HighlightRegionType.BUILT_IN,
    );
    computer._addRegion_token(
      node.externalKeyword,
      HighlightRegionType.BUILT_IN,
    );

    super.visitTopLevelVariableDeclaration(node);
  }

  @override
  void visitTryStatement(TryStatement node) {
    computer._addRegion_token(
      node.tryKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    computer._addRegion_token(
      node.finallyKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitTryStatement(node);
  }

  @override
  void visitTypeParameter(TypeParameter node) {
    computer._addRegion_token(
      node.name,
      HighlightRegionType.TYPE_PARAMETER,
      additionalSemanticTokenModifiers: _additionalModifiersForElement(
        node.declaredFragment?.element,
      ),
    );
    super.visitTypeParameter(node);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    var element = node.declaredFragment?.element ?? node.declaredElement2;
    if (element is FieldElement) {
      computer._addRegion_token(
        node.name,
        element.isStatic
            ? HighlightRegionType.STATIC_FIELD_DECLARATION
            : HighlightRegionType.INSTANCE_FIELD_DECLARATION,
      );
    } else if (element is LocalVariableElement) {
      computer._addRegion_token(
        node.name,
        element.type is DynamicType
            ? HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_DECLARATION
            : HighlightRegionType.LOCAL_VARIABLE_DECLARATION,
        additionalSemanticTokenModifiers: _additionalModifiersForElement(
          element,
        ),
      );
    } else if (element is TopLevelVariableElement) {
      computer._addRegion_token(
        node.name,
        HighlightRegionType.TOP_LEVEL_VARIABLE_DECLARATION,
      );
    }

    super.visitVariableDeclaration(node);
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    computer._addRegion_token(node.lateKeyword, HighlightRegionType.KEYWORD);
    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);
    super.visitVariableDeclarationList(node);
  }

  @override
  void visitWhenClause(WhenClause node) {
    computer._addRegion_token(
      node.whenKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitWhenClause(node);
  }

  @override
  void visitWhileStatement(WhileStatement node) {
    computer._addRegion_token(
      node.whileKeyword,
      HighlightRegionType.KEYWORD,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitWhileStatement(node);
  }

  @override
  void visitWildcardPattern(WildcardPattern node) {
    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);

    // For consistency, wildcard patterns are treated like wildcard variable
    // declarations.
    // https://github.com/dart-lang/sdk/issues/56567
    computer._addRegion_token(
      node.name,
      HighlightRegionType.LOCAL_VARIABLE_DECLARATION,
      additionalSemanticTokenModifiers: {CustomSemanticTokenModifiers.wildcard},
    );

    super.visitWildcardPattern(node);
  }

  @override
  void visitWithClause(WithClause node) {
    computer._addRegion_token(node.withKeyword, HighlightRegionType.KEYWORD);
    super.visitWithClause(node);
  }

  @override
  void visitYieldStatement(YieldStatement node) {
    var keyword = node.yieldKeyword;
    var star = node.star;
    var offset = keyword.offset;
    var end = star != null ? star.end : keyword.end;
    computer._addRegion(
      offset,
      end - offset,
      HighlightRegionType.BUILT_IN,
      semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
    );
    super.visitYieldStatement(node);
  }

  /// Returns a set of additional semantic token modifiers that apply to
  /// [element].
  Set<SemanticTokenModifiers>? _additionalModifiersForElement(
    Element? element,
  ) {
    return computer._additionalModifiersForElement(element);
  }

  void _addRegions_configurations(List<Configuration> configurations) {
    for (var configuration in configurations) {
      computer._addRegion_token(
        configuration.ifKeyword,
        HighlightRegionType.BUILT_IN,
        semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
      );
    }
  }

  void _addRegions_functionBody(FunctionBody node) {
    var keyword = node.keyword;
    if (keyword != null) {
      var star = node.star;
      var offset = keyword.offset;
      var end = star != null ? star.end : keyword.end;
      computer._addRegion(
        offset,
        end - offset,
        HighlightRegionType.BUILT_IN,
        semanticTokenModifiers: {CustomSemanticTokenModifiers.control},
      );
    }
  }

  void _addRegions_stringEscapes(
    String string,
    Quote quote,
    int nodeOffset,
    int startIndex,
    int endIndex,
  ) {
    switch (quote) {
      case Quote.RawSingle ||
          Quote.RawDouble ||
          Quote.RawMultiLineSingle ||
          Quote.RawMultiLineDouble:
        // Raw strings don't have escape characters.
        break;
      case Quote.Single ||
          Quote.Double ||
          Quote.MultiLineSingle ||
          Quote.MultiLineDouble:
        _findEscapes(
          string,
          startIndex: startIndex,
          endIndex: endIndex,
          listener: (offset, end) {
            var length = end - offset;
            computer._addRegion(
              nodeOffset + offset,
              length,
              HighlightRegionType.VALID_STRING_ESCAPE,
            );
          },
        );
    }
  }

  /// Finds escaped regions within a string between [startIndex] and [endIndex],
  /// calling [listener] for each found region.
  void _findEscapes(
    String string, {
    required int startIndex,
    required int endIndex,
    required void Function(int offset, int end) listener,
  }) {
    var codeUnits = string.codeUnits;
    var length = string.length;

    bool isBackslash(int i) => i <= length && codeUnits[i] == char.$BACKSLASH;
    bool isHexEscape(int i) => i <= length && codeUnits[i] == char.$x;
    bool isUnicodeHexEscape(int i) => i <= length && codeUnits[i] == char.$u;
    bool isOpenBrace(int i) =>
        i <= length && codeUnits[i] == char.$OPEN_CURLY_BRACKET;
    bool isCloseBrace(int i) =>
        i <= length && codeUnits[i] == char.$CLOSE_CURLY_BRACKET;
    int? numHexDigits(int i, {required int min, required int max}) {
      var numHexDigits = 0;
      for (var j = i; j < math.min(i + max, length); j++) {
        if (!char.isHexDigit(codeUnits[j])) {
          break;
        }
        numHexDigits++;
      }
      return numHexDigits >= min ? numHexDigits : null;
    }

    for (var i = startIndex; i < endIndex;) {
      if (isBackslash(i)) {
        var backslashOffset = i++;
        // All escaped characters are a single character except for:
        // `\uXXXX` or `\u{XX?X?X?X?X?}` for Unicode hex escape.
        // `\xXX` for hex escape.
        if (isHexEscape(i)) {
          // Expect exactly 2 hex digits.
          var numDigits = numHexDigits(i + 1, min: 2, max: 2);
          if (numDigits != null) {
            i += 1 + numDigits;
            listener(backslashOffset, i);
          }
        } else if (isUnicodeHexEscape(i) && isOpenBrace(i + 1)) {
          // Expect 1-6 hex digits followed by '}'.
          var numDigits = numHexDigits(i + 2, min: 1, max: 6);
          if (numDigits != null && isCloseBrace(i + 2 + numDigits)) {
            i += 2 + numDigits + 1;
            listener(backslashOffset, i);
          }
        } else if (isUnicodeHexEscape(i)) {
          // Expect exactly 4 hex digits.
          var numDigits = numHexDigits(i + 1, min: 4, max: 4);
          if (numDigits != null) {
            i += 1 + numDigits;
            listener(backslashOffset, i);
          }
        } else {
          i++;
          // Single-character escape.
          listener(backslashOffset, i);
        }
      } else {
        i++;
      }
    }
  }
}

extension on StringInterpolation {
  Quote get quote => switch ((isRaw, isMultiline, isSingleQuoted)) {
    (true, true, true) => Quote.RawMultiLineSingle,
    (true, true, false) => Quote.RawMultiLineDouble,
    (true, false, true) => Quote.RawSingle,
    (true, false, false) => Quote.RawDouble,
    (false, true, true) => Quote.MultiLineSingle,
    (false, true, false) => Quote.MultiLineDouble,
    (false, false, true) => Quote.Single,
    (false, false, false) => Quote.Double,
  };
}
