aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/VirtualFileSystem.cpp
diff options
context:
space:
mode:
authorJonas Devlieghere <jonas@devlieghere.com>2020-03-27 15:02:24 -0700
committerJonas Devlieghere <jonas@devlieghere.com>2020-03-27 15:16:52 -0700
commit3ef33e69de085cb6bc028b4fc4dd39087631ac12 (patch)
tree4f8d905ad95a4b765fbb35d5b2ca53895bda8c41 /llvm/lib/Support/VirtualFileSystem.cpp
parent0fca766458da04bbc6d33b3f9ecd57e615c556c1 (diff)
downloadllvm-3ef33e69de085cb6bc028b4fc4dd39087631ac12.zip
llvm-3ef33e69de085cb6bc028b4fc4dd39087631ac12.tar.gz
llvm-3ef33e69de085cb6bc028b4fc4dd39087631ac12.tar.bz2
[VirtualFileSystem] Support directory entries in the YAMLVFSWriter
The current implementation of the JSONWriter does not support writing out directory entries. Earlier today I added a unit test to illustrate the problem. When an entry is added to the YAMLVFSWriter and the path is a directory, it will incorrectly emit the directory as a file, and any files inside that directory will not be found by the VFS. It's possible to partially work around the issue by only adding "leaf nodes" (files) to the YAMLVFSWriter. However, this doesn't work for representing empty directories. This is a problem for clients of the VFS that want to iterate over a directory. The directory not being there is not the same as the directory being empty. This is not just a hypothetical problem. The FileCollector for example does not differentiate between file and directory paths. I temporarily worked around the issue for LLDB by ignoring directories, but I suspect this will prove problematic sooner rather than later. This patch fixes the issue by extending the JSONWriter to support writing out directory entries. We store whether an entry should be emitted as a file or directory. Differential revision: https://reviews.llvm.org/D76670
Diffstat (limited to 'llvm/lib/Support/VirtualFileSystem.cpp')
-rw-r--r--llvm/lib/Support/VirtualFileSystem.cpp34
1 files changed, 26 insertions, 8 deletions
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index 737116c..22b4a08 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -1912,11 +1912,21 @@ UniqueID vfs::getNextVirtualUniqueID() {
return UniqueID(std::numeric_limits<uint64_t>::max(), ID);
}
-void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
+void YAMLVFSWriter::addEntry(StringRef VirtualPath, StringRef RealPath,
+ bool IsDirectory) {
assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
assert(sys::path::is_absolute(RealPath) && "real path not absolute");
assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported");
- Mappings.emplace_back(VirtualPath, RealPath);
+ Mappings.emplace_back(VirtualPath, RealPath, IsDirectory);
+}
+
+void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
+ addEntry(VirtualPath, RealPath, /*IsDirectory=*/false);
+}
+
+void YAMLVFSWriter::addDirectoryMapping(StringRef VirtualPath,
+ StringRef RealPath) {
+ addEntry(VirtualPath, RealPath, /*IsDirectory=*/true);
}
namespace {
@@ -2017,7 +2027,10 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
if (!Entries.empty()) {
const YAMLVFSEntry &Entry = Entries.front();
- startDirectory(path::parent_path(Entry.VPath));
+ bool first_entry_is_directory = Entry.IsDirectory;
+ StringRef Dir =
+ first_entry_is_directory ? Entry.VPath : path::parent_path(Entry.VPath);
+ startDirectory(Dir);
StringRef RPath = Entry.RPath;
if (UseOverlayRelative) {
@@ -2027,13 +2040,18 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
RPath = RPath.slice(OverlayDirLen, RPath.size());
}
- writeEntry(path::filename(Entry.VPath), RPath);
+ if (!first_entry_is_directory)
+ writeEntry(path::filename(Entry.VPath), RPath);
for (const auto &Entry : Entries.slice(1)) {
- StringRef Dir = path::parent_path(Entry.VPath);
- if (Dir == DirStack.back())
- OS << ",\n";
- else {
+ StringRef Dir =
+ Entry.IsDirectory ? Entry.VPath : path::parent_path(Entry.VPath);
+ if (Dir == DirStack.back()) {
+ if (!first_entry_is_directory) {
+ OS << ",\n";
+ first_entry_is_directory = false;
+ }
+ } else {
while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
OS << "\n";
endDirectory();