[analysis_server] Allow multiple not-imported items in completion if name not already imported

Change-Id: Ie5bfa353d59546518180a08cd4720f793a01ba30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250660
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Danny Tuppeny
2022-07-06 17:19:40 +00:00
committed by Commit Bot
parent 572f24882f
commit 83f0bb25a4
2 changed files with 96 additions and 19 deletions
@@ -1128,6 +1128,18 @@ class SuggestionBuilder {
var key = suggestion.key;
listener?.builtSuggestion(suggestion);
if (laterReplacesEarlier || !_suggestionMap.containsKey(key)) {
// When suggesting from not-yet-imported libraries, record items
// with a key that includes the URI so that multiple not-yet-imported
// libraries can be included, but only if there is no imported library
// contributing that key.
if (isNotImportedLibrary) {
key += '::$libraryUriStr';
// If `!laterReplacesEarlier`, also ensure we don't already have this
// new key.
if (!laterReplacesEarlier && _suggestionMap.containsKey(key)) {
return;
}
}
_suggestionMap[key] = suggestion;
}
}
@@ -71,6 +71,7 @@ abstract class AbstractCompletionDriverTest
ElementKind? element,
CompletionSuggestionKind? kind,
String? file,
String? libraryUri,
}) {
expect(
suggestionWith(
@@ -78,22 +79,7 @@ abstract class AbstractCompletionDriverTest
element: element,
kind: kind,
file: file,
),
isNotNull);
}
void assertSuggestions({
required String completion,
ElementKind? element,
CompletionSuggestionKind? kind,
String? file,
}) {
expect(
suggestionWith(
completion: completion,
element: element,
kind: kind,
file: file,
libraryUri: libraryUri,
),
isNotNull);
}
@@ -161,6 +147,7 @@ name: test
ElementKind? element,
CompletionSuggestionKind? kind,
String? file,
String? libraryUri,
}) =>
(CompletionSuggestion s) {
if (s.completion != completion) {
@@ -176,6 +163,9 @@ name: test
if (file != null && s.element?.location?.file != convertPath(file)) {
return false;
}
if (libraryUri != null && s.libraryUri != libraryUri) {
return false;
}
return true;
};
@@ -184,18 +174,28 @@ name: test
ElementKind? element,
CompletionSuggestionKind? kind,
String? file,
String? libraryUri,
}) =>
suggestions.where(suggestionHas(
completion: completion, element: element, kind: kind, file: file));
completion: completion,
element: element,
kind: kind,
file: file,
libraryUri: libraryUri));
CompletionSuggestion suggestionWith({
required String completion,
ElementKind? element,
CompletionSuggestionKind? kind,
String? file,
String? libraryUri,
}) {
final matches = suggestionsWith(
completion: completion, element: element, kind: kind, file: file);
completion: completion,
element: element,
kind: kind,
file: file,
libraryUri: libraryUri);
expect(matches, hasLength(1));
return matches.first;
}
@@ -272,6 +272,14 @@ class CompletionWithSuggestionsTest1 extends AbstractCompletionDriverTest
Future<void> test_project_lib_multipleExports() async {
return super.test_project_lib_multipleExports();
}
@FailingTest(
reason:
'This test fails with available suggestions because it checks libraryUri')
@override
Future<void> test_project_lib_multipleExports_filteredByLocal() async {
return super.test_project_lib_multipleExports_filteredByLocal();
}
}
@reflectiveTest
@@ -575,11 +583,68 @@ void f() {
}
''');
// Should only have one suggestion.
// Should be suggested from both libraries.
assertSuggestion(
completion: 'A',
libraryUri: 'package:test/a.dart',
element: ElementKind.CONSTRUCTOR,
kind: CompletionSuggestionKind.INVOCATION);
assertSuggestion(
completion: 'A',
libraryUri: 'package:test/b.dart',
element: ElementKind.CONSTRUCTOR,
kind: CompletionSuggestionKind.INVOCATION);
}
Future<void> test_project_lib_multipleExports_filteredByImport() async {
newFile('$testPackageLibPath/a.dart', r'''
class A {}
''');
newFile('$testPackageLibPath/b.dart', r'''
export 'a.dart';
''');
if (isProtocolVersion1) {
await waitForSetWithUri('package:test/a.dart');
await waitForSetWithUri('package:test/b.dart');
}
await addTestFile('''
import 'b.dart';
void f() {
^
}
''');
// Should be only one suggestion, which comes from the import of 'b.dart'.
assertSuggestion(
completion: 'A',
element: ElementKind.CLASS,
);
}
Future<void> test_project_lib_multipleExports_filteredByLocal() async {
newFile('$testPackageLibPath/a.dart', r'''
class A {}
''');
if (isProtocolVersion1) {
await waitForSetWithUri('package:test/a.dart');
}
await addTestFile('''
class A {}
void f() {
^
}
''');
// Should be only one suggestion, which comes from local declaration.
assertSuggestion(
completion: 'A',
element: ElementKind.CLASS,
);
}
Future<void> test_project_lib_setters_class() async {