[analysis_server] Apply fuzzy prefix matching to LSP YAML completions
Change-Id: I4b6a45d2601c10ed08c3bdcf4e5c007d5063dbff
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243328
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 97c569e..ac13d91 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -597,7 +597,15 @@
final insertionRange =
toRange(lineInfo, suggestions.replacementOffset, insertLength);
+ // Perform fuzzy matching based on the identifier in front of the caret to
+ // reduce the size of the payload.
+ final fuzzyPattern = suggestions.targetPrefix;
+ final fuzzyMatcher =
+ FuzzyMatcher(fuzzyPattern, matchStyle: MatchStyle.TEXT);
+
final completionItems = suggestions.suggestions
+ .where((item) =>
+ fuzzyMatcher.score(item.displayText ?? item.completion) > 0)
.map(
(item) => toCompletionItem(
capabilities,
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart
index 53c3de6..ec3e06f 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart
@@ -84,17 +84,23 @@
}
}
final node = nodePath.isNotEmpty ? nodePath.last : null;
+ String targetPrefix;
int replacementOffset;
int replacementLength;
if (node is YamlScalar && node.containsOffset(offset)) {
+ targetPrefix = node.span.text.substring(
+ 0,
+ offset - node.span.start.offset,
+ );
replacementOffset = node.span.start.offset;
replacementLength = node.span.length;
} else {
+ targetPrefix = '';
replacementOffset = offset;
replacementLength = 0;
}
return YamlCompletionResults(
- suggestions, replacementOffset, replacementLength);
+ suggestions, targetPrefix, replacementOffset, replacementLength);
}
/// Return the result of parsing the file [content] into a YAML node.
@@ -196,14 +202,16 @@
class YamlCompletionResults {
final List<CompletionSuggestion> suggestions;
+ final String targetPrefix;
final int replacementOffset;
final int replacementLength;
- const YamlCompletionResults(
- this.suggestions, this.replacementOffset, this.replacementLength);
+ const YamlCompletionResults(this.suggestions, this.targetPrefix,
+ this.replacementOffset, this.replacementLength);
const YamlCompletionResults.empty()
: suggestions = const [],
+ targetPrefix = '',
replacementOffset = 0,
replacementLength = 0;
}
diff --git a/pkg/analysis_server/test/lsp/completion_yaml_test.dart b/pkg/analysis_server/test/lsp/completion_yaml_test.dart
index cee886f..9d8ff8a 100644
--- a/pkg/analysis_server/test/lsp/completion_yaml_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_yaml_test.dart
@@ -295,7 +295,7 @@
await verifyCompletions(
pubspecFileUri,
content,
- expectCompletions: ['flutter: ', 'sdk: '],
+ expectCompletions: ['sdk: '],
applyEditsFor: 'sdk: ',
expectedContent: expected,
);
@@ -576,6 +576,32 @@
expect(completionResults, isEmpty);
}
+ Future<void> test_prefixFilter() async {
+ httpClient.sendHandler = (BaseRequest request) async {
+ if (request.url.toString().endsWith(PubApi.packageNameListPath)) {
+ return Response(samplePackageList, 200);
+ } else {
+ throw UnimplementedError();
+ }
+ };
+
+ final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+ on^''';
+
+ await initialize();
+ await openFile(pubspecFileUri, content);
+ await pumpEventQueue();
+
+ completionResults =
+ await getCompletion(pubspecFileUri, positionFromMarker(content));
+ expect(completionResults.length, equals(1));
+ expect(completionResults.single.label, equals('one: '));
+ }
+
Future<void> test_topLevel() async {
final content = '''
version: 1.0.0
@@ -602,7 +628,7 @@
await verifyCompletions(
pubspecFileUri,
content,
- expectCompletions: ['name: ', 'description: '],
+ expectCompletions: ['name: '],
applyEditsFor: 'name: ',
expectedContent: expected,
);