clang-tools  14.0.0git
FS.cpp
Go to the documentation of this file.
1 //===--- FS.cpp - 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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "FS.h"
10 #include "clang/Basic/LLVM.h"
11 #include "llvm/ADT/None.h"
12 #include "llvm/Support/Path.h"
13 #include "llvm/Support/VirtualFileSystem.h"
14 
15 namespace clang {
16 namespace clangd {
17 
19  assert(llvm::sys::path::is_absolute(MainFilePath));
20  llvm::SmallString<256> MainFileCanonical(MainFilePath);
21  llvm::sys::path::remove_dots(MainFileCanonical, /*remove_dot_dot=*/true);
22  this->MainFilePath = std::string(MainFileCanonical.str());
23 }
24 
25 void PreambleFileStatusCache::update(const llvm::vfs::FileSystem &FS,
26  llvm::vfs::Status S) {
27  // Canonicalize path for later lookup, which is usually by absolute path.
28  llvm::SmallString<32> PathStore(S.getName());
29  if (FS.makeAbsolute(PathStore))
30  return;
31  llvm::sys::path::remove_dots(PathStore, /*remove_dot_dot=*/true);
32  // Do not cache status for the main file.
33  if (PathStore == MainFilePath)
34  return;
35  // Stores the latest status in cache as it can change in a preamble build.
36  StatCache.insert({PathStore, std::move(S)});
37 }
38 
39 llvm::Optional<llvm::vfs::Status>
40 PreambleFileStatusCache::lookup(llvm::StringRef File) const {
41  // Canonicalize to match the cached form.
42  // Lookup tends to be first by absolute path, so no need to make absolute.
43  llvm::SmallString<256> PathLookup(File);
44  llvm::sys::path::remove_dots(PathLookup, /*remove_dot_dot=*/true);
45 
46  auto I = StatCache.find(PathLookup);
47  if (I != StatCache.end())
48  // Returned Status name should always match the requested File.
49  return llvm::vfs::Status::copyWithNewName(I->getValue(), File);
50  return None;
51 }
52 
53 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
55  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
56  // This invalidates old status in cache if files are re-`open()`ed or
57  // re-`stat()`ed in case file status has changed during preamble build.
58  class CollectFS : public llvm::vfs::ProxyFileSystem {
59  public:
60  CollectFS(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
61  PreambleFileStatusCache &StatCache)
62  : ProxyFileSystem(std::move(FS)), StatCache(StatCache) {}
63 
64  llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
65  openFileForRead(const llvm::Twine &Path) override {
66  auto File = getUnderlyingFS().openFileForRead(Path);
67  if (!File || !*File)
68  return File;
69  // Eagerly stat opened file, as the followup `status` call on the file
70  // doesn't necessarily go through this FS. This puts some extra work on
71  // preamble build, but it should be worth it as preamble can be reused
72  // many times (e.g. code completion) and the repeated status call is
73  // likely to be cached in the underlying file system anyway.
74  if (auto S = File->get()->status())
75  StatCache.update(getUnderlyingFS(), std::move(*S));
76  return File;
77  }
78 
79  llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
80  auto S = getUnderlyingFS().status(Path);
81  if (S)
82  StatCache.update(getUnderlyingFS(), *S);
83  return S;
84  }
85 
86  private:
87  PreambleFileStatusCache &StatCache;
88  };
89  return llvm::IntrusiveRefCntPtr<CollectFS>(
90  new CollectFS(std::move(FS), *this));
91 }
92 
93 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
95  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) const {
96  class CacheVFS : public llvm::vfs::ProxyFileSystem {
97  public:
98  CacheVFS(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
99  const PreambleFileStatusCache &StatCache)
100  : ProxyFileSystem(std::move(FS)), StatCache(StatCache) {}
101 
102  llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
103  if (auto S = StatCache.lookup(Path.str()))
104  return *S;
105  return getUnderlyingFS().status(Path);
106  }
107 
108  private:
109  const PreambleFileStatusCache &StatCache;
110  };
111  return llvm::IntrusiveRefCntPtr<CacheVFS>(new CacheVFS(std::move(FS), *this));
112 }
113 
115  llvm::SmallString<128> CanonPath(File);
116  llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true);
117  return CanonPath.str().str();
118 }
119 
120 } // namespace clangd
121 } // namespace clang
clang::clangd::Path
std::string Path
A typedef to represent a file path.
Definition: Path.h:26
clang::clangd::PreambleFileStatusCache::lookup
llvm::Optional< llvm::vfs::Status > lookup(llvm::StringRef Path) const
Path is a path stored in preamble.
Definition: FS.cpp:40
clang::clangd::PreambleFileStatusCache::getProducingFS
IntrusiveRefCntPtr< llvm::vfs::FileSystem > getProducingFS(IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
Returns a VFS that collects file status.
Definition: FS.cpp:54
clang::clangd::PreambleFileStatusCache::update
void update(const llvm::vfs::FileSystem &FS, llvm::vfs::Status S)
Definition: FS.cpp:25
clang::clangd::PreambleFileStatusCache::getConsumingFS
IntrusiveRefCntPtr< llvm::vfs::FileSystem > getConsumingFS(IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS) const
Returns a VFS that uses the cache collected.
Definition: FS.cpp:94
clang::clangd::PathRef
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:29
clang::clangd::PreambleFileStatusCache::PreambleFileStatusCache
PreambleFileStatusCache(llvm::StringRef MainFilePath)
MainFilePath is the absolute path of the main source file this preamble corresponds to.
Definition: FS.cpp:18
clang::clangd::PreambleFileStatusCache
Records status information for files open()ed or stat()ed during preamble build (except for the main ...
Definition: FS.h:38
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::removeDots
Path removeDots(PathRef File)
Returns a version of File that doesn't contain dots and dot dots.
Definition: FS.cpp:114
FS.h