如何使用Dart的分析服务器方法search.findTopLevelDeclarations?



我正在尝试使用Dart的分析服务器获取顶级类声明的列表。所以,我发送了search.findTopLevelDeclarations请求,但搜索结果总是空的。

在我看来,分析服务器不知道在哪里搜索。我尝试将项目的根设置为执行上下文(execution.createContext(根和/或分析根(analysis.setAnalysisRoots(,但搜索结果仍然为空。

我应该怎么做才能让服务器了解在哪里搜索声明?

以前从未玩过这个,所以我开始了一段相当长的旅程。。。

我不知道您是如何与分析服务器交互的,但我已经使用analysis_server_client包做了一个工作示例。这样做的一个问题是pub.dev上的版本很旧,所以我最终从Dart SDK的稳定分支获取了这个版本:
https://github.com/dart-lang/sdk/tree/stable/pkg/analysis_server_client

然后,您可以通过执行以下操作在pubspec.yaml中导入包:

dependencies:
analysis_server_client:
path: /path/to/analysis_server_client

然后,我制作了示例代码的简化版本:
https://github.com/dart-lang/sdk/blob/stable/pkg/analysis_server_client/example/example.dart

import 'dart:io' show exit;
import 'package:analysis_server_client/handler/connection_handler.dart';
import 'package:analysis_server_client/handler/notification_handler.dart';
import 'package:analysis_server_client/protocol.dart';
import 'package:analysis_server_client/server.dart';
final server = Server();
Future<void> main(List<String> args) async {
const targetDirPath = r'C:tmpsimple_project';
const searchPattern = 'main';
// Launch the server
await server.start();
// Connect to the server
final handler = _Handler(server);
server.listenToOutput(notificationProcessor: handler.handleEvent);
if (!await handler.serverConnected(timeLimit: const Duration(seconds: 15))) {
exit(1);
}
await server.send(ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS,
AnalysisSetAnalysisRootsParams([targetDirPath], const []).toJson());
await server.send(SEARCH_REQUEST_FIND_TOP_LEVEL_DECLARATIONS,
SearchFindTopLevelDeclarationsParams(searchPattern).toJson());
}
class _Handler with NotificationHandler, ConnectionHandler {
@override
final Server server;
_Handler(this.server);
@override
void onSearchResults(SearchResultsParams params) {
print('-- Start of result --');
params.results.forEach(print);
print('--  End of result  --');
server.stop();
}
}

C:tmpsimple_project中的项目是一个简单的项目,它由以下内容创建,这意味着它只包含一个main方法:

dart create -t console-simple simple_project

当我运行分析仪程序时,我得到以下输出:

-- Start of result --
{"location":{"file":"C:\tmp\simple_project\bin\simple_project.dart","offset":5,"length":4,"startLine":1,"startColumn":6,"endLine":1,"endColumn":10},"kind":"DECLARATION","isPotential":false,"path":[{"kind":"FUNCTION","name":"main","location":{"file":"C:\tmp\simple_project\bin\simple_project.dart","offset":5,"length":4,"startLine":1,"startColumn":6,"endLine":1,"endColumn":10},"flags":8,"parameters":"(List<String> arguments)","returnType":"void"},{"kind":"COMPILATION_UNIT","name":"simple_project.dart","location":{"file":"C:\tmp\simple_project\bin\simple_project.dart","offset":0,"length":0,"startLine":1,"startColumn":1,"endLine":1,"endColumn":1},"flags":16},{"kind":"LIBRARY","name":"","location":{"file":"C:\tmp\simple_project\bin\simple_project.dart","offset":0,"length":0,"startLine":1,"startColumn":1,"endLine":1,"endColumn":1},"flags":0}]}
--  End of result  --

如果我将searchPattern更改为空的String,我会得到一长串关于默认包含的Dart SDK库的顶级声明。我相信有办法排除这些。

但就我所见,searchPattern是一个针对每个顶级声明的名称进行测试的正则表达式,并且如果声明的名称包含正则表达式的任何部分,则包含该声明。

我在这里找到了负责搜索的代码:

@override
Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern) async {
var allElements = <Element>{};
var regExp = RegExp(pattern);
var drivers = _drivers.toList();
for (var driver in drivers) {
var elements = await driver.search.topLevelElements(regExp);
allElements.addAll(elements);
}
return allElements.map(SearchMatchImpl.forElement).toList();
}

https://github.com/dart-lang/sdk/blob/1278bd5adb6a857580f137e47bc521976222f7b9/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart#L113-L123

哪个调用:

/// 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.functions.forEach(addElement);
unitElement.mixins.forEach(addElement);
unitElement.topLevelVariables.forEach(addElement);
unitElement.typeAliases.forEach(addElement);
}
}
return elements;
}

https://github.com/dart-lang/sdk/blob/1278bd5adb6a857580f137e47bc521976222f7b9/pkg/analyzer/lib/src/dart/analysis/search.dart#L166-L192

最新更新