Use the max number of suggestions to limit the number of candidate suggestions being retained
Change-Id: I4a60569fb4efe4af576b9adbb375c6e2e0b1727c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/370720
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Keerti Parthasarathy <keertip@google.com>
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 50713af..d88d035 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -102,6 +102,7 @@
performance,
enableOverrideContributor: false,
enableUriContributor: false,
+ maxSuggestions: -1,
useFilter: true,
);
});
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index 30342f7..3918a83 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -79,6 +79,7 @@
).computeSuggestions(
dartRequest,
OperationPerformanceImpl('<root>'),
+ maxSuggestions: -1,
useFilter: false,
);
var suggestions = serverSuggestions.map((e) => e.build()).toList();
diff --git a/pkg/analysis_server/lib/src/handler/legacy/completion_get_suggestions2.dart b/pkg/analysis_server/lib/src/handler/legacy/completion_get_suggestions2.dart
index 8de8f53..6a2832a 100644
--- a/pkg/analysis_server/lib/src/handler/legacy/completion_get_suggestions2.dart
+++ b/pkg/analysis_server/lib/src/handler/legacy/completion_get_suggestions2.dart
@@ -42,6 +42,7 @@
required CompletionBudget budget,
required OperationPerformanceImpl performance,
required DartCompletionRequest request,
+ required int maxSuggestions,
NotImportedSuggestions? notImportedSuggestions,
required bool useFilter,
}) async {
@@ -66,6 +67,7 @@
await manager.computeSuggestions(
request,
performance,
+ maxSuggestions: maxSuggestions,
useFilter: useFilter,
),
);
@@ -205,6 +207,7 @@
budget: budget,
performance: performance,
request: completionRequest,
+ maxSuggestions: params.maxResults,
notImportedSuggestions: notImportedSuggestions,
useFilter: true,
);
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 fc00f02..e894785 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -167,6 +167,7 @@
offset,
triggerCharacter,
token,
+ maxResults,
);
},
);
@@ -360,6 +361,7 @@
int offset,
String? triggerCharacter,
CancellationToken token,
+ int maxSuggestions,
) async {
var useNotImportedCompletions =
suggestFromUnimportedLibraries && capabilities.applyEdit;
@@ -397,6 +399,7 @@
var suggestions = await contributor.computeSuggestions(
completionRequest,
performance,
+ maxSuggestions: maxSuggestions,
useFilter: true,
);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index b834eec..c2d0f056 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -88,6 +88,7 @@
OperationPerformanceImpl performance, {
bool enableOverrideContributor = true,
bool enableUriContributor = true,
+ required int maxSuggestions,
required bool useFilter,
}) async {
request.checkAborted();
@@ -108,15 +109,15 @@
var notImportedSuggestions = this.notImportedSuggestions;
- var collector = SuggestionCollector();
+ var collector = SuggestionCollector(maxSuggestions: maxSuggestions);
try {
var selection = request.unit.select(offset: request.offset, length: 0);
if (selection == null) {
throw AbortCompletion();
}
- var matcher = request.targetPrefix.isEmpty
- ? NoPrefixMatcher()
- : FuzzyMatcher(request.targetPrefix);
+ var targetPrefix = request.targetPrefix;
+ var matcher =
+ targetPrefix.isEmpty ? NoPrefixMatcher() : FuzzyMatcher(targetPrefix);
var state = CompletionState(request, selection, budget, matcher);
var operations = performance.run(
'InScopeCompletionPass',
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_collector.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_collector.dart
index 2d099be..327d486 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_collector.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_collector.dart
@@ -6,6 +6,9 @@
/// An object that collects the candidate suggestions produced by the steps.
class SuggestionCollector {
+ /// The maximum number of suggestions that will be returned.
+ final int maxSuggestions;
+
/// The list of candidate suggestions that have been collected.
final List<CandidateSuggestion> suggestions = [];
@@ -20,15 +23,56 @@
/// exception being thrown.
bool isIncomplete = false;
- /// Return `true` if the context prefers a constant expression. This is used
- /// to compute relevance.
+ /// Whether the context prefers a constant expression. This is used to compute
+ /// relevance.
bool preferConstants = false;
/// Initializes a newly created collector to collect candidate suggestions.
- SuggestionCollector();
+ ///
+ /// The [maxSuggestions] is the maximum number of suggestions that will be
+ /// returned to the client, or `-1` if all of the suggestions should be
+ /// returned. This is used to truncate the list of suggestions early, which
+ /// - reduces the amount of memory used during completion
+ /// - reduces the number of suggestions that need to have relevance scores and
+ /// that need to be converted to the form used by the protocol
+ SuggestionCollector({required this.maxSuggestions});
/// Adds the candidate [suggestion] to the list of suggestions.
void addSuggestion(CandidateSuggestion suggestion) {
- suggestions.add(suggestion);
+ // Insert the suggestion into the list in sorted order.
+ if (suggestions.isEmpty) {
+ suggestions.add(suggestion);
+ return;
+ }
+ var score = suggestion.matcherScore;
+ var added = false;
+ for (var i = suggestions.length - 1; i >= 0; i--) {
+ var currentSuggestion = suggestions[i];
+ if (currentSuggestion.matcherScore >= score) {
+ suggestions.insert(i + 1, suggestion);
+ added = true;
+ break;
+ }
+ }
+ if (!added) {
+ suggestions.insert(0, suggestion);
+ }
+ // If there are suggestions whose matcher score is too low, remove them.
+ //
+ // Note that this will allow the list of suggestions to be longer than the
+ // maximum number of suggestions as long as at least one suggestion with the
+ // lowest score would be kept. Suggestions with the same score will later be
+ // sorted by the relevance score and then the lowest bucket will be
+ // truncated.
+ if (maxSuggestions >= 0 && suggestions.length > maxSuggestions) {
+ var minScoreToKeep = suggestions[maxSuggestions].matcherScore;
+ while (suggestions.length > maxSuggestions) {
+ if (suggestions.last.matcherScore < minScoreToKeep) {
+ suggestions.removeLast();
+ } else {
+ break;
+ }
+ }
+ }
}
}
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index 58ddd89..1adf3f3 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -106,6 +106,7 @@
var suggestions = await contributor.computeSuggestions(
dartRequest,
OperationPerformanceImpl('<root>'),
+ maxSuggestions: -1,
useFilter: true,
);
timer.stop();
diff --git a/pkg/analysis_server/tool/code_completion/benchmark/flutter.dart b/pkg/analysis_server/tool/code_completion/benchmark/flutter.dart
index 194066c..364a9e6 100644
--- a/pkg/analysis_server/tool/code_completion/benchmark/flutter.dart
+++ b/pkg/analysis_server/tool/code_completion/benchmark/flutter.dart
@@ -93,6 +93,7 @@
).computeSuggestions(
dartRequest,
OperationPerformanceImpl('<root>'),
+ maxSuggestions: -1,
useFilter: false,
);
}
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 6a31083..5e85216 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1410,6 +1410,7 @@
).computeSuggestions(
dartRequest,
performance,
+ maxSuggestions: -1,
useFilter: true,
);