80fb1a56db
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>
365 lines
10 KiB
Dart
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',
|
|
);
|
|
}
|
|
}
|