// 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/ast.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/dart/element/visitor.dart';
import 'package:analyzer/source/line_info.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/extensions.dart';
import 'package:analyzer/src/dart/ast/utilities.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';

Element _getEnclosingElement(CompilationUnitElement unitElement, int offset) {
  var finder = _ContainingElementFinder(offset);
  unitElement.accept(finder);
  var element = finder.containingElement;
  if (element == null) {
    throw StateError(
      'No containing element in ${unitElement.source.fullName} at $offset',
    );
  }
  return element;
}

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 FunctionElement) {
    return DeclarationKind.FUNCTION;
  }

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

  if (element is PropertyAccessorElement) {
    return element.isGetter ? DeclarationKind.GETTER : 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 [importElement].
class ImportElementReferencesVisitor extends RecursiveAstVisitor<void> {
  final List<SearchResult> results = <SearchResult>[];

  final LibraryImportElement importElement;
  final CompilationUnitElement enclosingUnitElement;

  late final Set<Element> importedElements;

  ImportElementReferencesVisitor(
      LibraryImportElement element, this.enclosingUnitElement)
      : importElement = element {
    importedElements = element.namespace.definedNames.values.toSet();
  }

  @override
  void visitExportDirective(ExportDirective node) {}

  @override
  void visitImportDirective(ImportDirective node) {}

  @override
  void visitNamedType(NamedType node) {
    if (importedElements.contains(node.element)) {
      var importElementPrefix = importElement.prefix;
      var importPrefix = node.importPrefix;
      if (importElementPrefix == null) {
        if (importPrefix == null) {
          _addResult(node.offset, 0);
        }
      } else {
        if (importPrefix != null &&
            importPrefix.element == importElementPrefix.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 (importElement.prefix != null) {
      if (node.staticElement == importElement.prefix?.element) {
        var parent = node.parent;
        if (parent is PrefixedIdentifier && parent.prefix == node) {
          var element = parent.writeOrReadElement?.declaration;
          if (importedElements.contains(element)) {
            _addResultForPrefix(node, parent.identifier);
          }
        }
        if (parent is MethodInvocation && parent.target == node) {
          var element = parent.methodName.staticElement?.declaration;
          if (importedElements.contains(element)) {
            _addResultForPrefix(node, parent.methodName);
          }
        }
      }
    } else {
      var element = node.writeOrReadElement?.declaration;
      if (importedElements.contains(element)) {
        _addResult(node.offset, 0);
      }
    }
  }

  void _addResult(int offset, int length) {
    Element enclosingElement =
        _getEnclosingElement(enclosingUnitElement, offset);
    results.add(SearchResult._(enclosingElement, SearchResultKind.REFERENCE,
        offset, length, true, false));
  }

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

/// 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 {
    List<Element> elements = <Element>[];

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

    void addElements(InterfaceElement element) {
      element.accessors.forEach(addElement);
      element.fields.forEach(addElement);
      element.methods.forEach(addElement);
    }

    var files = await _driver.getFilesDefiningClassMemberName(name);
    for (var file in files) {
      if (searchedFiles.add(file.path, this)) {
        var unitResult = await _driver.getUnitElement(file.path);
        if (unitResult is UnitElementResult) {
          unitResult.element.classes.forEach(addElements);
          unitResult.element.enums.forEach(addElements);
          unitResult.element.extensionTypes.forEach(addElements);
          unitResult.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);
        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 PropertyAccessorElement && element.isSetter ||
        element is TypeAliasElement) {
      return _searchReferences(element, searchedFiles);
    } else if (element is ConstructorElement) {
      return await _searchReferences_Constructor(element, searchedFiles);
    } else if (element is CompilationUnitElement) {
      return _searchReferences_CompilationUnit(element);
    } else if (element is PropertyAccessorElement && element.isGetter) {
      return _searchReferences_Getter(element, searchedFiles);
    } else if (element is PropertyInducingElement) {
      return _searchReferences_Field(element, searchedFiles);
    } else if (kind == ElementKind.FUNCTION || kind == ElementKind.METHOD) {
      if (element.enclosingElement3 is ExecutableElement) {
        return _searchReferences_Local(
            element, (n) => n is Block, searchedFiles);
      }
      return _searchReferences_Function(element, searchedFiles);
    } else if (element is LibraryImportElement) {
      return _searchReferences_Import(element, searchedFiles);
    } else if (element is PatternVariableElementImpl) {
      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 LibraryElement) {
      return _searchReferences_Library(element, searchedFiles);
    } else if (element is ParameterElement) {
      return _searchReferences_Parameter(element, searchedFiles);
    } else if (element is PrefixElement) {
      return _searchReferences_Prefix(element, searchedFiles);
    } else if (element is TypeParameterElement) {
      return _searchReferences_Local(
          element, (n) => n.parent is CompilationUnit, searchedFiles);
    }
    return const <SearchResult>[];
  }

  /// 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 {
    String name;
    String id;
    if (type != null) {
      name = type.name;
      id = '${type.librarySource.uri};${type.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 {
    List<Element> 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 unitResult = await _driver.getUnitElement(file.path);
      if (unitResult is UnitElementResult) {
        CompilationUnitElement unitElement = unitResult.element;
        unitElement.accessors.forEach(addElement);
        unitElement.classes.forEach(addElement);
        unitElement.enums.forEach(addElement);
        unitElement.extensions.forEach(addElement);
        unitElement.extensionTypes.forEach(addElement);
        unitElement.functions.forEach(addElement);
        unitElement.mixins.forEach(addElement);
        unitElement.topLevelVariables.forEach(addElement);
        unitElement.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;
    if (element is ConstructorElement) {
      name = element.enclosingElement3.displayName;
    }

    var elementPath = element.source!.fullName;
    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.library!.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<CompilationUnitElement?> _getUnitElement(String file) async {
    var result = await _driver.getUnitElement(file);
    return result is UnitElementResult ? result.element : 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(
      CompilationUnitElement 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.
    List<SearchResult> results = <SearchResult>[];
    for (var reference in fileState.referencingFiles) {
      await _addResultsInFile(
        results,
        element,
        const {
          IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
        },
        reference.path,
      );
    }
    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>[];
    PropertyAccessorElement? getter = field.getter;
    PropertyAccessorElement? setter = field.setter;
    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.declaration!, searchedFiles, const {
      IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
      IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION
    });
    return results;
  }

  Future<List<SearchResult>> _searchReferences_Getter(
      PropertyAccessorElement 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(
      LibraryImportElement element, SearchedFiles searchedFiles) async {
    String path = element.source.fullName;
    if (!searchedFiles.add(path, this)) {
      return const <SearchResult>[];
    }

    List<SearchResult> results = <SearchResult>[];
    LibraryElement libraryElement = element.library;
    for (CompilationUnitElement 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(
      LibraryElement element, SearchedFiles searchedFiles) async {
    String path = element.source.fullName;
    if (!searchedFiles.add(path, this)) {
      return const <SearchResult>[];
    }

    List<SearchResult> results = <SearchResult>[];
    for (CompilationUnitElement unitElement in element.units) {
      String unitPath = unitElement.source.fullName;
      var unitResult = await _driver.getResolvedUnit(unitPath);
      if (unitResult is ResolvedUnitResult) {
        CompilationUnit unit = unitResult.unit;
        for (Directive directive in unit.directives) {
          if (directive is PartOfDirective && directive.element == element) {
            var targetEntity = directive.libraryName ?? directive.uri;
            results.add(
              SearchResult._(
                unit.declaredElement!,
                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.source!.fullName;
    if (!searchedFiles.add(path, this)) {
      return const <SearchResult>[];
    }

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

    // Prepare the node.
    var node = NodeLocator(element.nameOffset).searchWithin(unit);
    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.name}". '
      '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.declaredElement!);
    enclosingNode.accept(visitor);
    return visitor.results;
  }

  Future<List<SearchResult>> _searchReferences_Parameter(
      ParameterElement 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.enclosingElement3 is ConstructorElement) {
      results.addAll(await _searchReferences(parameter, searchedFiles));
    }
    return results;
  }

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

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

    // Prepare a binding element for the variable.
    var bindElement = transitiveVariables
        .whereType<BindPatternVariableElementImpl>()
        .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.enclosingUnit,
    );
    rootNode.accept(visitor);
    return visitor.results;
  }

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

    List<SearchResult> results = <SearchResult>[];
    LibraryElement libraryElement = element.library;
    for (CompilationUnitElement 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 element that contains this result.
  final Element enclosingElement;

  /// 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.enclosingElement, 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(", enclosingElement=");
    buffer.write(enclosingElement);
    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;
  }
}

/// A visitor that finds the deep-most [Element] that contains the [offset].
class _ContainingElementFinder extends GeneralizingElementVisitor<void> {
  final int offset;
  Element? containingElement;

  _ContainingElementFinder(this.offset);

  @override
  void visitElement(Element element) {
    if (element is ElementImpl) {
      if (element.codeOffset != null &&
          element.codeOffset! <= offset &&
          offset <= element.codeOffset! + element.codeLength!) {
        containingElement = element;
        super.visitElement(element);
      }
    }
  }
}

class _FindCompilationUnitDeclarations {
  final CompilationUnitElement unit;
  final String filePath;
  final LineInfo lineInfo;
  final WorkspaceSymbols result;
  final int? maxResults;
  final FuzzyMatcher matcher;
  final void Function(Declaration) collect;

  _FindCompilationUnitDeclarations(
    this.unit,
    this.filePath,
    this.result,
    this.maxResults,
    this.matcher,
    this.collect,
  ) : lineInfo = unit.lineInfo;

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

    _addAccessors(unit.accessors);
    _addClasses(unit.classes);
    _addClasses(unit.enums);
    _addClasses(unit.mixins);
    _addExtensions(unit.extensions);
    _addClasses(unit.extensionTypes);
    _addFunctions(unit.functions);
    _addTypeAliases(unit.typeAliases);
    _addVariables(unit.topLevelVariables);
  }

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

  void _addClasses(List<InterfaceElement> elements) {
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      _addDeclaration(element, element.name);
      _addAccessors(element.accessors);
      _addConstructors(element.constructors);
      _addFields(element.fields);
      _addMethods(element.methods);
    }
  }

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

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

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

    var enclosing = element.enclosingElement3;

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

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

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

    element as ElementImpl; // to access codeOffset/codeLength
    var locationOffset = element.nameOffset;
    var locationStart = lineInfo.getLocation(locationOffset);

    collect(
      Declaration(
        result._getPathIndex(filePath),
        lineInfo,
        name,
        kind,
        locationOffset,
        locationStart.lineNumber,
        locationStart.columnNumber,
        element.codeOffset ?? 0,
        element.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.name;
      if (name != null) {
        _addDeclaration(element, name);
      }
      _addAccessors(element.accessors);
      _addFields(element.fields);
      _addMethods(element.methods);
    }
  }

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

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

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

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

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

/// 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.element as LibraryElementImpl;
            }
            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 units = libraryElement.units;
          for (var i = 0; i < units.length; i++) {
            var unit = units[i];
            var filePath = unit.source.fullName;
            if (onlyForFile != null && filePath != onlyForFile) {
              continue;
            }
            performance.run('unitDeclarations', (performance) {
              var finder = _FindCompilationUnitDeclarations(
                unit,
                filePath,
                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 _IndexRequest {
  final AnalysisDriverUnitIndex index;

  _IndexRequest(this.index);

  void addSubtypes(
      String superIdString, List<SubtypeResult> results, FileState file) {
    var superId = 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 = getStringId(components.unitMemberName);
    if (unitMemberId == -1) {
      return -1;
    }
    int classMemberId = getStringId(components.classMemberName);
    if (classMemberId == -1) {
      return -1;
    }
    int parameterId = 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 [CompilationUnitElement] if there is a relation of an
  /// interesting kind.
  Future<List<SearchResult>> getRelations(
      int elementId,
      Map<IndexRelationKind, SearchResultKind> relationToResultKind,
      Future<CompilationUnitElement?> 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>[];
    CompilationUnitElement? 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) {
          Element enclosingElement =
              _getEnclosingElement(enclosingUnitElement, offset);
          results.add(SearchResult._(
            enclosingElement,
            resultKind,
            offset,
            index.usedElementLengths[i],
            true,
            index.usedElementIsQualifiedFlags[i],
          ));
        }
      }
    }
    return results;
  }

  /// Return the identifier of [str] in the [index] or `-1` if [str] is not
  /// used in the [index].
  int getStringId(String? str) {
    if (str == null) {
      return index.nullStringId;
    }

    return binarySearch(index.strings, str);
  }

  /// Return the identifier of the [CompilationUnitElement] containing the
  /// [element] in the [index] or `-1` if not found.
  int getUnitId(Element element) {
    CompilationUnitElement unitElement = getUnitElement(element);
    int libraryUriId = getUriId(unitElement.library.source.uri);
    if (libraryUriId == -1) {
      return -1;
    }
    int unitUriId = getUriId(unitElement.source.uri);
    if (unitUriId == -1) {
      return -1;
    }
    for (int i = 0; i < index.unitLibraryUris.length; i++) {
      if (index.unitLibraryUris[i] == libraryUriId &&
          index.unitUnitUris[i] == unitUriId) {
        return i;
      }
    }
    return -1;
  }

  /// 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<CompilationUnitElement?> Function()
          getEnclosingUnitElement) async {
    // Find the name identifier.
    int nameId = 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>[];
    CompilationUnitElement? 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) {
          Element enclosingElement =
              _getEnclosingElement(enclosingUnitElement, offset);
          results.add(SearchResult._(enclosingElement, resultKind, offset,
              name.length, false, index.usedNameIsQualifiedFlags[i]));
        }
      }
    }

    return results;
  }

  /// Return the identifier of the [uri] in the [index] or `-1` if the [uri] is
  /// not used in the [index].
  int getUriId(Uri uri) {
    String str = uri.toString();
    return getStringId(str);
  }

  /// 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 CompilationUnitElement enclosingUnitElement;

  _LocalReferencesVisitor(this.elements, this.enclosingUnitElement);

  @override
  void visitAssignedVariablePattern(AssignedVariablePattern node) {
    if (elements.contains(node.element)) {
      _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.element;
    if (elements.contains(element)) {
      _addResult(node.name, SearchResultKind.REFERENCE);
    }
  }

  @override
  void visitNamedType(NamedType node) {
    var element = node.element;
    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.staticElement;
    if (elements.contains(element)) {
      var parent = node.parent;
      SearchResultKind kind = SearchResultKind.REFERENCE;
      if (element is FunctionElement) {
        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;
    Element enclosingElement =
        _getEnclosingElement(enclosingUnitElement, entity.offset);
    results.add(SearchResult._(enclosingElement, kind, entity.offset,
        entity.length, true, isQualified));
  }
}

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