Suggest void as a return type in existing generic function types
Change-Id: I88c37e5ce273de2e9598b182fc5fb61066c11740
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/204600
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
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 b6d71a6..268064a 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
@@ -403,7 +403,7 @@
} else if (entity is FormalParameter) {
var beginToken = entity.beginToken;
var offset = request.target.offset;
- if (beginToken.offset <= offset && offset <= beginToken.end) {
+ if (offset <= beginToken.end) {
_addSuggestion(Keyword.COVARIANT);
_addSuggestion(Keyword.DYNAMIC);
_addSuggestion(Keyword.VOID);
@@ -679,6 +679,22 @@
}
@override
+ void visitSimpleFormalParameter(SimpleFormalParameter node) {
+ var entity = this.entity;
+ if (node.type == entity && entity is GenericFunctionType) {
+ var offset = request.offset;
+ var returnType = entity.returnType;
+ if ((returnType == null && offset < entity.offset) ||
+ (returnType != null &&
+ offset >= returnType.offset &&
+ offset < returnType.end)) {
+ _addSuggestion(Keyword.DYNAMIC);
+ _addSuggestion(Keyword.VOID);
+ }
+ }
+ }
+
+ @override
void visitSpreadElement(SpreadElement node) {
_addExpressionKeywords(node);
return super.visitSpreadElement(node);
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index baa577fc..8ace81f 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -108,7 +108,7 @@
'1+void',
'1-null',
'2+Arrays',
- '2-void',
+ '2+void',
'2-null'
]);
diff --git a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
index 14b5877..d131792 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
@@ -17,6 +17,7 @@
defineReflectiveTests(ExpressionFunctionBodyCompletionTest);
defineReflectiveTests(ExtensionCompletionTest);
defineReflectiveTests(FormalParameterCompletionTest);
+ defineReflectiveTests(GenericFunctionTypeCompletionTest);
defineReflectiveTests(GenericTypeAliasCompletionTest);
defineReflectiveTests(PropertyAccessCompletionTest);
defineReflectiveTests(RedirectedConstructorCompletionTest);
@@ -405,6 +406,57 @@
}
@reflectiveTest
+class GenericFunctionTypeCompletionTest extends CompletionTestCase {
+ Future<void> test_returnType_beforeType() async {
+ addTestFile('''
+void f({^vo Function() p}) {}
+''');
+ await getSuggestions();
+ assertHasCompletion('void');
+ }
+
+ Future<void> test_returnType_beforeType_afterRequired() async {
+ addTestFile('''
+void f({required ^vo Function() p}) {}
+''');
+ await getSuggestions();
+ assertHasCompletion('void');
+ }
+
+ Future<void> test_returnType_inType() async {
+ addTestFile('''
+void f({v^o Function() p}) {}
+''');
+ await getSuggestions();
+ assertHasCompletion('void');
+ }
+
+ Future<void> test_returnType_inType_afterRequired() async {
+ addTestFile('''
+void f({required v^o Function() p}) {}
+''');
+ await getSuggestions();
+ assertHasCompletion('void');
+ }
+
+ Future<void> test_returnType_partialFunctionType() async {
+ addTestFile('''
+void f({^ Function() p}) {}
+''');
+ await getSuggestions();
+ assertHasCompletion('void');
+ }
+
+ Future<void> test_returnType_partialFunctionType_afterRequired() async {
+ addTestFile('''
+void f({required ^ Function() p}) {}
+''');
+ await getSuggestions();
+ assertHasCompletion('void');
+ }
+}
+
+@reflectiveTest
class GenericTypeAliasCompletionTest extends CompletionTestCase {
Future<void> test_returnType_void() async {
addTestFile('''