diff --git a/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart b/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart index 3ce86a005b4..a654a33529f 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart @@ -133,6 +133,22 @@ class DeclarationHelper { } } + /// Add suggestions for declarations through [prefixElement]. + void addDeclarationsThroughImportPrefix(PrefixElement prefixElement) { + for (var importElement in prefixElement.imports) { + var importedLibrary = importElement.importedLibrary; + if (importedLibrary == null) { + continue; + } + + _addDeclarationsImportedFrom( + library: importedLibrary, + namespace: importElement.namespace, + prefix: null, + ); + } + } + /// Add any fields that can be initialized in the initializer list of the /// given [constructor]. If a [fieldToInclude] is provided, then it should not /// be skipped because the cursor is inside that field's name. diff --git a/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart b/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart index dd52f627381..135c1b789ea 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart @@ -1525,6 +1525,22 @@ class InScopeCompletionPass extends SimpleAstVisitor { @override void visitNamedType(NamedType node) { + var importPrefix = node.importPrefix; + var prefixElement = importPrefix?.element; + + // `prefix.x^ print(0);` is recovered as `prefix.x print; (0);`. + if (prefixElement is PrefixElement) { + if (node.parent case VariableDeclarationList variableList) { + if (variableList.parent case VariableDeclarationStatement statement) { + if (statement.semicolon.isSynthetic) { + declarationHelper() + .addDeclarationsThroughImportPrefix(prefixElement); + return; + } + } + } + } + _forTypeAnnotation(node); } diff --git a/pkg/analysis_server/test/services/completion/dart/location/property_access_expression_test.dart b/pkg/analysis_server/test/services/completion/dart/location/property_access_expression_test.dart index 4bfee6799c7..79a792dcf60 100644 --- a/pkg/analysis_server/test/services/completion/dart/location/property_access_expression_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/location/property_access_expression_test.dart @@ -55,6 +55,31 @@ suggestions '''); } + Future test_afterIdentifier_beforeIdentifier_partial() async { + newFile('$testPackageLibPath/a.dart', r''' +void v01() {} +void g01() {} +'''); + + // There should be no `void`, we use `v` to verify this. + await computeSuggestions(''' +import 'a.dart' as prefix; + +void f() { + prefix.v^ + print(0); +} +'''); + + assertResponse(r''' +replacement + left: 1 +suggestions + v01 + kind: functionInvocation +'''); + } + Future test_afterIdentifier_partial() async { await computeSuggestions(''' class A { foo() {bar.as^}}