blob: 10c432331307fdab68be51229419ad93f9155b3a [file] [log] [blame]
// 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/lsp_protocol/protocol_special.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'server_abstract.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(FileModificationTest);
});
}
@reflectiveTest
class FileModificationTest extends AbstractLspAnalysisServerTest {
Future<void> test_change_badPosition() async {
final contents = '';
await initialize(
// Error is expected and checked below.
failTestOnAnyErrorNotification: false,
);
await openFile(mainFileUri, contents);
// Since this is a notification and not a request, the server cannot
// respond with an error, but instead sends a ShowMessage notification
// to alert the user to something failing.
final error = await expectErrorNotification(() async {
await changeFile(222, mainFileUri, [
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
range: Range(
start: Position(line: 999, character: 999),
end: Position(line: 999, character: 999)),
text: ' ',
))
]);
});
expect(error.message, contains('Invalid line'));
}
Future<void> test_change_fullContents() async {
final initialContent = 'int a = 1;';
final updatedContent = 'int a = 2;';
await initialize();
await openFile(mainFileUri, initialContent);
await replaceFile(222, mainFileUri, updatedContent);
expect(_getOverlay(mainFilePath), equals(updatedContent));
final documentVersion = server.getVersionedDocumentIdentifier(mainFilePath);
expect(documentVersion.version, equals(222));
}
Future<void> test_change_incremental() async {
final initialContent = '0123456789\n0123456789';
final expectedUpdatedContent = '0123456789\n01234 89';
await initialize();
await openFile(mainFileUri, initialContent);
await changeFile(222, mainFileUri, [
// Replace line1:5-1:8 with spaces.
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
range: Range(
start: Position(line: 1, character: 5),
end: Position(line: 1, character: 8)),
text: ' ',
))
]);
expect(_getOverlay(mainFilePath), equals(expectedUpdatedContent));
final documentVersion = server.getVersionedDocumentIdentifier(mainFilePath);
expect(documentVersion.version, equals(222));
}
Future<void> test_change_unopenedFile() async {
// It's not valid for a client to send a request to modify a file that it
// has not opened, but Visual Studio has done it in the past so we should
// ensure it generates an obvious error that the user can understand.
final simpleEdit = Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
range: Range(
start: Position(line: 1, character: 1),
end: Position(line: 1, character: 1)),
text: 'test',
));
await initialize(
// Error is expected and checked below.
failTestOnAnyErrorNotification: false,
);
final notificationParams = await expectErrorNotification(
() => changeFile(222, mainFileUri, [simpleEdit]),
);
expect(notificationParams, isNotNull);
expect(
notificationParams.message,
allOf(
contains('because the file was not previously opened'),
contains(mainFilePath),
),
);
}
Future<void> test_close() async {
final initialContent = 'int a = 1;';
final updatedContent = 'int a = 2;';
await initialize();
await openFile(mainFileUri, initialContent);
await replaceFile(222, mainFileUri, updatedContent);
await closeFile(mainFileUri);
expect(_getOverlay(mainFilePath), isNull);
// When we close a file, we expect the version in the versioned identifier to
// return to `null`.
final documentVersion = server.getVersionedDocumentIdentifier(mainFilePath);
expect(documentVersion.version, isNull);
}
Future<void> test_open() async {
const testContent = 'CONTENT';
await initialize();
expect(_getOverlay(mainFilePath), isNull);
await openFile(mainFileUri, testContent, version: 2);
expect(_getOverlay(mainFilePath), equals(testContent));
// The version for a file that's just been opened (and never modified) is
// `null` (this means the contents match what's on disk).
final documentVersion = server.getVersionedDocumentIdentifier(mainFilePath);
expect(documentVersion.version, 2);
}
Future<void> test_open_invalidPath() async {
await initialize(
// Error is expected and checked below.
failTestOnAnyErrorNotification: false,
);
final notificationParams = await expectErrorNotification(
() => openFile(Uri.http('localhost', 'not-a-file'), ''),
);
expect(notificationParams, isNotNull);
expect(
notificationParams.message,
contains('URI was not a valid file:// URI'),
);
}
String? _getOverlay(String path) {
if (server.resourceProvider.hasOverlay(path)) {
return server.resourceProvider.getFile(path).readAsStringSync();
}
return null;
}
}