[wildcards] hover tests

See: https://github.com/dart-lang/sdk/issues/55681

Change-Id: I58630feb6e8b35b00d90d20c305a2f0ca9b37e4b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/382042
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart
index 03be073..7e465e8 100644
--- a/pkg/analysis_server/test/lsp/hover_test.dart
+++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -81,6 +81,25 @@
     expect(markup.value, matcher);
   }
 
+  Future<void> assertNullHover(
+    String content, {
+    bool waitForAnalysis = false,
+    bool withOpenFile = true,
+  }) async {
+    var code = TestCode.parse(content);
+
+    var initialAnalysis = waitForAnalysis ? waitForAnalysisComplete() : null;
+    await initialize();
+    if (withOpenFile) {
+      await openFile(mainFileUri, code.code);
+    } else {
+      newFile(mainFilePath, code.code);
+    }
+    await initialAnalysis;
+    var hover = await getHover(mainFileUri, code.position.position);
+    expect(hover, isNull);
+  }
+
   Future<void> assertPlainTextContents(String content, Matcher matcher) async {
     setHoverContentFormat([MarkupKind.PlainText]);
     var code = TestCode.parse(content);
@@ -185,6 +204,23 @@
     await assertStringContents(content, equals(expected));
   }
 
+  Future<void> test_field_underscore() async {
+    var content = '''
+class A {
+  int _ = 1;
+  int f() => [!^_!];
+}
+''';
+    var expected = '''
+```dart
+int _
+```
+Type: `int`
+
+*package:test/main.dart*''';
+    await assertStringContents(content, equals(expected));
+  }
+
   Future<void> test_forLoop_declaredVariable() async {
     var content = '''
 void f() {
@@ -240,6 +276,20 @@
     );
   }
 
+  Future<void> test_localVariable_wildcard() async {
+    var content = '''
+f() {
+  int [!^_!] = 0;
+}
+''';
+    var expected = '''
+```dart
+int _
+```
+Type: `int`''';
+    await assertStringContents(content, equals(expected));
+  }
+
   Future<void> test_markdown_isFormattedForDisplay() async {
     var content = '''
     /// This is a string.
@@ -306,6 +356,23 @@
         contains('This is a method.'),
       );
 
+  Future<void> test_method_underscore() async {
+    var content = '''
+class A {
+  int _() => 1;
+  int f() => [!^_!]();
+}
+''';
+    var expected = '''
+```dart
+int _()
+```
+Type: `int Function()`
+
+*package:test/main.dart*''';
+    await assertStringContents(content, equals(expected));
+  }
+
   Future<void> test_noElement() async {
     var code = TestCode.parse('''
     String? abc;
@@ -346,6 +413,18 @@
     await assertStringContents(content, equals(expectedHoverContent));
   }
 
+  Future<void> test_parameter_wildcard() async {
+    var content = '''
+f(int [!^_!]) { }
+''';
+    var expected = '''
+```dart
+int _
+```
+Type: `int`''';
+    await assertStringContents(content, equals(expected));
+  }
+
   Future<void> test_pattern_assignment_left() => assertStringContents(
         '''
 void f(String a, String b) {
@@ -807,6 +886,50 @@
     await assertStringContents(content, equals(expected));
   }
 
+  Future<void> test_topLevelFunction_underscore() async {
+    var content = '''
+int _() => 1;
+int f() => [!^_!]();
+''';
+    var expected = '''
+```dart
+int _()
+```
+Type: `int Function()`
+
+*package:test/main.dart*''';
+    await assertStringContents(content, equals(expected));
+  }
+
+  Future<void> test_topLevelVariable_underscore() async {
+    var content = '''
+int _ = 1;
+int f() => [!^_!];
+''';
+    var expected = '''
+```dart
+int _
+```
+Type: `int`
+
+*package:test/main.dart*''';
+    await assertStringContents(content, equals(expected));
+  }
+
+  Future<void> test_typeParameter() async {
+    var content = '''
+class C<[!^T!]> {}
+''';
+    await assertNullHover(content);
+  }
+
+  Future<void> test_typeParameter_wildcard() async {
+    var content = '''
+class C<[!^_!]> {}
+''';
+    await assertNullHover(content);
+  }
+
   Future<void> test_unnamed_library_directive() async {
     var content = '''
 /// This is a string.