#pragma once #include #include #include #include namespace clice { namespace vfs = llvm::vfs; namespace fs = llvm::sys::fs; namespace path = llvm::sys::path; class ThreadSafeFS : public vfs::ProxyFileSystem { public: explicit ThreadSafeFS() : ProxyFileSystem(vfs::createPhysicalFileSystem()) {} class VolatileFile : public vfs::File { public: VolatileFile(std::unique_ptr Wrapped) : wrapped(std::move(Wrapped)) { assert(this->wrapped); } llvm::ErrorOr> getBuffer(const llvm::Twine& Name, int64_t FileSize, bool RequiresNullTerminator, bool /*IsVolatile*/) override { return wrapped->getBuffer(Name, FileSize, RequiresNullTerminator, /*IsVolatile=*/true); } llvm::ErrorOr status() override { return wrapped->status(); } llvm::ErrorOr getName() override { return wrapped->getName(); } std::error_code close() override { return wrapped->close(); } private: std::unique_ptr wrapped; }; llvm::ErrorOr> openFileForRead(const llvm::Twine& InPath) override { llvm::SmallString<128> Path; InPath.toVector(Path); auto file = getUnderlyingFS().openFileForRead(Path); if(!file) return file; // Try to guess preamble files, they can be memory-mapped even on Windows as // clangd has exclusive access to those and nothing else should touch them. llvm::StringRef filename = path::filename(Path); if(filename.starts_with("preamble-") && filename.ends_with(".pch")) { return file; } return std::make_unique(std::move(*file)); } }; } // namespace clice