// Copyright (c) 2016, 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/analysis/results.dart';
import 'package:analyzer/dart/ast/syntactic_entity.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/index.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/utilities/cancellation.dart';
import 'package:analyzer/src/utilities/fuzzy_matcher.dart';
import 'package:collection/collection.dart';

Fragment _getEnclosingFragment(
  LibraryFragmentImpl libraryFragment,
  int offset,
) {
  Fragment? visitFragment(Fragment fragment) {
    var fragmentImpl = fragment as FragmentImpl;
    var codeOffset = fragmentImpl.codeOffset;
    var codeLength = fragmentImpl.codeLength;
    if (codeOffset == null || codeLength == null) {
      return null;
    }

    var codeEnd = codeOffset + codeLength;
    if (codeOffset <= offset && offset <= codeEnd) {
      for (var child in fragment.children3) {
        var result = visitFragment(child);
        if (result != null) {
          return result;
        }
      }
      return fragment;
    }

    return null;
  }

  var result = visitFragment(libraryFragment);
  return result ?? libraryFragment;
}

DeclarationKind? _getSearchElementKind(Element element) {
  if (element is EnumElement) {
    return DeclarationKind.ENUM;
  }

  if (element is ExtensionTypeElement) {
    return DeclarationKind.EXTENSION_TYPE;
  }

  if (element is MixinElement) {
    return DeclarationKind.MIXIN;
  }

  if (element is ClassElement) {
    if (element.isMixinApplication) {
      return DeclarationKind.CLASS_TYPE_ALIAS;
    }
    return DeclarationKind.CLASS;
  }

  if (element is ConstructorElement) {
    return DeclarationKind.CONSTRUCTOR;
  }

  if (element is ExtensionElement) {
    return DeclarationKind.EXTENSION;
  }

  if (element is FieldElement) {
    if (element.isEnumConstant) return DeclarationKind.ENUM_CONSTANT;
    return DeclarationKind.FIELD;
  }

  if (element is LocalFunctionElement || element is TopLevelFunctionElement) {
    return DeclarationKind.FUNCTION;
  }

  if (element is MethodElement) {
    return DeclarationKind.METHOD;
  }

  if (element is GetterElement) {
    return DeclarationKind.GETTER;
  }

  if (element is SetterElement) {
    return DeclarationKind.SETTER;
  }

  if (element is TypeAliasElement) {
    return DeclarationKind.TYPE_ALIAS;
  }

  if (element is VariableElement) {
    return DeclarationKind.VARIABLE;
  }

  return null;
}

/// An element declaration.
class Declaration {
  final int fileIndex;
  final LineInfo lineInfo;
  final String name;
  final DeclarationKind kind;
  final int offset;
  final int line;
  final int column;
  final int codeOffset;
  final int codeLength;
  final String? className;
  final String? mixinName;
  final String? parameters;

  Declaration(
    this.fileIndex,
    this.lineInfo,
    this.name,
    this.kind,
    this.offset,
    this.line,
    this.column,
    this.codeOffset,
    this.codeLength,
    this.className,
    this.mixinName,
    this.parameters,
  );
}

/// The kind of a [Declaration].
enum DeclarationKind {
  CLASS,
  CLASS_TYPE_ALIAS,
  CONSTRUCTOR,
  ENUM,
  ENUM_CONSTANT,
  EXTENSION,
  EXTENSION_TYPE,
  FIELD,
  FUNCTION,
  FUNCTION_TYPE_ALIAS,
  GETTER,
  METHOD,
  MIXIN,
  SETTER,
  TYPE_ALIAS,
  VARIABLE,
}

/// Searches through files known to [drivers] for declarations.
///
/// If files are known to multiple drivers, they will be searched only within
/// the context of the first.
class FindDeclarations {
  final List<AnalysisDriver> drivers;
  final WorkspaceSymbols result;
  final int? maxResults;
  final String pattern;
  final FuzzyMatcher matcher;
  final String? onlyForFile;
  final bool onlyAnalyzed;
  final OwnedFiles ownedFiles;
  final OperationPerformanceImpl performance;

  FindDeclarations(
    this.drivers,
    this.result,
    this.pattern,
    this.maxResults, {
    this.onlyForFile,
    this.onlyAnalyzed = false,
    required this.ownedFiles,
    required this.performance,
  }) : matcher = FuzzyMatcher(pattern);

  Future<void> compute([CancellationToken? cancellationToken]) async {
    if (!onlyAnalyzed) {
      await performance.runAsync('discoverAvailableFiles', (performance) async {
        await Future.wait(
          drivers.map((driver) => driver.discoverAvailableFiles()),
        );
      });
    }

    var entries = [
      ...ownedFiles.addedFiles.entries,
      if (!onlyAnalyzed) ...ownedFiles.knownFiles.entries,
    ];

    await performance.runAsync('findDeclarations', (performance) async {
      await _FindDeclarations(
        entries,
        result,
        pattern,
        matcher,
        maxResults,
        onlyForFile: onlyForFile,
        performance: performance,
      ).compute(cancellationToken);
    });
  }
}

/// Visitor that adds [SearchResult]s for references to the [import].
class ImportElementReferencesVisitor extends RecursiveAstVisitor<void> {
  final List<SearchResult> results = <SearchResult>[];

  final LibraryImport import;
  final LibraryFragmentImpl enclosingLibraryFragment;

  late final Set<Element> importedElements;

  ImportElementReferencesVisitor(
    LibraryImport element,
    this.enclosingLibraryFragment,
  ) : import = element {
    importedElements = element.namespace.definedNames2.values.toSet();
  }

  @override
  void visitExportDirective(ExportDirective node) {}

  @override
  void visitImportDirective(ImportDirective node) {}

  @override
  void visitNamedType(NamedType node) {
    if (importedElements.contains(node.element2)) {
      var prefixFragment = import.prefix2;
      var importPrefix = node.importPrefix;
      if (prefixFragment == null) {
        if (importPrefix == null) {
          _addResult(node.offset, 0);
        }
      } else {
        if (importPrefix != null &&
            importPrefix.element2 == prefixFragment.element) {
          var offset = importPrefix.offset;
          var end = importPrefix.period.end;
          _addResult(offset, end - offset);
        }
      }
    }

    node.importPrefix?.accept(this);
    node.typeArguments?.accept(this);
  }

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    if (node.inDeclarationContext()) {
      return;
    }
    if (import.prefix2 != null) {
      if (node.element == import.prefix2?.element) {
        var parent = node.parent;
        if (parent is PrefixedIdentifier && parent.prefix == node) {
          var element = parent.writeOrReadElement2?.baseElement;
          if (importedElements.contains(element)) {
            _addResultForPrefix(node, parent.identifier);
          }
        }
        if (parent is MethodInvocation && parent.target == node) {
          var element = parent.methodName.element?.baseElement;
          if (importedElements.contains(element)) {
            _addResultForPrefix(node, parent.methodName);
          }
        }
      }
    } else {
      var element = node.writeOrReadElement2?.baseElement;
      if (importedElements.contains(element)) {
        _addResult(node.offset, 0);
      }
    }
  }

  void _addResult(int offset, int length) {
    var enclosingFragment = _getEnclosingFragment(
      enclosingLibraryFragment,
      offset,
    );
    results.add(
      SearchResult._(
        enclosingFragment,
        SearchResultKind.REFERENCE,
        offset,
        length,
        true,
        false,
      ),
    );
  }

  void _addResultForPrefix(SimpleIdentifier prefixNode, AstNode nextNode) {
    int prefixOffset = prefixNode.offset;
    _addResult(prefixOffset, nextNode.offset - prefixOffset);
  }
}

/// A single reference to a [LibraryFragment], e.g. import of a library, which
/// is a reference to the first library fragment.
class LibraryFragmentSearchMatch {
  /// The library fragment that contains this reference.
  final LibraryFragment libraryFragment;

  /// The source range of the URI.
  final SourceRange range;

  LibraryFragmentSearchMatch({
    required this.libraryFragment,
    required this.range,
  });
}

/// Search support for an [AnalysisDriver].
class Search {
  final AnalysisDriver _driver;

  Search(this._driver);

  /// Returns class or mixin members with the given [name].
  Future<List<Element>> classMembers(
    String name,
    SearchedFiles searchedFiles,
  ) async {
    var elements = <Element>[];

    void addElement(Element element) {
      if (!element.isSynthetic && element.displayName == name) {
        elements.add(element);
      }
    }

    void addElements(InterfaceElement element) {
      element.getters2.forEach(addElement);
      element.setters2.forEach(addElement);
      element.fields2.forEach(addElement);
      element.methods2.forEach(addElement);
    }

    var files = await _driver.getFilesDefiningClassMemberName(name);
    for (var file in files) {
      if (searchedFiles.add(file.path, this)) {
        var libraryResult = await _driver.getLibraryByUri(file.uriStr);
        if (libraryResult is LibraryElementResultImpl) {
          var element = libraryResult.element2;
          element.classes.forEach(addElements);
          element.enums.forEach(addElements);
          element.extensionTypes.forEach(addElements);
          element.mixins.forEach(addElements);
        }
      }
    }
    return elements;
  }

  /// Return the prefixes used to reference the [element] in any of the
  /// compilation units in the [library]. The returned set will include an empty
  /// string if the element is referenced without a prefix.
  Future<Set<String>> prefixesUsedInLibrary(
    LibraryElementImpl library,
    Element element,
  ) async {
    var prefixes = <String>{};
    for (var unit in library.units) {
      var index = await _driver.getIndex(unit.source.fullName);
      if (index != null) {
        _IndexRequest request = _IndexRequest(index);
        int elementId = request.findElementId(element);
        if (elementId != -1) {
          var prefixList = index.elementImportPrefixes[elementId].split(',');
          prefixes.addAll(prefixList);
        }
      }
    }
    return prefixes;
  }

  /// Returns references to the [element].
  Future<List<SearchResult>> references(
    Element? element,
    SearchedFiles searchedFiles,
  ) async {
    if (element == null) {
      return const <SearchResult>[];
    }

    ElementKind kind = element.kind;
    if (element is ExtensionElement ||
        element is InterfaceElement ||
        element is SetterElement ||
        element is TypeAliasElement) {
      return _searchReferences(element, searchedFiles);
    } else if (element is ConstructorElement) {
      return await _searchReferences_Constructor(element, searchedFiles);
    } else if (element is GetterElement) {
      return _searchReferences_Getter(element, searchedFiles);
    } else if (element is PropertyInducingElement) {
      return _searchReferences_Field(element, searchedFiles);
    } else if (element is LocalFunctionElement) {
      return _searchReferences_Local(element, (n) => n is Block, searchedFiles);
    } else if (element is ExecutableElement) {
      return _searchReferences_Function(element, searchedFiles);
    } else if (element is PatternVariableElementImpl2) {
      return _searchReferences_PatternVariable(element, searchedFiles);
    } else if (kind == ElementKind.LABEL ||
        kind == ElementKind.LOCAL_VARIABLE) {
      return _searchReferences_Local(
        element,
        (n) =>
            n is Block ||
            n is ForElement ||
            n is FunctionBody ||
            n is TopLevelVariableDeclaration ||
            n is SwitchExpression ||
            n.parent is CompilationUnit,
        searchedFiles,
      );
    } else if (element is LibraryElementImpl) {
      return _searchReferences_Library(element, searchedFiles);
    } else if (element is FormalParameterElement) {
      return _searchReferences_Parameter(element, searchedFiles);
    } else if (element is PrefixElementImpl2) {
      return _searchReferences_Prefix(element, searchedFiles);
    } else if (element is TypeParameterElement) {
      return _searchReferences_Local(
        element,
        (n) => n.parent is CompilationUnit,
        searchedFiles,
      );
    }
    return const <SearchResult>[];
  }

  Future<List<LibraryFragmentSearchMatch>> referencesLibraryFragment(
    LibraryFragment libraryFragment,
  ) async {
    var legacyElement = libraryFragment as LibraryFragmentImpl;
    var legacyResults = await _searchReferences_CompilationUnit(legacyElement);

    return legacyResults.map((match) {
      return LibraryFragmentSearchMatch(
        libraryFragment: match.enclosingFragment as LibraryFragment,
        range: SourceRange(match.offset, match.length),
      );
    }).toList();
  }

  Future<List<LibraryFragmentSearchMatch>> referencesLibraryImport(
    LibraryImport import,
    SearchedFiles searchedFiles,
  ) async {
    import as LibraryImportImpl;
    var legacyResults = await _searchReferences_Import(import, searchedFiles);

    return legacyResults.map((match) {
      return LibraryFragmentSearchMatch(
        libraryFragment: match.enclosingFragment.libraryFragment!,
        range: SourceRange(match.offset, match.length),
      );
    }).toList();
  }

  /// Returns subtypes of the given [type].
  ///
  /// The [searchedFiles] are consulted to see if a file is "owned" by this
  /// [Search] object, so should be only searched by it to avoid duplicate
  /// results; and updated to take ownership if the file is not owned yet.
  Future<List<SearchResult>> subTypes(
    InterfaceElement? type,
    SearchedFiles searchedFiles, {
    List<FileState>? filesToCheck,
  }) async {
    if (type == null) {
      return const <SearchResult>[];
    }
    List<SearchResult> results = <SearchResult>[];
    await _addResults(results, type, searchedFiles, const {
      IndexRelationKind.IS_EXTENDED_BY:
          SearchResultKind.REFERENCE_IN_EXTENDS_CLAUSE,
      IndexRelationKind.IS_MIXED_IN_BY:
          SearchResultKind.REFERENCE_IN_WITH_CLAUSE,
      IndexRelationKind.IS_IMPLEMENTED_BY:
          SearchResultKind.REFERENCE_IN_IMPLEMENTS_CLAUSE,
      IndexRelationKind.CONSTRAINS: SearchResultKind.REFERENCE_IN_ON_CLAUSE,
    }, filesToCheck: filesToCheck);
    return results;
  }

  /// Return direct [SubtypeResult]s for either the [type] or [subtype].
  Future<List<SubtypeResult>> subtypes(
    SearchedFiles searchedFiles, {
    InterfaceElement? type,
    SubtypeResult? subtype,
  }) async {
    var type1 = type;
    String name;
    String id;
    if (type1 != null) {
      name = type1.name3!;
      var librarySource = type1.library2.firstFragment.source;
      var source = type1.firstFragment.libraryFragment.source;
      id = '${librarySource.uri};${source.uri};$name';
    } else {
      name = subtype!.name;
      id = subtype.id;
    }

    await _driver.discoverAvailableFiles();

    List<SubtypeResult> results = [];

    // Note, this is a defensive copy.
    var files = _driver.fsState.getFilesSubtypingName(name)?.toList();

    if (files != null) {
      for (FileState file in files) {
        if (searchedFiles.add(file.path, this)) {
          var index = await _driver.getIndex(file.path);
          if (index != null) {
            var request = _IndexRequest(index);
            request.addSubtypes(id, results, file);
          }
        }
      }
    }

    return results;
  }

  /// Returns top-level elements with names matching the given [regExp].
  Future<List<Element>> topLevelElements(RegExp regExp) async {
    var elements = <Element>[];

    void addElement(Element element) {
      if (!element.isSynthetic && regExp.hasMatch(element.displayName)) {
        elements.add(element);
      }
    }

    List<FileState> knownFiles = _driver.fsState.knownFiles.toList();
    for (FileState file in knownFiles) {
      var libraryResult = await _driver.getLibraryByUri(file.uriStr);
      if (libraryResult is LibraryElementResult) {
        var element = libraryResult.element2;
        element.getters.forEach(addElement);
        element.classes.forEach(addElement);
        element.enums.forEach(addElement);
        element.extensions.forEach(addElement);
        element.extensionTypes.forEach(addElement);
        element.topLevelFunctions.forEach(addElement);
        element.mixins.forEach(addElement);
        element.setters.forEach(addElement);
        element.topLevelVariables.forEach(addElement);
        element.typeAliases.forEach(addElement);
      }
    }
    return elements;
  }

  /// Returns unresolved references to the given [name].
  Future<List<SearchResult>> unresolvedMemberReferences(
    String? name,
    SearchedFiles searchedFiles,
  ) async {
    if (name == null) {
      return const <SearchResult>[];
    }

    // Prepare the list of files that reference the name.
    var files = await _driver.getFilesReferencingName(name);

    // Check the index of every file that references the element name.
    List<SearchResult> results = [];
    for (var file in files) {
      if (searchedFiles.add(file.path, this)) {
        var index = await _driver.getIndex(file.path);
        if (index != null) {
          _IndexRequest request = _IndexRequest(index);
          var fileResults = await request.getUnresolvedMemberReferences(
            name,
            const {
              IndexRelationKind.IS_READ_BY: SearchResultKind.READ,
              IndexRelationKind.IS_WRITTEN_BY: SearchResultKind.WRITE,
              IndexRelationKind.IS_READ_WRITTEN_BY: SearchResultKind.READ_WRITE,
              IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION,
            },
            () => _getUnitElement(file.path),
          );
          results.addAll(fileResults);
        }
      }
    }

    return results;
  }

  Future<void> _addResults(
    List<SearchResult> results,
    Element element,
    SearchedFiles searchedFiles,
    Map<IndexRelationKind, SearchResultKind> relationToResultKind, {
    List<FileState>? filesToCheck,
  }) async {
    // Prepare the element name.
    String name = element.displayName;
    var externalElement = element;
    if (externalElement case FormalParameterElement(:var enclosingElement2?)) {
      externalElement = enclosingElement2;
    }
    if (externalElement is ConstructorElement) {
      name = externalElement.enclosingElement2.displayName;
    }

    var elementPath = element.firstFragment.libraryFragment?.source.fullName;
    if (elementPath == null) {
      return;
    }

    var elementFile = _driver.fsState.getExistingFromPath(elementPath);
    if (elementFile == null) {
      return;
    }

    // Prepare the list of files that reference the element name.
    var files = <FileState>[];
    if (name.startsWith('_')) {
      String libraryPath = element.library2!.firstFragment.source.fullName;
      if (searchedFiles.add(libraryPath, this)) {
        var libraryFile = _driver.fsState.getFileForPath(libraryPath);
        var libraryKind = libraryFile.kind;
        if (libraryKind is LibraryFileKind) {
          for (var file in libraryKind.files) {
            if (file == elementFile || file.referencedNames.contains(name)) {
              files.add(file);
            }
          }
        }
      }
    } else {
      if (filesToCheck != null) {
        for (FileState file in filesToCheck) {
          if (file.referencedNames.contains(name)) {
            files.add(file);
          }
        }
      } else {
        files = await _driver.getFilesReferencingName(name);
      }
      // Add all files of the library.
      if (elementFile.kind.library case var library?) {
        for (var file in library.files) {
          if (searchedFiles.add(file.path, this)) {
            if (!files.contains(file)) {
              files.add(file);
            }
          }
        }
      }
    }

    // Check the index of every file that references the element name.
    for (var file in files) {
      if (searchedFiles.add(file.path, this)) {
        await _addResultsInFile(
          results,
          element,
          relationToResultKind,
          file.path,
        );
      }
    }
  }

  /// Add results for [element] usage in the given [file].
  Future<void> _addResultsInFile(
    List<SearchResult> results,
    Element element,
    Map<IndexRelationKind, SearchResultKind> relationToResultKind,
    String file,
  ) async {
    var index = await _driver.getIndex(file);
    if (index != null) {
      _IndexRequest request = _IndexRequest(index);
      int elementId = request.findElementId(element);
      if (elementId != -1) {
        List<SearchResult> fileResults = await request.getRelations(
          elementId,
          relationToResultKind,
          () => _getUnitElement(file),
        );
        results.addAll(fileResults);
      }
    }
  }

  Future<LibraryFragmentImpl?> _getUnitElement(String file) async {
    var result = await _driver.getUnitElement(file);
    return result is UnitElementResultImpl ? result.fragment : null;
  }

  Future<List<SearchResult>> _searchReferences(
    Element element,
    SearchedFiles searchedFiles,
  ) async {
    List<SearchResult> results = <SearchResult>[];
    await _addResults(results, element, searchedFiles, const {
      IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
    });
    return results;
  }

  Future<List<SearchResult>> _searchReferences_CompilationUnit(
    LibraryFragmentImpl element,
  ) async {
    String path = element.source.fullName;

    var file = _driver.resourceProvider.getFile(path);
    var fileState = _driver.fsState.getExisting(file);

    // If the file is not known, then it is not referenced.
    if (fileState == null) {
      return const <SearchResult>[];
    }

    // Check files that reference the given file.
    var results = <SearchResult>[];
    for (var reference in fileState.referencingFiles) {
      var index = await _driver.getIndex(reference.path);
      if (index != null) {
        var targetId = index.getLibraryFragmentId(element);
        for (var i = 0; i < index.libFragmentRefTargets.length; i++) {
          if (index.libFragmentRefTargets[i] == targetId) {
            var refUnit = await _getUnitElement(reference.path);
            results.add(
              SearchResult._(
                refUnit!,
                SearchResultKind.REFERENCE,
                index.libFragmentRefUriOffsets[i],
                index.libFragmentRefUriLengths[i],
                true,
                true,
              ),
            );
          }
        }
      }
    }
    return results;
  }

  Future<List<SearchResult>> _searchReferences_Constructor(
    ConstructorElement element,
    SearchedFiles searchedFiles,
  ) async {
    List<SearchResult> results = <SearchResult>[];
    await _addResults(results, element, searchedFiles, const {
      IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION,
      IndexRelationKind.IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS:
          SearchResultKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
      IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
      IndexRelationKind.IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF:
          SearchResultKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF,
    });
    return results;
  }

  Future<List<SearchResult>> _searchReferences_Field(
    PropertyInducingElement field,
    SearchedFiles searchedFiles,
  ) async {
    List<SearchResult> results = <SearchResult>[];
    var getter = field.getter2;
    var setter = field.setter2;
    if (!field.isSynthetic) {
      await _addResults(results, field, searchedFiles, const {
        IndexRelationKind.IS_WRITTEN_BY: SearchResultKind.WRITE,
        IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
      });
    }
    if (getter != null) {
      await _addResults(results, getter, searchedFiles, const {
        IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.READ,
        IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION,
      });
    }
    if (setter != null) {
      await _addResults(results, setter, searchedFiles, const {
        IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.WRITE,
      });
    }
    return results;
  }

  Future<List<SearchResult>> _searchReferences_Function(
    Element element,
    SearchedFiles searchedFiles,
  ) async {
    List<SearchResult> results = <SearchResult>[];
    await _addResults(results, element.baseElement, searchedFiles, const {
      IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
      IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION,
    });
    return results;
  }

  Future<List<SearchResult>> _searchReferences_Getter(
    GetterElement getter,
    SearchedFiles searchedFiles,
  ) async {
    List<SearchResult> results = <SearchResult>[];
    await _addResults(results, getter, searchedFiles, const {
      IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
      IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION,
    });
    return results;
  }

  Future<List<SearchResult>> _searchReferences_Import(
    LibraryImportImpl element,
    SearchedFiles searchedFiles,
  ) async {
    String path = element.libraryFragment.source.fullName;
    if (!searchedFiles.add(path, this)) {
      return const <SearchResult>[];
    }

    List<SearchResult> results = <SearchResult>[];
    LibraryElementImpl libraryElement = element.libraryFragment.element;
    for (var unitElement in libraryElement.units) {
      String unitPath = unitElement.source.fullName;
      var unitResult = await _driver.getResolvedUnit(unitPath);
      if (unitResult is ResolvedUnitResult) {
        var visitor = ImportElementReferencesVisitor(element, unitElement);
        unitResult.unit.accept(visitor);
        results.addAll(visitor.results);
      }
    }
    return results;
  }

  Future<List<SearchResult>> _searchReferences_Library(
    LibraryElementImpl element,
    SearchedFiles searchedFiles,
  ) async {
    String path = element.source.fullName;
    if (!searchedFiles.add(path, this)) {
      return const <SearchResult>[];
    }

    List<SearchResult> results = <SearchResult>[];
    for (var unitElement in element.units) {
      String unitPath = unitElement.source.fullName;
      var unitResult = await _driver.getResolvedUnit(unitPath);
      if (unitResult is ResolvedUnitResultImpl) {
        var unit = unitResult.unit;
        for (var directive in unit.directives) {
          if (directive is PartOfDirectiveImpl) {
            var targetEntity = directive.libraryName ?? directive.uri;
            results.add(
              SearchResult._(
                unit.declaredFragment!,
                SearchResultKind.REFERENCE,
                targetEntity!.offset,
                targetEntity.length,
                true,
                false,
              ),
            );
          }
        }
      }
    }
    return results;
  }

  Future<List<SearchResult>> _searchReferences_Local(
    Element element,
    bool Function(AstNode n) isRootNode,
    SearchedFiles searchedFiles,
  ) async {
    String? path = element.firstFragment.libraryFragment?.source.fullName;
    if (path == null || !searchedFiles.add(path, this)) {
      return const <SearchResult>[];
    }

    // Prepare the unit.
    var unitResult = await _driver.getResolvedUnit(path);
    if (unitResult is! ResolvedUnitResultImpl) {
      return const <SearchResult>[];
    }
    var unit = unitResult.unit;

    var node = unit.nodeCovering(offset: element.firstFragment.nameOffset2!);
    if (node == null) {
      return const <SearchResult>[];
    }

    // Prepare the enclosing node.
    var enclosingNode = node.thisOrAncestorMatching(
      (node) =>
          isRootNode(node) || node is ClassMember || node is CompilationUnit,
    );
    assert(
      enclosingNode != null && enclosingNode is! CompilationUnit,
      'Did not find enclosing node for local "${element.name3}". '
      'Perhaps the isRootNode function is missing a condition to locate the '
      'outermost node where this element is in scope?',
    );
    if (enclosingNode == null) {
      return const <SearchResult>[];
    }

    // Find the matches.
    var visitor = _LocalReferencesVisitor({element}, unit.declaredFragment!);
    enclosingNode.accept(visitor);
    return visitor.results;
  }

  Future<List<SearchResult>> _searchReferences_Parameter(
    FormalParameterElement parameter,
    SearchedFiles searchedFiles,
  ) async {
    List<SearchResult> results = <SearchResult>[];
    results.addAll(
      await _searchReferences_Local(parameter, (AstNode node) {
        var parent = node.parent;
        return parent is ClassDeclaration || parent is CompilationUnit;
      }, searchedFiles),
    );
    if (parameter.isNamed ||
        parameter.isOptionalPositional ||
        parameter.enclosingElement2 is ConstructorElement) {
      results.addAll(await _searchReferences(parameter, searchedFiles));
    }
    return results;
  }

  Future<List<SearchResult>> _searchReferences_PatternVariable(
    PatternVariableElementImpl2 element,
    SearchedFiles searchedFiles,
  ) async {
    String path = element.firstFragment.libraryFragment.source.fullName;
    if (!searchedFiles.add(path, this)) {
      return const <SearchResult>[];
    }

    var rootVariable = element.rootVariable;
    var transitiveVariables =
        rootVariable is JoinPatternVariableElementImpl2
            ? rootVariable.transitiveVariables
            : [rootVariable];

    // Prepare a binding element for the variable.
    var bindElement =
        transitiveVariables
            .whereType<BindPatternVariableElementImpl2>()
            .firstOrNull;
    if (bindElement == null) {
      return const <SearchResult>[];
    }

    // Prepare the root node for search.
    var rootNode = bindElement.node.thisOrAncestorMatching(
      (node) => node is SwitchExpression || node is Block,
    );
    if (rootNode == null) {
      return const <SearchResult>[];
    }

    // Find the matches.
    var visitor = _LocalReferencesVisitor(
      transitiveVariables.toSet(),
      bindElement.firstFragment.libraryFragment,
    );
    rootNode.accept(visitor);
    return visitor.results;
  }

  Future<List<SearchResult>> _searchReferences_Prefix(
    PrefixElementImpl2 element,
    SearchedFiles searchedFiles,
  ) async {
    String path = element.firstFragment.libraryFragment.source.fullName;
    if (!searchedFiles.add(path, this)) {
      return const <SearchResult>[];
    }

    List<SearchResult> results = <SearchResult>[];
    var libraryElement = element.library2;
    for (var unitElement in libraryElement.units) {
      String unitPath = unitElement.source.fullName;
      var unitResult = await _driver.getResolvedUnit(unitPath);
      if (unitResult is ResolvedUnitResult) {
        var visitor = _LocalReferencesVisitor({element}, unitElement);
        unitResult.unit.accept(visitor);
        results.addAll(visitor.results);
      }
    }
    return results;
  }
}

/// Container that keeps track of file owners.
class SearchedFiles {
  final Map<String, Search> pathOwners = {};
  final Map<Uri, Search> uriOwners = {};

  bool add(String path, Search search) {
    var fsState = search._driver.fsState;
    var fileState = fsState.getExistingFromPath(path);
    if (fileState == null) {
      return false;
    }

    var pathOwner = pathOwners[path];
    var uriOwner = uriOwners[fileState.uri];
    if (pathOwner == null && uriOwner == null) {
      pathOwners[path] = search;
      uriOwners[fileState.uri] = search;
      return true;
    }
    return identical(pathOwner, search) && identical(uriOwner, search);
  }

  void ownAnalyzed(Search search) {
    for (var path in search._driver.addedFiles) {
      if (path.endsWith('.dart')) {
        add(path, search);
      }
    }
  }

  void ownKnown(Search search) {
    for (var file in search._driver.knownFiles) {
      var path = file.path;
      if (path.endsWith('.dart')) {
        add(path, search);
      }
    }
  }
}

/// A single search result.
class SearchResult {
  /// The deep most fragment that contains this result.
  final Fragment enclosingFragment;

  /// The kind of the element usage.
  final SearchResultKind kind;

  /// The offset relative to the beginning of the containing file.
  final int offset;

  /// The length of the usage in the containing file context.
  final int length;

  /// Whether a field or a method is using with a qualifier.
  final bool isResolved;

  /// Whether the result is a resolved reference to the element.
  final bool isQualified;

  SearchResult._(
    this.enclosingFragment,
    this.kind,
    this.offset,
    this.length,
    this.isResolved,
    this.isQualified,
  );

  @override
  String toString() {
    StringBuffer buffer = StringBuffer();
    buffer.write("SearchResult(kind=");
    buffer.write(kind);
    buffer.write(", enclosingFragment=");
    buffer.write(enclosingFragment);
    buffer.write(", offset=");
    buffer.write(offset);
    buffer.write(", length=");
    buffer.write(length);
    buffer.write(", isResolved=");
    buffer.write(isResolved);
    buffer.write(", isQualified=");
    buffer.write(isQualified);
    buffer.write(")");
    return buffer.toString();
  }
}

/// The kind of reference in a [SearchResult].
enum SearchResultKind {
  READ,
  READ_WRITE,
  WRITE,
  INVOCATION,
  INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
  REFERENCE,
  REFERENCE_BY_CONSTRUCTOR_TEAR_OFF,
  REFERENCE_IN_EXTENDS_CLAUSE,
  REFERENCE_IN_WITH_CLAUSE,
  REFERENCE_IN_ON_CLAUSE,
  REFERENCE_IN_IMPLEMENTS_CLAUSE,
}

/// A single subtype of a type.
class SubtypeResult {
  /// The URI of the library.
  final String libraryUri;

  /// The identifier of the subtype.
  final String id;

  /// The name of the subtype.
  final String name;

  /// The names of instance members declared in the class.
  final List<String> members;

  SubtypeResult(this.libraryUri, this.id, this.name, this.members);

  @override
  String toString() => id;
}

class WorkspaceSymbols {
  final List<Declaration> declarations = [];
  final List<String> files = [];
  final Map<String, int> _pathToIndex = {};

  /// Whether this search was marked cancelled before it completed.
  bool cancelled = false;

  bool hasMoreDeclarationsThan(int? maxResults) {
    return maxResults != null && declarations.length >= maxResults;
  }

  int _getPathIndex(String path) {
    var index = _pathToIndex[path];
    if (index == null) {
      index = files.length;
      files.add(path);
      _pathToIndex[path] = index;
    }
    return index;
  }
}

/// Searches through [fileEntries] for declarations.
class _FindDeclarations {
  final List<MapEntry<Uri, AnalysisDriver>> fileEntries;
  final WorkspaceSymbols result;
  final int? maxResults;
  final String pattern;
  final FuzzyMatcher matcher;
  final String? onlyForFile;
  final OperationPerformanceImpl performance;

  _FindDeclarations(
    this.fileEntries,
    this.result,
    this.pattern,
    this.matcher,
    this.maxResults, {
    this.onlyForFile,
    required this.performance,
  });

  /// Add matching declarations to the [result].
  Future<void> compute(CancellationToken? cancellationToken) async {
    if (result.hasMoreDeclarationsThan(maxResults)) {
      return;
    }

    if (cancellationToken != null &&
        cancellationToken.isCancellationRequested) {
      result.cancelled = true;
      return;
    }

    var filesProcessed = 0;
    try {
      for (var entry in fileEntries) {
        var uri = entry.key;
        var analysisDriver = entry.value;

        var libraryElement = await performance.runAsync('getLibraryByUri', (
          performance,
        ) async {
          var result = await analysisDriver.getLibraryByUri('$uri');
          if (result is LibraryElementResultImpl) {
            return result.element2;
          }
          return null;
        });

        if (libraryElement != null) {
          // Check if there is any name that could match the pattern.
          var match = libraryElement.nameUnion.contains(pattern);
          if (!match) {
            continue;
          }

          var filePath = libraryElement.firstFragment.source.fullName;
          if (onlyForFile != null && filePath != onlyForFile) {
            continue;
          }

          performance.run('libraryDeclarations', (performance) {
            var finder = _FindLibraryDeclarations(
              libraryElement.firstFragment,
              result,
              maxResults,
              matcher,
              result.declarations.add,
            );
            finder.compute(cancellationToken);
          });
        }

        // Periodically yield and check cancellation token.
        if (cancellationToken != null && (filesProcessed++) % 20 == 0) {
          await null; // allow cancellation requests to be processed.
          if (cancellationToken.isCancellationRequested) {
            result.cancelled = true;
            return;
          }
        }
      }
    } on _MaxNumberOfDeclarationsError {
      return;
    }
  }
}

class _FindLibraryDeclarations {
  final LibraryElementImpl library;
  final WorkspaceSymbols result;
  final int? maxResults;
  final FuzzyMatcher matcher;
  final void Function(Declaration) collect;

  _FindLibraryDeclarations(
    LibraryFragmentImpl unit,
    this.result,
    this.maxResults,
    this.matcher,
    this.collect,
  ) : library = unit.element;

  void compute(CancellationToken? cancellationToken) {
    if (result.hasMoreDeclarationsThan(maxResults)) {
      return;
    }

    _addClasses(library.classes);
    _addGetters(library.getters);
    _addClasses(library.enums);
    _addClasses(library.mixins);
    _addExtensions(library.extensions);
    _addClasses(library.extensionTypes);
    _addSetters(library.setters);
    _addFunctions(library.topLevelFunctions);
    _addVariables(library.topLevelVariables);
    _addTypeAliases(library.typeAliases);
  }

  void _addClasses(List<InterfaceElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      _addDeclaration(element, element.name3!);
      _addGetters(element.getters2);
      _addConstructors(element.constructors2);
      _addFields(element.fields2);
      _addMethods(element.methods2);
      _addSetters(element.setters2);
    }
  }

  void _addConstructors(List<ConstructorElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      if (!element.isSynthetic) {
        _addDeclaration(element, element.name3!);
      }
    }
  }

  void _addDeclaration(Element element, String name) {
    if (result.hasMoreDeclarationsThan(maxResults)) {
      throw const _MaxNumberOfDeclarationsError();
    }

    if (matcher.score(name) < 0) {
      return;
    }

    var enclosing = element.enclosingElement2;

    String? className;
    String? mixinName;
    if (enclosing is EnumElement) {
      // skip
    } else if (enclosing is MixinElement) {
      mixinName = enclosing.name3;
    } else if (enclosing is InterfaceElement) {
      className = enclosing.name3;
    }

    var kind = _getSearchElementKind(element);
    if (kind == null) {
      return;
    }

    String? parameters;
    if (element is ExecutableElement) {
      var displayString = element.displayString2();
      var parameterIndex = displayString.indexOf('(');
      if (parameterIndex > 0) {
        parameters = displayString.substring(parameterIndex);
      }
    }

    var firstFragment = element.firstFragment;
    var libraryFragment = firstFragment.libraryFragment;
    if (libraryFragment == null) {
      return;
    }

    var filePath = libraryFragment.source.fullName;

    var locationOffset = firstFragment.nameOffset2;
    if (locationOffset == null) {
      if (firstFragment is ConstructorFragment) {
        locationOffset = firstFragment.typeNameOffset;
      }
    }

    if (locationOffset == null) {
      return;
    }
    var lineInfo = libraryFragment.lineInfo;
    var locationStart = lineInfo.getLocation(locationOffset);

    var fragmentImpl =
        firstFragment as FragmentImpl; // to access codeOffset/codeLength

    collect(
      Declaration(
        result._getPathIndex(filePath),
        lineInfo,
        name,
        kind,
        locationOffset,
        locationStart.lineNumber,
        locationStart.columnNumber,
        fragmentImpl.codeOffset ?? 0,
        fragmentImpl.codeLength ?? 0,
        className,
        mixinName,
        parameters,
      ),
    );
  }

  void _addExtensions(List<ExtensionElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      var name = element.name3;
      if (name != null) {
        _addDeclaration(element, name);
      }
      _addFields(element.fields2);
      _addGetters(element.getters2);
      _addMethods(element.methods2);
      _addSetters(element.setters2);
    }
  }

  void _addFields(List<FieldElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      if (!element.isSynthetic) {
        _addDeclaration(element, element.name3!);
      }
    }
  }

  void _addFunctions(List<TopLevelFunctionElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      _addDeclaration(element, element.name3!);
    }
  }

  void _addGetters(List<GetterElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      if (!element.isSynthetic) {
        _addDeclaration(element, element.displayName);
      }
    }
  }

  void _addMethods(List<MethodElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      _addDeclaration(element, element.name3!);
    }
  }

  void _addSetters(List<SetterElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      if (!element.isSynthetic) {
        _addDeclaration(element, element.displayName);
      }
    }
  }

  void _addTypeAliases(List<TypeAliasElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      _addDeclaration(element, element.name3!);
    }
  }

  void _addVariables(List<TopLevelVariableElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      if (!element.isSynthetic) {
        _addDeclaration(element, element.name3!);
      }
    }
  }
}

class _IndexRequest {
  final AnalysisDriverUnitIndex index;

  _IndexRequest(this.index);

  void addSubtypes(
    String superIdString,
    List<SubtypeResult> results,
    FileState file,
  ) {
    var superId = index.getStringId(superIdString);
    if (superId == -1) {
      return;
    }

    var superIndex = _findFirstOccurrence(index.supertypes, superId);
    if (superIndex == -1) {
      return;
    }

    var library = file.kind.library;
    if (library == null) {
      return;
    }

    for (
      ;
      superIndex < index.supertypes.length &&
          index.supertypes[superIndex] == superId;
      superIndex++
    ) {
      var subtype = index.subtypes[superIndex];
      var name = index.strings[subtype.name];
      var subId = '${library.file.uriStr};${file.uriStr};$name';
      results.add(
        SubtypeResult(
          library.file.uriStr,
          subId,
          name,
          subtype.members.map((m) => index.strings[m]).toList(),
        ),
      );
    }
  }

  /// Return the [element]'s identifier in the [index] or `-1` if the
  /// [element] is not referenced in the [index].
  int findElementId(Element element) {
    IndexElementInfo info = IndexElementInfo(element);
    element = info.element;
    // Find the id of the element's unit.
    int unitId = getUnitId(element);
    if (unitId == -1) {
      return -1;
    }
    // Prepare information about the element.
    var components = ElementNameComponents(element);
    int unitMemberId = index.getStringId(components.unitMemberName);
    if (unitMemberId == -1) {
      return -1;
    }
    int classMemberId = index.getStringId(components.classMemberName);
    if (classMemberId == -1) {
      return -1;
    }
    int parameterId = index.getStringId(components.parameterName);
    if (parameterId == -1) {
      return -1;
    }

    // Try to find the element id using classMemberId, parameterId, and kind.
    int elementId = _findFirstOccurrence(
      index.elementNameUnitMemberIds,
      unitMemberId,
    );
    if (elementId == -1) {
      return -1;
    }
    for (
      ;
      elementId < index.elementNameUnitMemberIds.length &&
          index.elementNameUnitMemberIds[elementId] == unitMemberId;
      elementId++
    ) {
      if (index.elementUnits[elementId] == unitId &&
          index.elementNameClassMemberIds[elementId] == classMemberId &&
          index.elementNameParameterIds[elementId] == parameterId &&
          index.elementKinds[elementId] == info.kind) {
        return elementId;
      }
    }
    return -1;
  }

  /// Return a list of results where an element with the given [elementId] has
  /// a relation with the kind from [relationToResultKind].
  ///
  /// The function [getEnclosingUnitElement] is used to lazily compute the
  /// enclosing [LibraryFragmentImpl] if there is a relation of an
  /// interesting kind.
  Future<List<SearchResult>> getRelations(
    int elementId,
    Map<IndexRelationKind, SearchResultKind> relationToResultKind,
    Future<LibraryFragmentImpl?> Function() getEnclosingUnitElement,
  ) async {
    // Find the first usage of the element.
    int i = _findFirstOccurrence(index.usedElements, elementId);
    if (i == -1) {
      return const <SearchResult>[];
    }
    // Create locations for every usage of the element.
    List<SearchResult> results = <SearchResult>[];
    LibraryFragmentImpl? enclosingUnitElement;
    for (
      ;
      i < index.usedElements.length && index.usedElements[i] == elementId;
      i++
    ) {
      IndexRelationKind relationKind = index.usedElementKinds[i];
      SearchResultKind? resultKind = relationToResultKind[relationKind];
      if (resultKind != null) {
        int offset = index.usedElementOffsets[i];
        enclosingUnitElement ??= await getEnclosingUnitElement();
        if (enclosingUnitElement != null) {
          var enclosingFragment = _getEnclosingFragment(
            enclosingUnitElement,
            offset,
          );
          results.add(
            SearchResult._(
              enclosingFragment,
              resultKind,
              offset,
              index.usedElementLengths[i],
              true,
              index.usedElementIsQualifiedFlags[i],
            ),
          );
        }
      }
    }
    return results;
  }

  /// Return the identifier of the [CompilationUnitElementIml] containing the
  /// [element] in the [index] or `-1` if not found.
  int getUnitId(Element element) {
    var unitElement = getUnitElement(element);
    return index.getLibraryFragmentId(unitElement);
  }

  /// Return a list of results where a class members with the given [name] is
  /// referenced with a qualifier, but is not resolved.
  Future<List<SearchResult>> getUnresolvedMemberReferences(
    String name,
    Map<IndexRelationKind, SearchResultKind> relationToResultKind,
    Future<LibraryFragmentImpl?> Function() getEnclosingUnitElement,
  ) async {
    // Find the name identifier.
    int nameId = index.getStringId(name);
    if (nameId == -1) {
      return const <SearchResult>[];
    }

    // Find the first usage of the name.
    int i = _findFirstOccurrence(index.usedNames, nameId);
    if (i == -1) {
      return const <SearchResult>[];
    }

    // Create results for every usage of the name.
    List<SearchResult> results = <SearchResult>[];
    LibraryFragmentImpl? enclosingUnitElement;
    for (; i < index.usedNames.length && index.usedNames[i] == nameId; i++) {
      IndexRelationKind relationKind = index.usedNameKinds[i];
      SearchResultKind? resultKind = relationToResultKind[relationKind];
      if (resultKind != null) {
        int offset = index.usedNameOffsets[i];
        enclosingUnitElement ??= await getEnclosingUnitElement();
        if (enclosingUnitElement != null) {
          var enclosingFragment = _getEnclosingFragment(
            enclosingUnitElement,
            offset,
          );
          results.add(
            SearchResult._(
              enclosingFragment,
              resultKind,
              offset,
              name.length,
              false,
              index.usedNameIsQualifiedFlags[i],
            ),
          );
        }
      }
    }

    return results;
  }

  /// Return the index of the first occurrence of the [value] in the
  /// [sortedList], or `-1` if the [value] is not in the list.
  int _findFirstOccurrence(List<int> sortedList, int value) {
    // Find an occurrence.
    int i = binarySearch(sortedList, value);
    if (i == -1) {
      return -1;
    }
    // Find the first occurrence.
    while (i > 0 && sortedList[i - 1] == value) {
      i--;
    }
    return i;
  }
}

/// Visitor that adds [SearchResult]s for local elements of a block, method,
/// class or a library - labels, local functions, local variables and
/// parameters, type parameters, import prefixes.
class _LocalReferencesVisitor extends RecursiveAstVisitor<void> {
  final List<SearchResult> results = <SearchResult>[];

  final Set<Element> elements;
  final LibraryFragmentImpl enclosingLibraryFragment;

  _LocalReferencesVisitor(this.elements, this.enclosingLibraryFragment);

  @override
  void visitAssignedVariablePattern(AssignedVariablePattern node) {
    if (elements.contains(node.element2)) {
      _addResult(node, SearchResultKind.WRITE);
    }

    super.visitAssignedVariablePattern(node);
  }

  @override
  void visitExtensionOverride(ExtensionOverride node) {
    node.importPrefix?.accept(this);
    node.typeArguments?.accept(this);
    node.argumentList.accept(this);
  }

  @override
  void visitImportPrefixReference(ImportPrefixReference node) {
    var element = node.element2;
    if (elements.contains(element)) {
      _addResult(node.name, SearchResultKind.REFERENCE);
    }
  }

  @override
  void visitNamedType(NamedType node) {
    var element = node.element2;
    if (elements.contains(element)) {
      _addResult(node.name2, SearchResultKind.REFERENCE);
    }

    node.importPrefix?.accept(this);
    node.typeArguments?.accept(this);
  }

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    if (node.inDeclarationContext()) {
      return;
    }
    var element = node.element;
    if (elements.contains(element)) {
      var parent = node.parent;
      SearchResultKind kind = SearchResultKind.REFERENCE;
      if (element is LocalFunctionElement) {
        if (parent is MethodInvocation && parent.methodName == node) {
          kind = SearchResultKind.INVOCATION;
        }
      } else if (element is VariableElement) {
        bool isGet = node.inGetterContext();
        bool isSet = node.inSetterContext();
        if (isGet && isSet) {
          kind = SearchResultKind.READ_WRITE;
        } else if (isGet) {
          if (parent is MethodInvocation && parent.methodName == node) {
            kind = SearchResultKind.INVOCATION;
          } else {
            kind = SearchResultKind.READ;
          }
        } else if (isSet) {
          kind = SearchResultKind.WRITE;
        }
      }
      _addResult(node, kind);
    }
  }

  void _addResult(SyntacticEntity entity, SearchResultKind kind) {
    bool isQualified = entity is AstNode ? entity.parent is Label : false;
    var enclosingFragment = _getEnclosingFragment(
      enclosingLibraryFragment,
      entity.offset,
    );
    results.add(
      SearchResult._(
        enclosingFragment,
        kind,
        entity.offset,
        entity.length,
        true,
        isQualified,
      ),
    );
  }
}

/// The marker class that is thrown to stop adding declarations.
class _MaxNumberOfDeclarationsError {
  const _MaxNumberOfDeclarationsError();
}
