blob: 96005189493445fdcc6b5b5390c369fe3dcabb8b [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.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/test_utilities/test_code_format.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../utils/test_code_extensions.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 {
var content = '''
class Foo {
void a() { /*1*/ }
void b() { /*2*/ }
}
''';
await initialize();
await openFile(mainFileUri, content);
var lineInfo = LineInfo.fromContent(content);
// Send a request for two positions.
var regions = await getSelectionRanges(mainFileUri, [
positionFromOffset(content.indexOf('/*1*/'), content),
positionFromOffset(content.indexOf('/*2*/'), content),
]);
expect(regions!.length, equals(2));
var firstTexts =
_getSelectionRangeText(lineInfo, content, regions[0]).toList();
var 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 {
var code = TestCode.parse('''
class Foo<T> {
void a(String b) {
print((1 ^+ 2) * 3);
}
}
''');
await initialize();
await openFile(mainFileUri, code.code);
var lineInfo = LineInfo.fromContent(code.code);
// The returned List corresponds to the input list of positions, and not
// the set of ranges - each range within that list has a (recursive) parent
// to walk up all ranges for that position.
var regions =
await getSelectionRanges(mainFileUri, [code.position.position]);
expect(regions!.length, equals(1)); // Only one position was sent.
var regionTexts =
_getSelectionRangeText(lineInfo, code.code, 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);
var parent = range.parent;
if (parent != null) {
yield* _getSelectionRangeText(lineInfo, content, parent);
}
}
String _rangeOfText(LineInfo lineInfo, String content, Range range) {
var startPos = range.start;
var endPos = range.end;
var start = lineInfo.getOffsetOfLine(startPos.line) + startPos.character;
var end = lineInfo.getOffsetOfLine(endPos.line) + endPos.character;
return content.substring(start, end);
}
}