[analysis_server] Throw if ChangeBuilder.addDartFileEdit is used in a way that would lose edits
Change-Id: Ifee71a7b471512ba74bfbc4be5ce26d86a67da1a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/222720
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
index d2d24b8..ebb810a 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
@@ -130,6 +130,13 @@
if (builder == null) {
builder = await _createDartFileEditBuilder(path);
if (builder != null) {
+ // It's not currently supported to call this method twice concurrently
+ // for the same file as two builder may be produced because of the above
+ // `await` so detect this and throw to avoid losing edits.
+ if (_dartFileEditBuilders.containsKey(path)) {
+ throw StateError(
+ "Can't add multiple edits concurrently for the same file");
+ }
_dartFileEditBuilders[path] = builder;
}
}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 047e7a1..481147a 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -1868,6 +1868,42 @@
''');
}
+ Future<void> test_multipleEdits_concurrently() async {
+ var initialCode = '00';
+ var path = convertPath('/home/test/lib/test.dart');
+ newFile(path, content: initialCode);
+
+ var builder = newBuilder();
+ var future = Future.wait([
+ builder.addDartFileEdit(path, (builder) {
+ builder.addSimpleInsertion(0, '11');
+ }),
+ builder.addDartFileEdit(path, (builder) {
+ builder.addSimpleInsertion(2, '22');
+ }),
+ ]);
+
+ expect(future, throwsA(TypeMatcher<StateError>()));
+ }
+
+ Future<void> test_multipleEdits_sequentially() async {
+ var initialCode = '00';
+ var path = convertPath('/home/test/lib/test.dart');
+ newFile(path, content: initialCode);
+
+ var builder = newBuilder();
+ await builder.addDartFileEdit(path, (builder) {
+ builder.addSimpleInsertion(0, '11');
+ });
+ await builder.addDartFileEdit(path, (builder) {
+ builder.addSimpleInsertion(2, '22');
+ });
+
+ var edits = getEdits(builder);
+ var resultCode = SourceEdit.applySequence(initialCode, edits);
+ expect(resultCode, '110022');
+ }
+
Future<void> test_replaceTypeWithFuture() async {
var path = convertPath('/home/test/lib/test.dart');
addSource(path, 'String f() {}');