Skip to content

Commit d42b7bc

Browse files
pqcommit-bot@chromium.org
authored andcommitted
partition imported/not-imported suggestion sets / de-dup
Change-Id: Iba72b3599e9153e9fac3dd883d7bdb272c25fa65 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135622 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Phil Quitslund <pquitslund@google.com>
1 parent 6a7d4e2 commit d42b7bc

2 files changed

Lines changed: 136 additions & 8 deletions

File tree

pkg/analysis_server/test/client/completion_driver_test.dart

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,51 @@ class CompletionWithSuggestionsTest extends AbstractCompletionDriverTest {
227227
@override
228228
String get testFilePath => '$projectPath/lib/test.dart';
229229

230+
Future<void> test_project_filterImports() async {
231+
await addProjectFile('lib/a.dart', r'''
232+
class A {}
233+
''');
234+
235+
await addProjectFile('lib/b.dart', r'''
236+
export 'a.dart';
237+
''');
238+
239+
await addTestFile('''
240+
import 'a.dart';
241+
void main() {
242+
^
243+
}
244+
''');
245+
246+
expectSuggestion(
247+
completion: 'A',
248+
element: ElementKind.CONSTRUCTOR,
249+
kind: CompletionSuggestionKind.INVOCATION);
250+
}
251+
252+
Future<void> test_project_filterMultipleImports() async {
253+
await addProjectFile('lib/a.dart', r'''
254+
class A {}
255+
''');
256+
257+
await addProjectFile('lib/b.dart', r'''
258+
export 'a.dart';
259+
''');
260+
261+
await addTestFile('''
262+
import 'a.dart';
263+
import 'b.dart';
264+
void main() {
265+
^
266+
}
267+
''');
268+
269+
expectSuggestion(
270+
completion: 'A',
271+
element: ElementKind.CLASS,
272+
kind: CompletionSuggestionKind.INVOCATION);
273+
}
274+
230275
Future<void> test_project_lib() async {
231276
await addProjectFile('lib/a.dart', r'''
232277
class A {}
@@ -278,6 +323,28 @@ void main() {
278323
}
279324

280325
@failingTest
326+
Future<void> test_project_lib_multipleExports() async {
327+
await addProjectFile('lib/a.dart', r'''
328+
class A {}
329+
''');
330+
331+
await addProjectFile('lib/b.dart', r'''
332+
export 'a.dart';
333+
''');
334+
335+
await addTestFile('''
336+
void main() {
337+
^
338+
}
339+
''');
340+
341+
// Should only have one suggestion.
342+
expectSuggestion(
343+
completion: 'A',
344+
element: ElementKind.CONSTRUCTOR,
345+
kind: CompletionSuggestionKind.INVOCATION);
346+
}
347+
281348
Future<void> test_sdk_lib_future_isNotDuplicated() async {
282349
await addTestFile('''
283350
void main() {

pkg/analysis_server/test/client/impl/completion_driver.dart

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ class CompletionDriver extends AbstractClient with ExpectMixin {
150150
allSuggestions[id] = params.results;
151151
var includedKinds = params.includedElementKinds;
152152

153+
//
154+
// Collect relevance information.
155+
//
156+
153157
// https://github.com/JetBrains/intellij-plugins/blob/59018828753973324ea0500fa4bae93563f1aacf/Dart/src/com/jetbrains/lang/dart/analyzer/DartAnalysisServerService.java#L467
154158
var includedRelevanceTags = <String, IncludedSuggestionRelevanceTag>{};
155159
var includedSuggestionRelevanceTags =
@@ -161,22 +165,79 @@ class CompletionDriver extends AbstractClient with ExpectMixin {
161165
}
162166
}
163167

168+
//
169+
// Identify imported libraries.
170+
//
171+
172+
var importedLibraryUris = <String>{};
173+
var existingImports = fileToExistingImports[params.libraryFile];
174+
if (existingImports != null) {
175+
for (var existingImport in existingImports.imports) {
176+
var uri = existingImports.elements.strings[existingImport.uri];
177+
importedLibraryUris.add(uri);
178+
}
179+
}
180+
181+
//
182+
// Partition included suggestion sets into imported and not-imported groups.
183+
//
184+
185+
var importedSets = <IncludedSuggestionSet>[];
186+
var notImportedSets = <IncludedSuggestionSet>[];
187+
164188
for (var set in params.includedSuggestionSets) {
165189
var id = set.id;
166190
while (!idToSetMap.containsKey(id)) {
167191
await Future.delayed(const Duration(milliseconds: 1));
168192
}
169193
var suggestionSet = idToSetMap[id];
170-
for (var suggestion in suggestionSet.items) {
171-
var kind = suggestion.element.kind;
172-
if (!includedKinds.contains(kind)) {
173-
continue;
194+
if (importedLibraryUris.contains(suggestionSet.uri)) {
195+
importedSets.add(set);
196+
} else {
197+
notImportedSets.add(set);
198+
}
199+
}
200+
201+
//
202+
// Add suggestions.
203+
//
204+
// First from imported then from not-imported sets.
205+
//
206+
207+
void addSuggestion(
208+
AvailableSuggestion suggestion, IncludedSuggestionSet includeSet) {
209+
var kind = suggestion.element.kind;
210+
if (!includedKinds.contains(kind)) {
211+
return;
212+
}
213+
var completionSuggestion =
214+
_createCompletionSuggestionFromAvailableSuggestion(
215+
suggestion, includeSet.relevance, includedRelevanceTags);
216+
suggestions.add(completionSuggestion);
217+
}
218+
219+
// Track seen elements to ensure they are not duplicated.
220+
var seenElements = <String>{};
221+
222+
// Suggestions can be uniquely identified by kind, label and uri.
223+
String suggestionId(AvailableSuggestion s) =>
224+
'${s.declaringLibraryUri}:${s.element.kind}:${s.label}';
225+
226+
for (var includeSet in importedSets) {
227+
var set = idToSetMap[includeSet.id];
228+
for (var suggestion in set.items) {
229+
if (seenElements.add(suggestionId(suggestion))) {
230+
addSuggestion(suggestion, includeSet);
174231
}
232+
}
233+
}
175234

176-
var completionSuggestion =
177-
_createCompletionSuggestionFromAvailableSuggestion(
178-
suggestion, set.relevance, includedRelevanceTags);
179-
suggestions.add(completionSuggestion);
235+
for (var includeSet in notImportedSets) {
236+
var set = idToSetMap[includeSet.id];
237+
for (var suggestion in set.items) {
238+
if (!seenElements.contains(suggestionId(suggestion))) {
239+
addSuggestion(suggestion, includeSet);
240+
}
180241
}
181242
}
182243

0 commit comments

Comments
 (0)