[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:
committed by
Commit Bot
parent
572f24882f
commit
83f0bb25a4
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user