Files
sdk/pkg/analysis_server/test/lsp/hover_test.dart
T
Danny Tuppeny 80fb1a56db [analysis_server] Add shared protocol.dart file for LSP
In an upcoming change some types will between these files. To reduce the size of that (already very large) CL and because the distinction between spec-generated/custom-generated types was unnecessary anyway, this adds a single import for LSP protocol-related types.

Change-Id: I322447d6c979538c12014d87875176e1bf2adca7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/244244
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
2022-05-11 15:28:35 +00:00

365 lines
10 KiB
Dart

// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/lsp_protocol/protocol.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../tool/lsp_spec/matchers.dart';
import 'server_abstract.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(HoverTest);
});
}
@reflectiveTest
class HoverTest extends AbstractLspAnalysisServerTest {
Future<void> test_dartDoc_macros() async {
final content = '''
/// {@template template_name}
/// This is shared content.
/// {@endtemplate}
const String foo = null;
/// {@macro template_name}
const String [[f^oo2]] = null;
''';
final initialAnalysis = waitForAnalysisComplete();
await initialize();
await openFile(mainFileUri, withoutMarkers(content));
await initialAnalysis;
var hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
expect(_getStringContents(hover), endsWith('This is shared content.'));
}
Future<void> test_hover_bad_position() async {
await initialize();
await openFile(mainFileUri, '');
await expectLater(
() => getHover(mainFileUri, Position(line: 999, character: 999)),
throwsA(isResponseError(ServerErrorCodes.InvalidFileLineCol)),
);
}
Future<void> test_markdown_isFormattedForDisplay() async {
final content = '''
/// This is a string.
///
/// {@template foo}
/// With some [refs] and some
/// [links](https://www.dartlang.org/)
/// {@endTemplate foo}
///
/// ```dart sample
/// print();
/// ```
String [[a^bc]];
''';
final expectedHoverContent = '''
```dart
String abc
```
Type: `String`
*package:test/main.dart*
---
This is a string.
With some [refs] and some
[links](https://www.dartlang.org/)
```dart
print();
```
'''
.trim();
await initialize(
textDocumentCapabilities: withHoverContentFormat(
emptyTextDocumentClientCapabilities, [MarkupKind.Markdown]));
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
expect(hover.contents, isNotNull);
final markup = _getMarkupContents(hover);
expect(markup.kind, equals(MarkupKind.Markdown));
expect(markup.value, equals(expectedHoverContent));
}
Future<void> test_markdown_simple() async {
final content = '''
/// This is a string.
String [[a^bc]];
''';
await initialize(
textDocumentCapabilities: withHoverContentFormat(
emptyTextDocumentClientCapabilities, [MarkupKind.Markdown]));
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
expect(hover.contents, isNotNull);
final markup = _getMarkupContents(hover);
expect(markup.kind, equals(MarkupKind.Markdown));
expect(markup.value, contains('This is a string.'));
}
Future<void> test_noElement() async {
final content = '''
String abc;
^
int a;
''';
await initialize(
textDocumentCapabilities: withHoverContentFormat(
emptyTextDocumentClientCapabilities, [MarkupKind.Markdown]));
await openFile(mainFileUri, withoutMarkers(content));
var hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNull);
}
Future<void> test_nonDartFile() async {
await initialize();
await openFile(pubspecFileUri, simplePubspecContent);
final hover = await getHover(pubspecFileUri, startOfDocPos);
expect(hover, isNull);
}
Future<void> test_nullableTypes() async {
final content = '''
String? [[a^bc]];
''';
final expectedHoverContent = '''
```dart
String? abc
```
Type: `String?`
*package:test/main.dart*
'''
.trim();
await initialize();
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
expect(hover.contents, isNotNull);
expect(_getStringContents(hover), equals(expectedHoverContent));
}
Future<void> test_plainText_simple() async {
final content = '''
/// This is a string.
String [[a^bc]];
''';
await initialize(
textDocumentCapabilities: withHoverContentFormat(
emptyTextDocumentClientCapabilities, [MarkupKind.PlainText]));
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
expect(hover.contents, isNotNull);
// Ensure we got PlainText back as the type, even though we're sending the
// same markdown content.
final markup = _getMarkupContents(hover);
expect(markup.kind, equals(MarkupKind.PlainText));
expect(markup.value, contains('This is a string.'));
}
Future<void> test_promotedTypes() async {
final content = '''
void f(aaa) {
if (aaa is String) {
print([[aa^a]]);
}
}
''';
final expectedHoverContent = '''
```dart
dynamic aaa
```
Type: `String`
'''
.trim();
await initialize();
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
expect(hover.contents, isNotNull);
expect(_getStringContents(hover), equals(expectedHoverContent));
}
Future<void> test_range_multiLineConstructorCall() async {
final content = '''
final a = new [[Str^ing.fromCharCodes]]([
1,
2,
]);
''';
await initialize();
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
}
Future<void> test_signatureFormatting_multiLine() async {
final content = '''
class Foo {
Foo(String arg1, String arg2, [String arg3]);
}
void f() {
var a = Fo^o();
}
''';
await initialize();
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
final contents = _getStringContents(hover!);
expect(contents, startsWith('''
```dart
(new) Foo Foo(
String arg1,
String arg2, [
String arg3,
])
```'''));
}
Future<void> test_signatureFormatting_singleLine() async {
final content = '''
class Foo {
Foo(String a, String b);
}
void f() {
var a = Fo^o();
}
''';
await initialize();
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
final contents = _getStringContents(hover!);
expect(contents, startsWith('''
```dart
(new) Foo Foo(String a, String b)
```'''));
}
Future<void> test_string_noDocComment() async {
final content = '''
String [[a^bc]];
''';
final expectedHoverContent = '''
```dart
String abc
```
Type: `String`
*package:test/main.dart*
'''
.trim();
await initialize();
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
expect(hover.contents, isNotNull);
expect(_getStringContents(hover), equals(expectedHoverContent));
}
Future<void> test_string_reflectsLatestEdits() async {
final original = '''
/// Original string.
String [[a^bc]];
''';
final updated = '''
/// Updated string.
String [[a^bc]];
''';
await initialize();
await openFile(mainFileUri, withoutMarkers(original));
var hover = await getHover(mainFileUri, positionFromMarker(original));
expect(hover, isNotNull);
var contents = _getStringContents(hover!);
expect(contents, contains('Original'));
await replaceFile(222, mainFileUri, withoutMarkers(updated));
hover = await getHover(mainFileUri, positionFromMarker(updated));
expect(hover, isNotNull);
contents = _getStringContents(hover!);
expect(contents, contains('Updated'));
}
Future<void> test_string_simple() async {
final content = '''
/// This is a string.
String [[a^bc]];
''';
await initialize();
await openFile(mainFileUri, withoutMarkers(content));
final hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
expect(hover.contents, isNotNull);
final contents = _getStringContents(hover);
expect(contents, contains('This is a string.'));
}
Future<void> test_unopenFile() async {
final content = '''
/// This is a string.
String [[a^bc]];
''';
newFile(mainFilePath, withoutMarkers(content));
await initialize();
final hover = await getHover(mainFileUri, positionFromMarker(content));
expect(hover, isNotNull);
expect(hover!.range, equals(rangeFromMarkers(content)));
expect(hover.contents, isNotNull);
final markup = _getStringContents(hover);
expect(markup, contains('This is a string.'));
}
MarkupContent _getMarkupContents(Hover hover) {
return hover.contents.map(
(t1) => throw 'Hover contents were String, not MarkupContent',
(t2) => t2,
);
}
String _getStringContents(Hover hover) {
return hover.contents.map(
(t1) => t1,
(t2) => throw 'Hover contents were MarkupContent, not String',
);
}
}