Folders containing overlayed files should exist even if they do not exist on disk
Change-Id: I511b5075cb10b2594dce9dc33f165b64d9527043
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103565
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Auto-Submit: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/test/integration/analysis/error_test.dart b/pkg/analysis_server/test/integration/analysis/error_test.dart
index 0a7948b..7d5cd76 100644
--- a/pkg/analysis_server/test/integration/analysis/error_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/error_test.dart
@@ -18,6 +18,24 @@
@reflectiveTest
class AnalysisErrorIntegrationTest
extends AbstractAnalysisServerIntegrationTest {
+ test_analysisRootDoesNotExist() async {
+ String packagePath = sourcePath('package');
+ String filePath = sourcePath('package/lib/test.dart');
+ String content = '''
+main() {
+ print(null) // parse error: missing ';'
+}''';
+ await sendServerSetSubscriptions([ServerService.STATUS]);
+ await sendAnalysisUpdateContent({filePath: AddContentOverlay(content)});
+ await sendAnalysisSetAnalysisRoots([packagePath], []);
+ await analysisFinished;
+
+ expect(currentAnalysisErrors[filePath], isList);
+ List<AnalysisError> errors = currentAnalysisErrors[filePath];
+ expect(errors, hasLength(1));
+ expect(errors[0].location.file, equals(filePath));
+ }
+
test_detect_simple_error() {
String pathname = sourcePath('test.dart');
writeFile(pathname, '''
diff --git a/pkg/analyzer/lib/file_system/overlay_file_system.dart b/pkg/analyzer/lib/file_system/overlay_file_system.dart
index 76879be..2f15a6a 100644
--- a/pkg/analyzer/lib/file_system/overlay_file_system.dart
+++ b/pkg/analyzer/lib/file_system/overlay_file_system.dart
@@ -70,6 +70,11 @@
@override
Resource getResource(String path) {
+ if (hasOverlay(path)) {
+ return new _OverlayResource._from(this, baseProvider.getFile(path));
+ } else if (_hasOverlayIn(path)) {
+ return new _OverlayResource._from(this, baseProvider.getFolder(path));
+ }
return new _OverlayResource._from(this, baseProvider.getResource(path));
}
@@ -140,14 +145,18 @@
}
/**
- * Return the paths of all of the overlaid files that are immediate children
- * of the given [folder].
+ * Return `true` if there is an overlay associated with at least one file
+ * contained inside the folder with the given [folderPath].
*/
- Iterable<String> _overlaysInFolder(Folder folder) {
- String folderPath = folder.path;
- return _overlayContent.keys
- .where((path) => pathContext.dirname(path) == folderPath);
- }
+ bool _hasOverlayIn(String folderPath) => _overlayContent.keys
+ .any((filePath) => pathContext.isWithin(folderPath, filePath));
+
+ /**
+ * Return the paths of all of the overlaid files that are children of the
+ * given [folder], either directly or indirectly.
+ */
+ Iterable<String> _overlaysInFolder(String folderPath) => _overlayContent.keys
+ .where((filePath) => pathContext.isWithin(folderPath, filePath));
}
/**
@@ -281,7 +290,7 @@
Stream<WatchEvent> get changes => _folder.changes;
@override
- bool get exists => _resource.exists;
+ bool get exists => _provider._hasOverlayIn(path) || _resource.exists;
/**
* Return the folder from the base resource provider that corresponds to this
@@ -330,12 +339,24 @@
@override
List<Resource> getChildren() {
- List<Resource> children = _folder
- .getChildren()
- .map((child) => new _OverlayResource._from(_provider, child))
- .toList();
- for (String overlayPath in _provider._overlaysInFolder(this)) {
- children.add(_provider.getFile(overlayPath));
+ List<Resource> children;
+ try {
+ children = _folder
+ .getChildren()
+ .map((child) => new _OverlayResource._from(_provider, child))
+ .toList();
+ } on FileSystemException {
+ children = [];
+ }
+ for (String overlayPath in _provider._overlaysInFolder(path)) {
+ pathos.Context context = _provider.pathContext;
+ if (context.dirname(overlayPath) == path) {
+ children.add(_provider.getFile(overlayPath));
+ } else {
+ String relativePath = context.relative(overlayPath, from: path);
+ String folderName = context.split(relativePath)[0];
+ children.add(_provider.getFolder(context.join(path, folderName)));
+ }
}
return children;
}
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 c422ade..f852767 100644
--- a/pkg/analyzer/test/file_system/overlay_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
@@ -506,7 +506,7 @@
expect(child, isNotNull);
}
- test_getChildren() {
+ test_getChildren_existing() {
Folder folder = _folder(exists: true);
Folder child1 = _folder(
exists: true, path: provider.pathContext.join(folder.path, 'lib'));
@@ -523,6 +523,13 @@
unorderedEquals([child1.path, child2.path, child3.path]));
}
+ test_getChildren_nonExisting_withOverlay() {
+ File file = _file(exists: false, withOverlay: true);
+ List<Resource> children = file.parent.parent.getChildren();
+ expect(children, hasLength(1));
+ expect(children[0], _isFolder);
+ }
+
test_isOrContains_false() {
Folder folder = _folder(exists: true);
expect(folder.isOrContains(baseProvider.convertPath('/foo/baz')), isFalse);
@@ -662,20 +669,28 @@
expect(file.exists, isTrue);
}
- test_getFolder_existing() {
+ test_getFolder_existing_withoutOverlay() {
Folder folder = _folder(exists: true);
expect(folder, isNotNull);
expect(folder.path, defaultFolderPath);
expect(folder.exists, isTrue);
}
- test_getFolder_notExisting() {
+ test_getFolder_notExisting_withoutOverlay() {
Folder folder = _folder(exists: false);
expect(folder, isNotNull);
expect(folder.path, defaultFolderPath);
expect(folder.exists, isFalse);
}
+ test_getFolder_notExisting_withOverlay() {
+ File file = _file(exists: false, withOverlay: true);
+ Folder folder = file.parent;
+ expect(folder, isNotNull);
+ expect(folder.path, defaultFolderPath);
+ expect(folder.exists, isTrue);
+ }
+
test_getModificationTimes_withoutOverlay() async {
Source source = _file(exists: true).createSource();
List<int> times = await provider.getModificationTimes([source]);
@@ -688,36 +703,43 @@
expect(times, [42]);
}
- test_getResource_existingFile_withoutOverlay() {
+ test_getResource_file_existing_withoutOverlay() {
String path = _file(exists: true).path;
Resource resource = provider.getResource(path);
expect(resource, _isFile);
}
- test_getResource_existingFile_withOverlay() {
+ test_getResource_file_existing_withOverlay() {
String path = _file(exists: true, withOverlay: true).path;
Resource resource = provider.getResource(path);
expect(resource, _isFile);
}
- test_getResource_existingFolder() {
- String path = _folder(exists: true).path;
- Resource resource = provider.getResource(path);
- expect(resource, _isFolder);
- }
-
- test_getResource_notExisting_withoutOverlay() {
+ test_getResource_file_notExisting_withoutOverlay() {
String path = _file(exists: false).path;
Resource resource = provider.getResource(path);
expect(resource, _isFile);
}
- test_getResource_notExisting_withOverlay() {
+ test_getResource_file_notExisting_withOverlay() {
String path = _file(exists: false, withOverlay: true).path;
Resource resource = provider.getResource(path);
expect(resource, _isFile);
}
+ test_getResource_folder_existing() {
+ String path = _folder(exists: true).path;
+ Resource resource = provider.getResource(path);
+ expect(resource, _isFolder);
+ }
+
+ test_getResource_folder_nonExisting_withOverlay() {
+ String filePath = _file(exists: false, withOverlay: true).path;
+ String folderPath = provider.pathContext.dirname(filePath);
+ Resource resource = provider.getResource(folderPath);
+ expect(resource, _isFolder);
+ }
+
test_getStateLocation_uniqueness() {
String idOne = 'one';
Folder folderOne = provider.getStateLocation(idOne);