[Analyzer] Send a "content modified" response if files are modified during a refactor
See https://github.com/dart-lang/sdk/issues/43459.
Change-Id: I2e32ba0ba1020d18ea574caac42e79ec184a5562
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165362
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Danny Tuppeny <danny@tuppeny.com>
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
index 714c7ad..dc30e56 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
@@ -12,6 +12,7 @@
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
final _manager = _RefactorManager();
@@ -89,6 +90,9 @@
final edit = createWorkspaceEdit(server, change.edits);
return await sendWorkspaceEditToClient(edit);
+ } on InconsistentAnalysisException {
+ return error(ErrorCodes.ContentModified,
+ 'Content was modified before refactor was applied');
} finally {
_manager.end(cancellationToken);
}
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index 19589b0..90bd497 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -105,6 +105,31 @@
expect(contents[mainFilePath], equals(expectedContent));
}
+ Future<void> test_contentModified() async {
+ const content = '''
+main() {
+ print('Test!');
+ [[print('Test!');]]
+}
+ ''';
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: rangeFromMarkers(content));
+ final codeAction =
+ findCommand(codeActions, Commands.performRefactor, extractMethodTitle);
+ expect(codeAction, isNotNull);
+
+ // Send an edit request immediately after the refactor request.
+ final req1 = executeCodeAction(codeAction);
+ await replaceFile(100, mainFileUri, 'new test content');
+
+ // Expect the first to fail because of the modified content.
+ await expectLater(
+ req1, throwsA(isResponseError(ErrorCodes.ContentModified)));
+ }
+
Future<void> test_invalidLocation() async {
const content = '''
import 'dart:convert';