mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:19:47 +00:00
16e4709922
Change-Id: I6c1e35f944a7e551882745e74c9570086bc53b56 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210422 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
384 lines
11 KiB
Dart
384 lines
11 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_generated.dart' as lsp;
|
|
import 'package:analyzer_plugin/protocol/protocol_common.dart';
|
|
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
|
|
import 'package:test/test.dart';
|
|
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|
|
|
import 'server_abstract.dart';
|
|
|
|
void main() {
|
|
defineReflectiveSuite(() {
|
|
defineReflectiveTests(DefinitionTest);
|
|
});
|
|
}
|
|
|
|
@reflectiveTest
|
|
class DefinitionTest extends AbstractLspAnalysisServerTest {
|
|
Future<void> test_acrossFiles() async {
|
|
final mainContents = '''
|
|
import 'referenced.dart';
|
|
|
|
main() {
|
|
fo^o();
|
|
}
|
|
''';
|
|
|
|
final referencedContents = '''
|
|
/// Ensure the function is on a line that
|
|
/// does not exist in the mainContents file
|
|
/// to ensure we're translating offsets to line/col
|
|
/// using the correct file's LineInfo
|
|
/// ...
|
|
/// ...
|
|
/// ...
|
|
/// ...
|
|
/// ...
|
|
[[foo]]() {}
|
|
''';
|
|
|
|
final referencedFileUri =
|
|
Uri.file(join(projectFolderPath, 'lib', 'referenced.dart'));
|
|
|
|
await initialize();
|
|
await openFile(mainFileUri, withoutMarkers(mainContents));
|
|
await openFile(referencedFileUri, withoutMarkers(referencedContents));
|
|
final res = await getDefinitionAsLocation(
|
|
mainFileUri, positionFromMarker(mainContents));
|
|
|
|
expect(res, hasLength(1));
|
|
var loc = res.single;
|
|
expect(loc.range, equals(rangeFromMarkers(referencedContents)));
|
|
expect(loc.uri, equals(referencedFileUri.toString()));
|
|
}
|
|
|
|
Future<void> test_comment_adjacentReference() async {
|
|
/// Computing Dart navigation locates a node at the provided offset then
|
|
/// returns all navigation regions inside it. This test ensures we filter
|
|
/// out any regions that are in the same target node (the comment) but do
|
|
/// not span the requested offset.
|
|
final contents = '''
|
|
/// Te^st
|
|
///
|
|
/// References [String].
|
|
main() {}
|
|
''';
|
|
|
|
await initialize();
|
|
await openFile(mainFileUri, withoutMarkers(contents));
|
|
final res = await getDefinitionAsLocation(
|
|
mainFileUri, positionFromMarker(contents));
|
|
|
|
expect(res, hasLength(0));
|
|
}
|
|
|
|
Future<void> test_fromPlugins() async {
|
|
final pluginAnalyzedFilePath = join(projectFolderPath, 'lib', 'foo.foo');
|
|
final pluginAnalyzedFileUri = Uri.file(pluginAnalyzedFilePath);
|
|
final pluginResult = plugin.AnalysisGetNavigationResult(
|
|
[pluginAnalyzedFilePath],
|
|
[NavigationTarget(ElementKind.CLASS, 0, 0, 5, 0, 0)],
|
|
[
|
|
NavigationRegion(0, 5, [0])
|
|
],
|
|
);
|
|
configureTestPlugin(respondWith: pluginResult);
|
|
|
|
newFile(pluginAnalyzedFilePath);
|
|
await initialize();
|
|
final res = await getDefinitionAsLocation(
|
|
pluginAnalyzedFileUri, lsp.Position(line: 0, character: 0));
|
|
|
|
expect(res, hasLength(1));
|
|
var loc = res.single;
|
|
expect(
|
|
loc.range,
|
|
equals(lsp.Range(
|
|
start: lsp.Position(line: 0, character: 0),
|
|
end: lsp.Position(line: 0, character: 5))));
|
|
expect(loc.uri, equals(pluginAnalyzedFileUri.toString()));
|
|
}
|
|
|
|
Future<void> test_locationLink_field() async {
|
|
final mainContents = '''
|
|
import 'referenced.dart';
|
|
|
|
main() {
|
|
Icons.[[ad^d]]();
|
|
}
|
|
''';
|
|
|
|
final referencedContents = '''
|
|
void unrelatedFunction() {}
|
|
|
|
class Icons {
|
|
/// `targetRange` should not include the dartDoc but should include the full
|
|
/// function body. `targetSelectionRange` will be just the name.
|
|
[[String add = "Test"]];
|
|
}
|
|
|
|
void otherUnrelatedFunction() {}
|
|
''';
|
|
|
|
final referencedFileUri =
|
|
Uri.file(join(projectFolderPath, 'lib', 'referenced.dart'));
|
|
|
|
await initialize(
|
|
textDocumentCapabilities:
|
|
withLocationLinkSupport(emptyTextDocumentClientCapabilities));
|
|
await openFile(mainFileUri, withoutMarkers(mainContents));
|
|
await openFile(referencedFileUri, withoutMarkers(referencedContents));
|
|
final res = await getDefinitionAsLocationLinks(
|
|
mainFileUri, positionFromMarker(mainContents));
|
|
|
|
expect(res, hasLength(1));
|
|
var loc = res.single;
|
|
expect(loc.originSelectionRange, equals(rangeFromMarkers(mainContents)));
|
|
expect(loc.targetUri, equals(referencedFileUri.toString()));
|
|
expect(loc.targetRange, equals(rangeFromMarkers(referencedContents)));
|
|
expect(
|
|
loc.targetSelectionRange,
|
|
equals(rangeOfString(referencedContents, 'add')),
|
|
);
|
|
}
|
|
|
|
Future<void> test_locationLink_function() async {
|
|
final mainContents = '''
|
|
import 'referenced.dart';
|
|
|
|
main() {
|
|
[[fo^o]]();
|
|
}
|
|
''';
|
|
|
|
final referencedContents = '''
|
|
void unrelatedFunction() {}
|
|
|
|
/// `targetRange` should not include the dartDoc but should include the full
|
|
/// function body. `targetSelectionRange` will be just the name.
|
|
[[void foo() {
|
|
// Contents of function
|
|
}]]
|
|
|
|
void otherUnrelatedFunction() {}
|
|
''';
|
|
|
|
final referencedFileUri =
|
|
Uri.file(join(projectFolderPath, 'lib', 'referenced.dart'));
|
|
|
|
await initialize(
|
|
textDocumentCapabilities:
|
|
withLocationLinkSupport(emptyTextDocumentClientCapabilities));
|
|
await openFile(mainFileUri, withoutMarkers(mainContents));
|
|
await openFile(referencedFileUri, withoutMarkers(referencedContents));
|
|
final res = await getDefinitionAsLocationLinks(
|
|
mainFileUri, positionFromMarker(mainContents));
|
|
|
|
expect(res, hasLength(1));
|
|
var loc = res.single;
|
|
expect(loc.originSelectionRange, equals(rangeFromMarkers(mainContents)));
|
|
expect(loc.targetUri, equals(referencedFileUri.toString()));
|
|
expect(loc.targetRange, equals(rangeFromMarkers(referencedContents)));
|
|
expect(
|
|
loc.targetSelectionRange,
|
|
equals(rangeOfString(referencedContents, 'foo')),
|
|
);
|
|
}
|
|
|
|
Future<void> test_macro_simpleIdentifier_getter() async {
|
|
final macroAnnotationsContents = '''
|
|
library analyzer.macro.annotations;
|
|
const observable = 0;
|
|
''';
|
|
|
|
final mainContents = '''
|
|
import 'macro_annotations.dart';
|
|
|
|
class A {
|
|
@observable
|
|
int _foo = 0;
|
|
}
|
|
|
|
void f(A a) {
|
|
a.[[foo^]];
|
|
}
|
|
''';
|
|
|
|
final combinedContents = r'''
|
|
import 'macro_annotations.dart';
|
|
|
|
class A {
|
|
@observable
|
|
int _foo = 0;
|
|
|
|
int get [[foo]] => _foo;
|
|
|
|
set foo(int val) {
|
|
print('Setting foo to ${val}');
|
|
_foo = val;
|
|
}
|
|
}
|
|
|
|
void f(A a) {
|
|
a.[[foo^]];
|
|
}
|
|
''';
|
|
|
|
final macroAnnotationsFileUri =
|
|
Uri.file(join(projectFolderPath, 'lib', 'macro_annotations.dart'));
|
|
final pubspecFileUri = Uri.file(join(projectFolderPath, 'pubspec.yaml'));
|
|
final combinedFileUri = Uri.file(join(projectFolderPath, '.dart_tool',
|
|
'analyzer', 'macro', 'lib', 'main.dart'));
|
|
|
|
await initialize(
|
|
textDocumentCapabilities:
|
|
withLocationLinkSupport(emptyTextDocumentClientCapabilities));
|
|
await openFile(pubspecFileUri, '');
|
|
await openFile(
|
|
macroAnnotationsFileUri, withoutMarkers(macroAnnotationsContents));
|
|
await openFile(mainFileUri, withoutMarkers(mainContents));
|
|
final res = await getDefinitionAsLocationLinks(
|
|
mainFileUri, positionFromMarker(mainContents));
|
|
|
|
expect(res, hasLength(1));
|
|
final loc = res.single;
|
|
expect(loc.originSelectionRange, equals(rangeFromMarkers(mainContents)));
|
|
expect(loc.targetUri, equals(combinedFileUri.toString()));
|
|
|
|
final getFooRange = rangesFromMarkers(combinedContents)[0];
|
|
expect(loc.targetRange, equals(getFooRange));
|
|
expect(loc.targetSelectionRange, equals(getFooRange));
|
|
}
|
|
|
|
Future<void> test_nonDartFile() async {
|
|
newFile(pubspecFilePath, content: simplePubspecContent);
|
|
await initialize();
|
|
|
|
final res = await getDefinitionAsLocation(pubspecFileUri, startOfDocPos);
|
|
expect(res, isEmpty);
|
|
}
|
|
|
|
Future<void> test_part() async {
|
|
final mainContents = '''
|
|
import 'lib.dart';
|
|
|
|
main() {
|
|
Icons.[[ad^d]]();
|
|
}
|
|
''';
|
|
|
|
final libContents = '''
|
|
part 'part.dart';
|
|
''';
|
|
|
|
final partContents = '''
|
|
part of 'lib.dart';
|
|
|
|
void unrelatedFunction() {}
|
|
|
|
class Icons {
|
|
/// `targetRange` should not include the dartDoc but should include the full
|
|
/// function body. `targetSelectionRange` will be just the name.
|
|
[[String add = "Test"]];
|
|
}
|
|
|
|
void otherUnrelatedFunction() {}
|
|
''';
|
|
|
|
final libFileUri = Uri.file(join(projectFolderPath, 'lib', 'lib.dart'));
|
|
final partFileUri = Uri.file(join(projectFolderPath, 'lib', 'part.dart'));
|
|
|
|
await initialize(
|
|
textDocumentCapabilities:
|
|
withLocationLinkSupport(emptyTextDocumentClientCapabilities));
|
|
await openFile(mainFileUri, withoutMarkers(mainContents));
|
|
await openFile(libFileUri, withoutMarkers(libContents));
|
|
await openFile(partFileUri, withoutMarkers(partContents));
|
|
final res = await getDefinitionAsLocationLinks(
|
|
mainFileUri, positionFromMarker(mainContents));
|
|
|
|
expect(res, hasLength(1));
|
|
var loc = res.single;
|
|
expect(loc.originSelectionRange, equals(rangeFromMarkers(mainContents)));
|
|
expect(loc.targetUri, equals(partFileUri.toString()));
|
|
expect(loc.targetRange, equals(rangeFromMarkers(partContents)));
|
|
expect(
|
|
loc.targetSelectionRange,
|
|
equals(rangeOfString(partContents, 'add')),
|
|
);
|
|
}
|
|
|
|
Future<void> test_sameLine() async {
|
|
final contents = '''
|
|
int plusOne(int [[value]]) => 1 + val^ue;
|
|
''';
|
|
|
|
await initialize();
|
|
await openFile(mainFileUri, withoutMarkers(contents));
|
|
final res = await getDefinitionAsLocation(
|
|
mainFileUri, positionFromMarker(contents));
|
|
|
|
expect(res, hasLength(1));
|
|
var loc = res.single;
|
|
expect(loc.range, equals(rangeFromMarkers(contents)));
|
|
expect(loc.uri, equals(mainFileUri.toString()));
|
|
}
|
|
|
|
Future<void> test_singleFile() async {
|
|
final contents = '''
|
|
[[foo]]() {
|
|
fo^o();
|
|
}
|
|
''';
|
|
|
|
await initialize();
|
|
await openFile(mainFileUri, withoutMarkers(contents));
|
|
final res = await getDefinitionAsLocation(
|
|
mainFileUri, positionFromMarker(contents));
|
|
|
|
expect(res, hasLength(1));
|
|
var loc = res.single;
|
|
expect(loc.range, equals(rangeFromMarkers(contents)));
|
|
expect(loc.uri, equals(mainFileUri.toString()));
|
|
}
|
|
|
|
Future<void> test_unopenFile() async {
|
|
final contents = '''
|
|
[[foo]]() {
|
|
fo^o();
|
|
}
|
|
''';
|
|
|
|
newFile(mainFilePath, content: withoutMarkers(contents));
|
|
await initialize();
|
|
final res = await getDefinitionAsLocation(
|
|
mainFileUri, positionFromMarker(contents));
|
|
|
|
expect(res, hasLength(1));
|
|
var loc = res.single;
|
|
expect(loc.range, equals(rangeFromMarkers(contents)));
|
|
expect(loc.uri, equals(mainFileUri.toString()));
|
|
}
|
|
|
|
Future<void> test_varKeyword() async {
|
|
final contents = '''
|
|
va^r a = MyClass();
|
|
|
|
class [[MyClass]] {}
|
|
''';
|
|
|
|
await initialize();
|
|
await openFile(mainFileUri, withoutMarkers(contents));
|
|
final res = await getDefinitionAsLocation(
|
|
mainFileUri, positionFromMarker(contents));
|
|
|
|
expect(res, hasLength(1));
|
|
var loc = res.single;
|
|
expect(loc.range, equals(rangeFromMarkers(contents)));
|
|
expect(loc.uri, equals(mainFileUri.toString()));
|
|
}
|
|
}
|