diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart index 3e25727f8a6..886dffa1764 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart @@ -360,11 +360,12 @@ class _KeywordVisitor extends GeneralizingAstVisitor { var constructorDeclaration = node.thisOrAncestorOfType(); if (constructorDeclaration != null) { - _addSuggestions([Keyword.THIS]); + _addSuggestion(Keyword.THIS); } if (entity is Token && (entity as Token).type == TokenType.CLOSE_PAREN) { _addSuggestion(Keyword.COVARIANT); _addSuggestion(Keyword.DYNAMIC); + _addSuggestion(Keyword.VOID); if (request.featureSet.isEnabled(Feature.non_nullable)) { _addSuggestion(Keyword.REQUIRED); } @@ -373,6 +374,14 @@ class _KeywordVisitor extends GeneralizingAstVisitor { if (beginToken != null && request.target.offset == beginToken.end) { _addSuggestion(Keyword.COVARIANT); _addSuggestion(Keyword.DYNAMIC); + _addSuggestion(Keyword.VOID); + if (request.featureSet.isEnabled(Feature.non_nullable)) { + _addSuggestion(Keyword.REQUIRED); + } + } else if (entity is FunctionTypedFormalParameter) { + _addSuggestion(Keyword.COVARIANT); + _addSuggestion(Keyword.DYNAMIC); + _addSuggestion(Keyword.VOID); if (request.featureSet.isEnabled(Feature.non_nullable)) { _addSuggestion(Keyword.REQUIRED); } diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart index a7c48cf2469..72c03d17451 100644 --- a/pkg/analysis_server/test/completion_test.dart +++ b/pkg/analysis_server/test/completion_test.dart @@ -103,8 +103,15 @@ class F {m() { m(); !1}}''', ['1+m']); class F {var x = !1false;}''', ['1+true']); buildTests('testCommentSnippets018', ''' -class Map{}class Arrays{}class C{ m(!1){} n(!2 x, q)''', - ['1+Map', '1-void', '1-null', '2+Arrays', '2-void', '2-null']); +class Map{}class Arrays{}class C{ m(!1){} n(!2 x, q)''', [ + '1+Map', + '1+dynamic', + '1+void', + '1-null', + '2+Arrays', + '2-void', + '2-null' + ]); buildTests('testCommentSnippets019', ''' class A{m(){Object x;x.!1/**/clear()''', ['1+toString']); diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart index 4272bdc6892..0df93092bca 100644 --- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart @@ -71,7 +71,13 @@ class KeywordContributorTest extends DartCompletionContributorTest { } List get constructorParameter { - var keywords = [Keyword.COVARIANT, Keyword.DYNAMIC, Keyword.THIS]; + var keywords = [ + Keyword.COVARIANT, + Keyword.DYNAMIC, + Keyword.THIS, + Keyword.DYNAMIC, + Keyword.VOID + ]; if (isEnabled(ExperimentalFeatures.non_nullable)) { keywords.add(Keyword.REQUIRED); } @@ -156,7 +162,7 @@ class KeywordContributorTest extends DartCompletionContributorTest { } List get methodParameter { - var keywords = [Keyword.COVARIANT, Keyword.DYNAMIC]; + var keywords = [Keyword.COVARIANT, Keyword.DYNAMIC, Keyword.VOID]; if (isEnabled(ExperimentalFeatures.non_nullable)) { keywords.add(Keyword.REQUIRED); } @@ -1028,12 +1034,26 @@ class C { assertSuggestKeywords(constructorParameter); } + Future test_constructor_param_noPrefix_func_parameter() async { + addTestSource('class A { A(^ Function(){}) {}}'); + await computeSuggestions(); + expect(suggestions, isNotEmpty); + assertSuggestKeywords(constructorParameter); + } + Future test_constructor_param_prefix() async { addTestSource('class A { A(t^) {}}'); await computeSuggestions(); assertSuggestKeywords(constructorParameter); } + Future test_constructor_param_prefix_func_parameter() async { + addTestSource('class A { A(v^ Function(){}) {}}'); + await computeSuggestions(); + expect(suggestions, isNotEmpty); + assertSuggestKeywords(constructorParameter); + } + Future test_do_break_continue_insideClass() async { addTestSource('class A {foo() {do {^} while (true);}}'); await computeSuggestions(); @@ -1971,6 +1991,13 @@ f() => {1, ^, 2}; assertSuggestKeywords(methodParameter); } + Future test_method_param_noPrefix_func_parameter() async { + addTestSource('class A { foo(^ Function(){}) {}}'); + await computeSuggestions(); + expect(suggestions, isNotEmpty); + assertSuggestKeywords(methodParameter); + } + Future test_method_param_positional_init() async { addTestSource('class A { foo([bool bar = ^]) {}}'); await computeSuggestions(); @@ -1992,6 +2019,13 @@ f() => {1, ^, 2}; assertSuggestKeywords(methodParameter); } + Future test_method_param_prefix_func_parameter() async { + addTestSource('class A { foo(v^ Function(){}) {}}'); + await computeSuggestions(); + expect(suggestions, isNotEmpty); + assertSuggestKeywords(methodParameter); + } + Future test_mixin() async { addTestSource('mixin M o^ { }'); await computeSuggestions();