| // 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_generated.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(999, 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 |
| ``` |
| *lib/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_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_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_string_noDocComment() async { |
| final content = ''' |
| String [[a^bc]]; |
| '''; |
| |
| final expectedHoverContent = ''' |
| ```dart |
| String abc |
| ``` |
| *lib/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)); |
| var contents = _getStringContents(hover); |
| expect(contents, contains('Original')); |
| |
| await replaceFile(222, mainFileUri, withoutMarkers(updated)); |
| hover = await getHover(mainFileUri, positionFromMarker(updated)); |
| 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, content: 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', |
| ); |
| } |
| } |