[analyzer] Don't show duplicate code completions for items imported via multiple libraries
Fixes https://github.com/Dart-Code/Dart-Code/issues/3227. Change-Id: Iac5704fea4f00470040b6b94bbf508dd916ed234 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196923 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
931f7dc2e6
commit
1e51549fab
@@ -357,11 +357,15 @@ class CompletionHandler
|
||||
final key = _createImportedSymbolKey(nameKey, declaringUri);
|
||||
final importingUris = alreadyImportedSymbols[key];
|
||||
|
||||
// Keep it only if there are either:
|
||||
// - no URIs importing it
|
||||
// - the URIs importing it include this one
|
||||
// Keep it only if:
|
||||
// - no existing imports include it
|
||||
// (in which case all libraries will be offered as
|
||||
// auto-imports)
|
||||
// - this is the first imported URI that includes it
|
||||
// (we don't want to repeat it for each imported library that
|
||||
// includes it)
|
||||
return importingUris == null ||
|
||||
importingUris.contains('${library.uri}');
|
||||
importingUris.first == '${library.uri}';
|
||||
}).map((item) => declarationToCompletionItem(
|
||||
capabilities,
|
||||
unit.path!,
|
||||
|
||||
@@ -1192,6 +1192,95 @@ main() {
|
||||
'''));
|
||||
}
|
||||
|
||||
Future<void>
|
||||
test_suggestionSets_doesNotDuplicate_importedViaMultipleLibraries() async {
|
||||
// An item that's already imported through multiple libraries that
|
||||
// export it should not result in multiple entries.
|
||||
newFile(
|
||||
join(projectFolderPath, 'lib/source_file.dart'),
|
||||
content: '''
|
||||
class MyExportedClass {}
|
||||
''',
|
||||
);
|
||||
newFile(
|
||||
join(projectFolderPath, 'lib/reexport1.dart'),
|
||||
content: '''
|
||||
export 'source_file.dart';
|
||||
''',
|
||||
);
|
||||
newFile(
|
||||
join(projectFolderPath, 'lib/reexport2.dart'),
|
||||
content: '''
|
||||
export 'source_file.dart';
|
||||
''',
|
||||
);
|
||||
|
||||
final content = '''
|
||||
import 'reexport1.dart';
|
||||
import 'reexport2.dart';
|
||||
|
||||
main() {
|
||||
MyExported^
|
||||
}
|
||||
''';
|
||||
|
||||
final initialAnalysis = waitForAnalysisComplete();
|
||||
await initialize(
|
||||
workspaceCapabilities:
|
||||
withApplyEditSupport(emptyWorkspaceClientCapabilities));
|
||||
await openFile(mainFileUri, withoutMarkers(content));
|
||||
await initialAnalysis;
|
||||
|
||||
final res = await getCompletion(mainFileUri, positionFromMarker(content));
|
||||
|
||||
final completions = res.where((c) => c.label == 'MyExportedClass').toList();
|
||||
expect(completions, hasLength(1));
|
||||
}
|
||||
|
||||
Future<void>
|
||||
test_suggestionSets_doesNotDuplicate_importedViaSingleLibrary() async {
|
||||
// An item that's already imported through a library that exports it
|
||||
// should not result in multiple entries.
|
||||
newFile(
|
||||
join(projectFolderPath, 'lib/source_file.dart'),
|
||||
content: '''
|
||||
class MyExportedClass {}
|
||||
''',
|
||||
);
|
||||
newFile(
|
||||
join(projectFolderPath, 'lib/reexport1.dart'),
|
||||
content: '''
|
||||
export 'source_file.dart';
|
||||
''',
|
||||
);
|
||||
newFile(
|
||||
join(projectFolderPath, 'lib/reexport2.dart'),
|
||||
content: '''
|
||||
export 'source_file.dart';
|
||||
''',
|
||||
);
|
||||
|
||||
final content = '''
|
||||
import 'reexport1.dart';
|
||||
|
||||
main() {
|
||||
MyExported^
|
||||
}
|
||||
''';
|
||||
|
||||
final initialAnalysis = waitForAnalysisComplete();
|
||||
await initialize(
|
||||
workspaceCapabilities:
|
||||
withApplyEditSupport(emptyWorkspaceClientCapabilities));
|
||||
await openFile(mainFileUri, withoutMarkers(content));
|
||||
await initialAnalysis;
|
||||
|
||||
final res = await getCompletion(mainFileUri, positionFromMarker(content));
|
||||
|
||||
final completions = res.where((c) => c.label == 'MyExportedClass').toList();
|
||||
expect(completions, hasLength(1));
|
||||
}
|
||||
|
||||
Future<void> test_suggestionSets_doesNotFilterSymbolsWithSameName() async {
|
||||
// Classes here are not re-exports, so should not be filtered out.
|
||||
newFile(
|
||||
|
||||
Reference in New Issue
Block a user