Version 2.15.0-124.0.dev

Merge commit '28738dfad0cb557b2d5f67f6125d5c0a9ac5e3b7' into 'dev'
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 665fe07..a5ec4d3 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 2.4.0-dev
+* Deprecated `ResourceProvider.getModificationTimes()`.
+* Deprecated `MemoryResourceProvider.newDummyLink()`.
+* Deprecated `MemoryResourceProvider.updateFile()`.
+
 ## 2.3.0
 * Enable `constructor-tearoffs` feature by default in `2.15`.
 * Improvements in constructors tear-off implementation.
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index b8a27f6..e71b153 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -198,6 +198,7 @@
   ///
   /// If the file of a source is not managed by this provider, return `null`.
   /// If the file a source does not exist, return `-1`.
+  @Deprecated('Not used by clients')
   Future<List<int?>> getModificationTimes(List<Source> sources);
 
   /// Return the [Resource] that corresponds to the given [path].
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 677f728..76b90a1 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:collection';
 import 'dart:convert';
 import 'dart:typed_data';
 
@@ -16,13 +15,9 @@
 /// An in-memory implementation of [ResourceProvider].
 /// Use `/` as a path separator.
 class MemoryResourceProvider implements ResourceProvider {
-  final Map<String, _MemoryResource> _pathToResource =
-      HashMap<String, _MemoryResource>();
-  final Map<String, Uint8List> _pathToBytes = HashMap<String, Uint8List>();
-  final Map<String, int> _pathToTimestamp = HashMap<String, int>();
+  final Map<String, _ResourceData> _pathToData = {};
   final Map<String, String> _pathToLinkedPath = {};
-  final Map<String, List<StreamController<WatchEvent>>> _pathToWatchers =
-      HashMap<String, List<StreamController<WatchEvent>>>();
+  final Map<String, List<StreamController<WatchEvent>>> _pathToWatchers = {};
   int nextStamp = 0;
 
   final pathos.Context _pathContext;
@@ -55,19 +50,28 @@
 
   /// Delete the file with the given path.
   void deleteFile(String path) {
-    _checkFileAtPath(path);
-    _pathToResource.remove(path);
-    _pathToBytes.remove(path);
-    _pathToTimestamp.remove(path);
+    var data = _pathToData[path];
+    if (data is! _FileData) {
+      throw FileSystemException(path, 'Not a file.');
+    }
+
+    _pathToData.remove(path);
+    _removeFromParentFolderData(path);
+
     _notifyWatchers(path, ChangeType.REMOVE);
   }
 
   /// Delete the folder with the given path
   /// and recursively delete nested files and folders.
   void deleteFolder(String path) {
-    _checkFolderAtPath(path);
-    var folder = _pathToResource[path] as _MemoryFolder;
-    for (Resource child in folder.getChildren()) {
+    var data = _pathToData[path];
+    if (data is! _FolderData) {
+      throw FileSystemException(path, 'Not a folder.');
+    }
+
+    for (var childName in data.childNames.toList()) {
+      var childPath = pathContext.join(path, childName);
+      var child = getResource(childPath);
       if (child is File) {
         deleteFile(child.path);
       } else if (child is Folder) {
@@ -76,9 +80,17 @@
         throw 'failed to delete resource: $child';
       }
     }
-    _pathToResource.remove(path);
-    _pathToBytes.remove(path);
-    _pathToTimestamp.remove(path);
+
+    if (_pathToData[path] != data) {
+      throw StateError('Unexpected concurrent modification: $path');
+    }
+    if (data.childNames.isNotEmpty) {
+      throw StateError('Must be empty.');
+    }
+
+    _pathToData.remove(path);
+    _removeFromParentFolderData(path);
+
     _notifyWatchers(path, ChangeType.REMOVE);
   }
 
@@ -94,18 +106,27 @@
     return _MemoryFolder(this, path);
   }
 
+  @Deprecated('Not used by clients')
   @override
   Future<List<int>> getModificationTimes(List<Source> sources) async {
     return sources.map((source) {
       String path = source.fullName;
-      return _pathToTimestamp[path] ?? -1;
+      var file = getFile(path);
+      try {
+        return file.modificationStamp;
+      } on FileSystemException {
+        return -1;
+      }
     }).toList();
   }
 
   @override
   Resource getResource(String path) {
     _ensureAbsoluteAndNormalized(path);
-    return _pathToResource[path] ?? _MemoryFile(this, path);
+    var data = _pathToData[path];
+    return data is _FolderData
+        ? _MemoryFolder(this, path)
+        : _MemoryFile(this, path);
   }
 
   @override
@@ -115,66 +136,53 @@
   }
 
   void modifyFile(String path, String content) {
-    _checkFileAtPath(path);
-    _pathToBytes[path] = utf8.encode(content) as Uint8List;
-    _pathToTimestamp[path] = nextStamp++;
+    var data = _pathToData[path];
+    if (data is! _FileData) {
+      throw FileSystemException(path, 'Not a file.');
+    }
+
+    _pathToData[path] = _FileData(
+      bytes: utf8.encode(content) as Uint8List,
+      timeStamp: nextStamp++,
+    );
     _notifyWatchers(path, ChangeType.MODIFY);
   }
 
   /// Create a resource representing a dummy link (that is, a File object which
   /// appears in its parent directory, but whose `exists` property is false)
+  @Deprecated('Not used by clients')
   File newDummyLink(String path) {
     _ensureAbsoluteAndNormalized(path);
     newFolder(pathContext.dirname(path));
     _MemoryDummyLink link = _MemoryDummyLink(this, path);
-    _pathToResource[path] = link;
-    _pathToTimestamp[path] = nextStamp++;
     _notifyWatchers(path, ChangeType.ADD);
     return link;
   }
 
   File newFile(String path, String content, [int? stamp]) {
-    _ensureAbsoluteAndNormalized(path);
-    _MemoryFile file = _newFile(path);
-    _pathToBytes[path] = utf8.encode(content) as Uint8List;
-    _pathToTimestamp[path] = stamp ?? nextStamp++;
-    _notifyWatchers(path, ChangeType.ADD);
-    return file;
+    var bytes = utf8.encode(content);
+    return newFileWithBytes(path, bytes, stamp);
   }
 
   File newFileWithBytes(String path, List<int> bytes, [int? stamp]) {
     _ensureAbsoluteAndNormalized(path);
-    _MemoryFile file = _newFile(path);
-    _pathToBytes[path] = Uint8List.fromList(bytes);
-    _pathToTimestamp[path] = stamp ?? nextStamp++;
+
+    var parentPath = pathContext.dirname(path);
+    var parentData = _newFolder(parentPath);
+    _addToParentFolderData(parentData, path);
+
+    _pathToData[path] = _FileData(
+      bytes: Uint8List.fromList(bytes),
+      timeStamp: stamp ?? nextStamp++,
+    );
     _notifyWatchers(path, ChangeType.ADD);
-    return file;
+
+    return _MemoryFile(this, path);
   }
 
   Folder newFolder(String path) {
-    _ensureAbsoluteAndNormalized(path);
-    if (!pathContext.isAbsolute(path)) {
-      throw ArgumentError("Path must be absolute : $path");
-    }
-    var resource = _pathToResource[path];
-    if (resource == null) {
-      String parentPath = pathContext.dirname(path);
-      if (parentPath != path) {
-        newFolder(parentPath);
-      }
-      _MemoryFolder folder = _MemoryFolder(this, path);
-      _pathToResource[path] = folder;
-      _pathToTimestamp[path] = nextStamp++;
-      _notifyWatchers(path, ChangeType.ADD);
-      return folder;
-    } else if (resource is _MemoryFolder) {
-      _notifyWatchers(path, ChangeType.ADD);
-      return resource;
-    } else {
-      String message =
-          'Folder expected at ' "'$path'" 'but ${resource.runtimeType} found';
-      throw ArgumentError(message);
-    }
+    _newFolder(path);
+    return _MemoryFolder(this, path);
   }
 
   /// Create a link from the [path] to the [target].
@@ -184,44 +192,29 @@
     _pathToLinkedPath[path] = target;
   }
 
+  @Deprecated('Not used by clients')
   File updateFile(String path, String content, [int? stamp]) {
     _ensureAbsoluteAndNormalized(path);
     newFolder(pathContext.dirname(path));
-    _MemoryFile file = _MemoryFile(this, path);
-    _pathToResource[path] = file;
-    _pathToBytes[path] = utf8.encode(content) as Uint8List;
-    _pathToTimestamp[path] = stamp ?? nextStamp++;
+    _pathToData[path] = _FileData(
+      bytes: utf8.encode(content) as Uint8List,
+      timeStamp: stamp ?? nextStamp++,
+    );
     _notifyWatchers(path, ChangeType.MODIFY);
-    return file;
+    return _MemoryFile(this, path);
   }
 
   /// Write a representation of the file system on the given [sink].
   void writeOn(StringSink sink) {
-    List<String> paths = _pathToResource.keys.toList();
+    List<String> paths = _pathToData.keys.toList();
     paths.sort();
     paths.forEach(sink.writeln);
   }
 
-  void _checkFileAtPath(String path) {
-    // TODO(brianwilkerson) Consider throwing a FileSystemException rather than
-    // an ArgumentError.
-    var resource = _pathToResource[path];
-    if (resource is! _MemoryFile) {
-      if (resource == null) {
-        throw ArgumentError('File expected at "$path" but does not exist');
-      }
-      throw ArgumentError(
-          'File expected at "$path" but ${resource.runtimeType} found');
-    }
-  }
-
-  void _checkFolderAtPath(String path) {
-    // TODO(brianwilkerson) Consider throwing a FileSystemException rather than
-    // an ArgumentError.
-    var resource = _pathToResource[path];
-    if (resource is! _MemoryFolder) {
-      throw ArgumentError(
-          'Folder expected at "$path" but ${resource.runtimeType} found');
+  void _addToParentFolderData(_FolderData parentData, String path) {
+    var childName = pathContext.basename(path);
+    if (!parentData.childNames.contains(childName)) {
+      parentData.childNames.add(childName);
     }
   }
 
@@ -236,18 +229,25 @@
     }
   }
 
-  /// Create a new [_MemoryFile] without any content.
-  _MemoryFile _newFile(String path) {
-    String folderPath = pathContext.dirname(path);
-    var folder = _pathToResource[folderPath];
-    if (folder == null) {
-      newFolder(folderPath);
-    } else if (folder is! Folder) {
-      throw ArgumentError('Cannot create file ($path) as child of file');
+  _FolderData _newFolder(String path) {
+    _ensureAbsoluteAndNormalized(path);
+
+    var data = _pathToData[path];
+    if (data is _FolderData) {
+      return data;
+    } else if (data == null) {
+      var parentPath = pathContext.dirname(path);
+      if (parentPath != path) {
+        var parentData = _newFolder(parentPath);
+        _addToParentFolderData(parentData, path);
+      }
+      var data = _FolderData();
+      _pathToData[path] = data;
+      _notifyWatchers(path, ChangeType.ADD);
+      return data;
+    } else {
+      throw FileSystemException(path, 'Folder expected.');
     }
-    _MemoryFile file = _MemoryFile(this, path);
-    _pathToResource[path] = file;
-    return file;
   }
 
   void _notifyWatchers(String path, ChangeType changeType) {
@@ -262,36 +262,41 @@
     });
   }
 
-  _MemoryFile _renameFileSync(_MemoryFile file, String newPath) {
-    String path = file.path;
+  void _removeFromParentFolderData(String path) {
+    var parentPath = pathContext.dirname(path);
+    var parentData = _pathToData[parentPath] as _FolderData;
+    var childName = pathContext.basename(path);
+    parentData.childNames.remove(childName);
+  }
+
+  void _renameFileSync(String path, String newPath) {
+    var data = _pathToData[path];
+    if (data is! _FileData) {
+      throw FileSystemException(path, 'Not a file.');
+    }
+
     if (newPath == path) {
-      return file;
-    }
-    var existingNewResource = _pathToResource[newPath];
-    if (existingNewResource is _MemoryFolder) {
-      throw FileSystemException(
-          path, 'Could not be renamed: $newPath is a folder.');
+      return;
     }
 
-    _MemoryFile newFile = _newFile(newPath);
-    _pathToResource.remove(path);
-
-    var oldBytes = _pathToBytes.remove(path);
-    if (oldBytes != null) {
-      _pathToBytes[newPath] = oldBytes;
+    var existingNewData = _pathToData[newPath];
+    if (existingNewData == null) {
+      // Nothing to do.
+    } else if (existingNewData is _FileData) {
+      deleteFile(newPath);
+    } else {
+      throw FileSystemException(newPath, 'Not a file.');
     }
 
-    var oldTimestamp = _pathToTimestamp.remove(path);
-    if (oldTimestamp != null) {
-      _pathToTimestamp[newPath] = oldTimestamp;
-    }
+    var parentPath = pathContext.dirname(path);
+    var parentData = _newFolder(parentPath);
+    _addToParentFolderData(parentData, path);
 
-    if (existingNewResource != null) {
-      _notifyWatchers(newPath, ChangeType.REMOVE);
-    }
+    _pathToData.remove(path);
+    _pathToData[newPath] = data;
+
     _notifyWatchers(path, ChangeType.REMOVE);
     _notifyWatchers(newPath, ChangeType.ADD);
-    return newFile;
   }
 
   String _resolveLinks(String path) {
@@ -317,15 +322,34 @@
     return result;
   }
 
-  void _setFileContent(_MemoryFile file, List<int> bytes) {
-    String path = file.path;
-    _pathToResource[path] = file;
-    _pathToBytes[path] = Uint8List.fromList(bytes);
-    _pathToTimestamp[path] = nextStamp++;
+  void _setFileContent(String path, List<int> bytes) {
+    var parentPath = pathContext.dirname(path);
+    var parentData = _newFolder(parentPath);
+    _addToParentFolderData(parentData, path);
+
+    _pathToData[path] = _FileData(
+      bytes: Uint8List.fromList(bytes),
+      timeStamp: nextStamp++,
+    );
     _notifyWatchers(path, ChangeType.MODIFY);
   }
 }
 
+class _FileData extends _ResourceData {
+  final Uint8List bytes;
+  final int timeStamp;
+
+  _FileData({
+    required this.bytes,
+    required this.timeStamp,
+  });
+}
+
+class _FolderData extends _ResourceData {
+  /// Names (not paths) of direct children.
+  final List<String> childNames = [];
+}
+
 /// An in-memory implementation of [File] which acts like a symbolic link to a
 /// non-existent file.
 class _MemoryDummyLink extends _MemoryResource implements File {
@@ -347,11 +371,7 @@
 
   @override
   int get modificationStamp {
-    var stamp = provider._pathToTimestamp[path];
-    if (stamp == null) {
-      throw FileSystemException(path, "File does not exist");
-    }
-    return stamp;
+    throw FileSystemException(path, "File does not exist");
   }
 
   @override
@@ -413,7 +433,7 @@
   @override
   bool get exists {
     var canonicalPath = provider._resolveLinks(path);
-    return provider._pathToResource[canonicalPath] is _MemoryFile;
+    return provider._pathToData[canonicalPath] is _FileData;
   }
 
   @override
@@ -424,11 +444,11 @@
   @override
   int get modificationStamp {
     var canonicalPath = provider._resolveLinks(path);
-    var stamp = provider._pathToTimestamp[canonicalPath];
-    if (stamp == null) {
-      throw FileSystemException(path, 'File "$path" does not exist.');
+    var data = provider._pathToData[canonicalPath];
+    if (data is! _FileData) {
+      throw FileSystemException(path, 'File does not exist.');
     }
-    return stamp;
+    return data.timeStamp;
   }
 
   @override
@@ -458,26 +478,23 @@
   @override
   Uint8List readAsBytesSync() {
     var canonicalPath = provider._resolveLinks(path);
-    var content = provider._pathToBytes[canonicalPath];
-    if (content == null) {
-      throw FileSystemException(path, 'File "$path" does not exist.');
+    var data = provider._pathToData[canonicalPath];
+    if (data is! _FileData) {
+      throw FileSystemException(path, 'File does not exist.');
     }
-    return content;
+    return data.bytes;
   }
 
   @override
   String readAsStringSync() {
-    var canonicalPath = provider._resolveLinks(path);
-    var content = provider._pathToBytes[canonicalPath];
-    if (content == null) {
-      throw FileSystemException(path, 'File "$path" does not exist.');
-    }
-    return utf8.decode(content);
+    var bytes = readAsBytesSync();
+    return utf8.decode(bytes);
   }
 
   @override
   File renameSync(String newPath) {
-    return provider._renameFileSync(this, newPath);
+    provider._renameFileSync(path, newPath);
+    return provider.getFile(newPath);
   }
 
   @override
@@ -486,7 +503,7 @@
     var result = provider.getFile(canonicalPath);
 
     if (!result.exists) {
-      throw FileSystemException(path, 'File "$path" does not exist.');
+      throw FileSystemException(path, 'File does not exist.');
     }
 
     return result;
@@ -494,12 +511,13 @@
 
   @override
   void writeAsBytesSync(List<int> bytes) {
-    provider._setFileContent(this, bytes);
+    provider._setFileContent(path, bytes);
   }
 
   @override
   void writeAsStringSync(String content) {
-    provider._setFileContent(this, utf8.encode(content));
+    var bytes = utf8.encode(content);
+    writeAsBytesSync(bytes);
   }
 }
 
@@ -511,7 +529,7 @@
   @override
   bool get exists {
     var canonicalPath = provider._resolveLinks(path);
-    return provider._pathToResource[canonicalPath] is _MemoryFolder;
+    return provider._pathToData[canonicalPath] is _FolderData;
   }
 
   @override
@@ -555,29 +573,20 @@
 
   @override
   Resource getChild(String relPath) {
-    String childPath = canonicalizePath(relPath);
-    return provider._pathToResource[childPath] ??
-        _MemoryFile(provider, childPath);
+    var path = canonicalizePath(relPath);
+    return provider.getResource(path);
   }
 
   @override
   _MemoryFile getChildAssumingFile(String relPath) {
-    String childPath = canonicalizePath(relPath);
-    var resource = provider._pathToResource[childPath];
-    if (resource is _MemoryFile) {
-      return resource;
-    }
-    return _MemoryFile(provider, childPath);
+    var path = canonicalizePath(relPath);
+    return _MemoryFile(provider, path);
   }
 
   @override
   _MemoryFolder getChildAssumingFolder(String relPath) {
-    String childPath = canonicalizePath(relPath);
-    var resource = provider._pathToResource[childPath];
-    if (resource is _MemoryFolder) {
-      return resource;
-    }
-    return _MemoryFolder(provider, childPath);
+    var path = canonicalizePath(relPath);
+    return _MemoryFolder(provider, path);
   }
 
   @override
@@ -596,17 +605,17 @@
       }).toList();
     }
 
-    if (!exists) {
+    var data = provider._pathToData[path];
+    if (data is! _FolderData) {
       throw FileSystemException(path, 'Folder does not exist.');
     }
 
     var children = <Resource>[];
-
-    provider._pathToResource.forEach((resourcePath, resource) {
-      if (provider.pathContext.dirname(resourcePath) == path) {
-        children.add(resource);
-      }
-    });
+    for (var childName in data.childNames) {
+      var childPath = provider.pathContext.join(path, childName);
+      var child = provider.getResource(childPath);
+      children.add(child);
+    }
 
     provider._pathToLinkedPath.forEach((resourcePath, targetPath) {
       if (provider.pathContext.dirname(resourcePath) == path) {
@@ -640,7 +649,7 @@
     var result = provider.getFolder(canonicalPath);
 
     if (!result.exists) {
-      throw FileSystemException(path, 'Folder "$path" does not exist.');
+      throw FileSystemException(path, 'Folder does not exist.');
     }
 
     return result;
@@ -712,3 +721,5 @@
   @override
   Uri toUri() => provider.pathContext.toUri(path);
 }
+
+class _ResourceData {}
diff --git a/pkg/analyzer/lib/file_system/overlay_file_system.dart b/pkg/analyzer/lib/file_system/overlay_file_system.dart
index 8d7ce33..e66c643 100644
--- a/pkg/analyzer/lib/file_system/overlay_file_system.dart
+++ b/pkg/analyzer/lib/file_system/overlay_file_system.dart
@@ -40,6 +40,7 @@
   Folder getFolder(String path) =>
       _OverlayFolder(this, baseProvider.getFolder(path));
 
+  @Deprecated('Not used by clients')
   @override
   Future<List<int>> getModificationTimes(List<Source> sources) async {
     return sources.map((source) {
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index 51e3bc8..9824499 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -78,6 +78,7 @@
     return _PhysicalFolder(io.Directory(path));
   }
 
+  @Deprecated('Not used by clients')
   @override
   Future<List<int?>> getModificationTimes(List<Source> sources) async {
     List<String> paths = sources.map((source) => source.fullName).toList();
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 2f2abf2..6a3198e 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 2.3.0
+version: 2.4.0-dev
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer
 
diff --git a/pkg/analyzer/test/file_system/file_system_test_support.dart b/pkg/analyzer/test/file_system/file_system_test_support.dart
index 4004239..6b5d0e2 100644
--- a/pkg/analyzer/test/file_system/file_system_test_support.dart
+++ b/pkg/analyzer/test/file_system/file_system_test_support.dart
@@ -12,6 +12,8 @@
 final isFileSystemException = TypeMatcher<FileSystemException>();
 final isFolder = TypeMatcher<Folder>();
 
+final throwsFileSystemException = throwsA(isFileSystemException);
+
 abstract class FileSystemTestSupport {
   /// The content used for the file at the [defaultFilePath] if it is created
   /// and no other content is provided.
@@ -108,9 +110,11 @@
   test_delete_existing() {
     File file = getFile(exists: true);
     expect(file.exists, isTrue);
+    expect(file.parent2.getChildren(), contains(file));
 
     file.delete();
     expect(file.exists, isFalse);
+    expect(file.parent2.getChildren(), isNot(contains(file)));
   }
 
   test_delete_notExisting();
@@ -919,6 +923,7 @@
     expect(folder.exists, isFalse);
   }
 
+  @Deprecated('Not used by clients')
   test_getModificationTimes_existing() async {
     Source source = getFile(exists: true).createSource();
 
@@ -926,6 +931,7 @@
     expect(times, [source.modificationStamp]);
   }
 
+  @Deprecated('Not used by clients')
   test_getModificationTimes_notExisting() async {
     Source source = getFile(exists: false).createSource();
 
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index 34dc801..94b56ef 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -241,7 +241,10 @@
     File file = getFile(exists: false);
     expect(file.exists, isFalse);
 
-    expect(() => file.delete(), throwsA(const TypeMatcher<ArgumentError>()));
+    expect(
+      () => file.delete(),
+      throwsFileSystemException,
+    );
   }
 
   @override
@@ -304,14 +307,20 @@
   test_deleteFile_folder() {
     Folder folder = getFolder(exists: true);
 
-    expect(() => provider.deleteFile(defaultFolderPath), throwsArgumentError);
+    expect(
+      () => provider.deleteFile(defaultFolderPath),
+      throwsFileSystemException,
+    );
     expect(folder.exists, isTrue);
   }
 
   test_deleteFile_notExisting() {
     File file = getFile(exists: false);
 
-    expect(() => provider.deleteFile(defaultFilePath), throwsArgumentError);
+    expect(
+      () => provider.deleteFile(defaultFilePath),
+      throwsFileSystemException,
+    );
     expect(file.exists, isFalse);
   }
 
@@ -325,16 +334,20 @@
   test_modifyFile_existing_folder() {
     getFolder(exists: true);
 
-    expect(() => provider.modifyFile(defaultFolderPath, 'contents'),
-        throwsArgumentError);
+    expect(
+      () => provider.modifyFile(defaultFolderPath, 'contents'),
+      throwsFileSystemException,
+    );
     expect(provider.getResource(defaultFolderPath), isFolder);
   }
 
   test_modifyFile_notExisting() {
     getFile(exists: false);
 
-    expect(() => provider.modifyFile(defaultFilePath, 'contents'),
-        throwsArgumentError);
+    expect(
+      () => provider.modifyFile(defaultFilePath, 'contents'),
+      throwsFileSystemException,
+    );
     Resource file = provider.getResource(defaultFilePath);
     expect(file, isFile);
     expect(file.exists, isFalse);
@@ -357,7 +370,10 @@
   test_newFolder_existing_file() {
     getFile(exists: true);
 
-    expect(() => provider.newFolder(defaultFilePath), throwsArgumentError);
+    expect(
+      () => provider.newFolder(defaultFilePath),
+      throwsFileSystemException,
+    );
   }
 
   test_newFolder_existing_folder() {
diff --git a/pkg/analyzer/test/file_system/overlay_file_system_test.dart b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
index dc0035f..78d9cbf 100644
--- a/pkg/analyzer/test/file_system/overlay_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
@@ -272,25 +272,21 @@
   test_renameSync_notExisting_withoutOverlay() {
     String oldPath = '/foo/bar/file.txt';
     String newPath = baseProvider.convertPath('/foo/bar/new-file.txt');
-    File oldFile = _file(exists: true, path: oldPath);
-    File newFile = oldFile.renameSync(newPath);
-    expect(oldFile.path, baseProvider.convertPath(oldPath));
-    expect(oldFile.exists, isFalse);
-    expect(newFile.path, newPath);
-    expect(newFile.exists, isTrue);
-    expect(newFile.readAsStringSync(), 'a');
+    File oldFile = _file(exists: false, path: oldPath);
+    expect(
+      () => oldFile.renameSync(newPath),
+      throwsFileSystemException,
+    );
   }
 
   test_renameSync_notExisting_withOverlay() {
     String oldPath = '/foo/bar/file.txt';
     String newPath = baseProvider.convertPath('/foo/bar/new-file.txt');
     File oldFile = _file(exists: false, path: oldPath, withOverlay: true);
-    File newFile = oldFile.renameSync(newPath);
-    expect(oldFile.path, baseProvider.convertPath(oldPath));
-    expect(oldFile.exists, isFalse);
-    expect(newFile.path, newPath);
-    expect(newFile.exists, isTrue);
-    expect(newFile.readAsStringSync(), 'bbb');
+    expect(
+      () => oldFile.renameSync(newPath),
+      throwsFileSystemException,
+    );
   }
 
   @failingTest
@@ -480,7 +476,7 @@
   test_delete_notExisting() {
     Folder folder = _folder(exists: false);
     expect(folder.exists, isFalse);
-    expect(() => folder.delete(), throwsA(TypeMatcher<ArgumentError>()));
+    expect(() => folder.delete(), throwsFileSystemException);
   }
 
   void test_exists_links_existing() {
@@ -810,12 +806,14 @@
     expect(folder.exists, isTrue);
   }
 
+  @Deprecated('Not used by clients')
   test_getModificationTimes_withoutOverlay() async {
     Source source = _file(exists: true).createSource();
     List<int> times = await provider.getModificationTimes([source]);
     expect(times, [source.modificationStamp]);
   }
 
+  @Deprecated('Not used by clients')
   test_getModificationTimes_withOverlay() async {
     Source source = _file(exists: true, withOverlay: true).createSource();
     List<int> times = await provider.getModificationTimes([source]);
diff --git a/tools/VERSION b/tools/VERSION
index 8d8bbba..96c9f0d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 123
+PRERELEASE 124
 PRERELEASE_PATCH 0
\ No newline at end of file