Improve testing of document versions in LSP renames
Change-Id: Ibbf562d6a99d73c00fc17521eb8576da4c708c06
Reviewed-on: https://dart-review.googlesource.com/c/89522
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/test/lsp/rename_test.dart b/pkg/analysis_server/test/lsp/rename_test.dart
index 6226b60..df2fc18 100644
--- a/pkg/analysis_server/test/lsp/rename_test.dart
+++ b/pkg/analysis_server/test/lsp/rename_test.dart
@@ -17,9 +17,6 @@
@reflectiveTest
class RenameTest extends AbstractLspAnalysisServerTest {
- // TODO(dantup): send a rename without a version
- // TODO(dantup): send an old version of the doc?
- // TODO(dantup): check the version returned matches?
// TODO(dantup): renames across multiple files
test_prepare_class() {
@@ -122,6 +119,23 @@
content, 'MyNewClass', expectedContent);
}
+ test_rename_withoutVersionedIdentifier() {
+ // Without sending a document version, the rename should still work because
+ // the server should use the version it had at the start of the rename
+ // operation.
+ const content = '''
+ class MyClass {}
+ final a = new [[My^Class]]();
+ ''';
+ const expectedContent = '''
+ class MyNewClass {}
+ final a = new MyNewClass();
+ ''';
+ return _test_rename_withDocumentChanges(
+ content, 'MyNewClass', expectedContent,
+ sendRenameVersion: false);
+ }
+
test_rename_classNewKeyword() async {
const content = '''
class MyClass {}
@@ -321,16 +335,25 @@
}
_test_rename_withDocumentChanges(
- String content, String newName, String expectedContent) async {
+ String content,
+ String newName,
+ String expectedContent, {
+ sendDocumentVersion = true,
+ sendRenameVersion = true,
+ }) async {
+ // The specific number doesn't matter here, it's just a placeholder to confirm
+ // the values match.
+ final documentVersion = 222;
await initialize(
workspaceCapabilities:
withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
);
- await openFile(mainFileUri, withoutMarkers(content), version: 222);
+ await openFile(mainFileUri, withoutMarkers(content),
+ version: sendDocumentVersion ? documentVersion : null);
final result = await rename(
mainFileUri,
- 222,
+ sendRenameVersion ? documentVersion : null,
positionFromMarker(content),
newName,
);
@@ -341,7 +364,14 @@
final contents = {
mainFilePath: withoutMarkers(content),
};
- applyDocumentChanges(contents, result.documentChanges);
+ final documentVersions = {
+ mainFilePath: documentVersion,
+ };
+ applyDocumentChanges(
+ contents,
+ result.documentChanges,
+ expectedVersions: documentVersions,
+ );
expect(contents[mainFilePath], equals(expectedContent));
}
}
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index fad7baf..ecae12a 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -55,19 +55,62 @@
}
void applyDocumentChanges(
- Map<String, String> fileContents,
- Either2<
- List<TextDocumentEdit>,
- List<
- Either4<TextDocumentEdit, CreateFile, RenameFile,
- DeleteFile>>>
- documentChanges) {
+ Map<String, String> fileContents,
+ Either2<List<TextDocumentEdit>,
+ List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>
+ documentChanges, {
+ Map<String, int> expectedVersions,
+ }) {
+ // If we were supplied with expected versions, ensure that all returned
+ // edits match the versions.
+ if (expectedVersions != null) {
+ expectDocumentVersions(documentChanges, expectedVersions);
+ }
documentChanges.map(
(edits) => applyTextDocumentEdits(fileContents, edits),
(changes) => applyResourceChanges(fileContents, changes),
);
}
+ /// Validates the document versions for a set of edits match the versions in
+ /// the supplied map.
+ void expectDocumentVersions(
+ Either2<List<TextDocumentEdit>,
+ List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>
+ documentChanges,
+ Map<String, int> expectedVersions,
+ ) {
+ documentChanges.map(
+ // Validate versions on simple doc edits
+ (edits) => edits
+ .forEach((edit) => expectDocumentVersion(edit, expectedVersions)),
+ // For resource changes, we only need to validate changes since
+ // creates/renames/deletes do not supply versions.
+ (changes) => changes.forEach((change) {
+ change.map(
+ (edit) => expectDocumentVersion(edit, expectedVersions),
+ (create) => {},
+ (rename) {},
+ (delete) {},
+ );
+ }),
+ );
+ }
+
+ void expectDocumentVersion(
+ TextDocumentEdit edit,
+ Map<String, int> expectedVersions,
+ ) {
+ final path = Uri.parse(edit.textDocument.uri).toFilePath();
+ final expectedVersion = expectedVersions[path];
+
+ if (edit.textDocument is VersionedTextDocumentIdentifier) {
+ expect(edit.textDocument.version, equals(expectedVersion));
+ } else {
+ throw 'Document identifier for $path was not versioned (expected version $expectedVersion)';
+ }
+ }
+
void applyResourceChanges(
Map<String, String> oldFileContent,
List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>> changes,