blob: 2a4da460c64e0a9b1e70285d4e3d2b2baf558258 [file] [log] [blame]
// Copyright (c) 2021, 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:analyzer/source/line_info.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'server_abstract.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(SelectionRangeTest);
});
}
/// Additional tests are in
///
/// test/src/computer/selection_range_computer_test.dart
@reflectiveTest
class SelectionRangeTest extends AbstractLspAnalysisServerTest {
Future<void> test_multiple() async {
final content = '''
class Foo {
void a() { /*1*/ }
void b() { /*2*/ }
}
''';
await initialize();
await openFile(mainFileUri, content);
final lineInfo = LineInfo.fromContent(content);
// Send a request for two positions.
final regions = await getSelectionRanges(mainFileUri, [
positionFromOffset(content.indexOf('/*1*/'), content),
positionFromOffset(content.indexOf('/*2*/'), content),
]);
expect(regions!.length, equals(2));
final firstTexts =
_getSelectionRangeText(lineInfo, content, regions[0]).toList();
final secondTexts =
_getSelectionRangeText(lineInfo, content, regions[1]).toList();
expect(
firstTexts,
equals([
'{ /*1*/ }',
'void a() { /*1*/ }',
content.trim(), // Whole content minus the trailing newline
]));
expect(
secondTexts,
equals([
'{ /*2*/ }',
'void b() { /*2*/ }',
content.trim(), // Whole content minus the trailing newline
]));
}
Future<void> test_single() async {
final content = '''
class Foo<T> {
void a(String b) {
print((1 ^+ 2) * 3);
}
}
''';
final contentWithoutMarker = withoutMarkers(content);
await initialize();
await openFile(mainFileUri, contentWithoutMarker);
final lineInfo = LineInfo.fromContent(contentWithoutMarker);
// The returned List corresponds to the input list of positions, and not
// the set of ranges - each range within that list has a (recusrive) parent
// to walk up all ranges for that position.
final regions =
await getSelectionRanges(mainFileUri, [positionFromMarker(content)]);
expect(regions!.length, equals(1)); // Only one position was sent.
final regionTexts =
_getSelectionRangeText(lineInfo, contentWithoutMarker, regions.first)
.toList();
expect(
regionTexts,
equals([
'1 + 2',
'(1 + 2)',
'(1 + 2) * 3',
'((1 + 2) * 3)',
'print((1 + 2) * 3)',
'print((1 + 2) * 3);',
'{\n print((1 + 2) * 3);\n }',
'void a(String b) {\n print((1 + 2) * 3);\n }',
'class Foo<T> {\n void a(String b) {\n print((1 + 2) * 3);\n }\n}',
]));
}
Iterable<String> _getSelectionRangeText(
LineInfo lineInfo, String content, SelectionRange range) sync* {
yield _rangeOfText(lineInfo, content, range.range);
final parent = range.parent;
if (parent != null) {
yield* _getSelectionRangeText(lineInfo, content, parent);
}
}
String _rangeOfText(LineInfo lineInfo, String content, Range range) {
final startPos = range.start;
final endPos = range.end;
final start = lineInfo.getOffsetOfLine(startPos.line) + startPos.character;
final end = lineInfo.getOffsetOfLine(endPos.line) + endPos.character;
return content.substring(start, end);
}
}