clang-tools  8.0.0
FS.cpp
Go to the documentation of this file.
1 //===--- FS.cpp - File system related utils ----------------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "FS.h"
11 #include "clang/Basic/LLVM.h"
12 #include "llvm/ADT/None.h"
13 #include "llvm/Support/Path.h"
14 
15 namespace clang {
16 namespace clangd {
17 
19  : MainFilePath(MainFilePath) {
20  assert(llvm::sys::path::is_absolute(MainFilePath));
21 }
22 
23 void PreambleFileStatusCache::update(const llvm::vfs::FileSystem &FS,
24  llvm::vfs::Status S) {
25  llvm::SmallString<32> PathStore(S.getName());
26  if (FS.makeAbsolute(PathStore))
27  return;
28  // Do not cache status for the main file.
29  if (PathStore == MainFilePath)
30  return;
31  // Stores the latest status in cache as it can change in a preamble build.
32  StatCache.insert({PathStore, std::move(S)});
33 }
34 
35 llvm::Optional<llvm::vfs::Status>
36 PreambleFileStatusCache::lookup(llvm::StringRef File) const {
37  auto I = StatCache.find(File);
38  if (I != StatCache.end())
39  return I->getValue();
40  return None;
41 }
42 
43 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
45  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
46  // This invalidates old status in cache if files are re-`open()`ed or
47  // re-`stat()`ed in case file status has changed during preamble build.
48  class CollectFS : public llvm::vfs::ProxyFileSystem {
49  public:
50  CollectFS(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
51  PreambleFileStatusCache &StatCache)
52  : ProxyFileSystem(std::move(FS)), StatCache(StatCache) {}
53 
54  llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
55  openFileForRead(const llvm::Twine &Path) override {
56  auto File = getUnderlyingFS().openFileForRead(Path);
57  if (!File || !*File)
58  return File;
59  // Eagerly stat opened file, as the followup `status` call on the file
60  // doesn't necessarily go through this FS. This puts some extra work on
61  // preamble build, but it should be worth it as preamble can be reused
62  // many times (e.g. code completion) and the repeated status call is
63  // likely to be cached in the underlying file system anyway.
64  if (auto S = File->get()->status())
65  StatCache.update(getUnderlyingFS(), std::move(*S));
66  return File;
67  }
68 
69  llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
70  auto S = getUnderlyingFS().status(Path);
71  if (S)
72  StatCache.update(getUnderlyingFS(), *S);
73  return S;
74  }
75 
76  private:
77  PreambleFileStatusCache &StatCache;
78  };
79  return llvm::IntrusiveRefCntPtr<CollectFS>(
80  new CollectFS(std::move(FS), *this));
81 }
82 
83 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
85  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) const {
86  class CacheVFS : public llvm::vfs::ProxyFileSystem {
87  public:
88  CacheVFS(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
89  const PreambleFileStatusCache &StatCache)
90  : ProxyFileSystem(std::move(FS)), StatCache(StatCache) {}
91 
92  llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
93  if (auto S = StatCache.lookup(Path.str()))
94  return *S;
95  return getUnderlyingFS().status(Path);
96  }
97 
98  private:
99  const PreambleFileStatusCache &StatCache;
100  };
101  return llvm::IntrusiveRefCntPtr<CacheVFS>(new CacheVFS(std::move(FS), *this));
102 }
103 
104 } // namespace clangd
105 } // namespace clang
void update(const llvm::vfs::FileSystem &FS, llvm::vfs::Status S)
Definition: FS.cpp:23
llvm::Optional< llvm::vfs::Status > lookup(llvm::StringRef Path) const
Path is a path stored in preamble.
Definition: FS.cpp:36
PreambleFileStatusCache(llvm::StringRef MainFilePath)
MainFilePath is the absolute path of the main source file this preamble corresponds to...
Definition: FS.cpp:18
Documents should not be synced at all.
IntrusiveRefCntPtr< llvm::vfs::FileSystem > getConsumingFS(IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS) const
Returns a VFS that uses the cache collected.
Definition: FS.cpp:84
IntrusiveRefCntPtr< llvm::vfs::FileSystem > getProducingFS(IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
Returns a VFS that collects file status.
Definition: FS.cpp:44
std::string Path
A typedef to represent a file path.
Definition: Path.h:21
Records status information for files open()ed or stat()ed during preamble build (except for the main ...
Definition: FS.h:37
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//