82 lines · c
1//===--- FS.h - File system related utils ------------------------*- C++-*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H11 12#include "support/Path.h"13#include "clang/Basic/LLVM.h"14#include "llvm/ADT/StringMap.h"15#include "llvm/Support/VirtualFileSystem.h"16#include <optional>17 18namespace clang {19namespace clangd {20 21/// Records status information for files open()ed or stat()ed during preamble22/// build (except for the main file), so we can avoid stat()s on the underlying23/// FS when reusing the preamble. For example, code completion can re-stat files24/// when getting FileID for source locations stored in preamble (e.g. checking25/// whether a location is in the main file).26///27/// The cache is keyed by absolute path of file name in cached status, as this28/// is what preamble stores.29///30/// The cache is not thread-safe when updates happen, so the use pattern should31/// be:32/// - One FS writes to the cache from one thread (or several but strictly33/// sequenced), e.g. when building preamble.34/// - Sequence point (no writes after this point, no reads before).35/// - Several FSs can read from the cache, e.g. code completions.36///37/// Note that the cache is only valid when reusing preamble.38class PreambleFileStatusCache {39public:40 /// \p MainFilePath is the absolute path of the main source file this preamble41 /// corresponds to. The stat for the main file will not be cached.42 PreambleFileStatusCache(llvm::StringRef MainFilePath);43 44 void update(const llvm::vfs::FileSystem &FS, llvm::vfs::Status S,45 llvm::StringRef File);46 47 /// \p Path is a path stored in preamble.48 std::optional<llvm::vfs::Status> lookup(llvm::StringRef Path) const;49 50 /// Returns a VFS that collects file status.51 /// Only cache stats for files that exist because52 /// 1) we only care about existing files when reusing preamble, unlike53 /// building preamble.54 /// 2) we use the file name in the Status as the cache key.55 ///56 /// Note that the returned VFS should not outlive the cache.57 IntrusiveRefCntPtr<llvm::vfs::FileSystem>58 getProducingFS(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);59 60 /// Returns a VFS that uses the cache collected.61 ///62 /// Note that the returned VFS should not outlive the cache.63 IntrusiveRefCntPtr<llvm::vfs::FileSystem>64 getConsumingFS(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) const;65 66private:67 std::string MainFilePath;68 llvm::StringMap<llvm::vfs::Status> StatCache;69};70 71/// Returns a version of \p File that doesn't contain dots and dot dots.72/// e.g /a/b/../c -> /a/c73/// /a/b/./c -> /a/b/c74/// FIXME: We should avoid encountering such paths in clangd internals by75/// filtering everything we get over LSP, CDB, etc.76Path removeDots(PathRef File);77 78} // namespace clangd79} // namespace clang80 81#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H82