clang-tools  8.0.0
FSProvider.cpp
Go to the documentation of this file.
1 //===--- FSProvider.cpp - VFS provider for ClangdServer -------------------===//
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 "FSProvider.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/Path.h"
15 #include "llvm/Support/VirtualFileSystem.h"
16 #include <memory>
17 
18 namespace clang {
19 namespace clangd {
20 
21 namespace {
22 /// Always opens files in the underlying filesystem as "volatile", meaning they
23 /// won't be memory-mapped. This avoid locking the files on Windows.
24 class VolatileFileSystem : public llvm::vfs::ProxyFileSystem {
25 public:
26  explicit VolatileFileSystem(llvm::IntrusiveRefCntPtr<FileSystem> FS)
27  : ProxyFileSystem(std::move(FS)) {}
28 
29  llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
30  openFileForRead(const llvm::Twine &InPath) override {
31  llvm::SmallString<128> Path;
32  InPath.toVector(Path);
33 
34  auto File = getUnderlyingFS().openFileForRead(Path);
35  if (!File)
36  return File;
37  // Try to guess preamble files, they can be memory-mapped even on Windows as
38  // clangd has exclusive access to those.
39  llvm::StringRef FileName = llvm::sys::path::filename(Path);
40  if (FileName.startswith("preamble-") && FileName.endswith(".pch"))
41  return File;
42  return std::unique_ptr<VolatileFile>(new VolatileFile(std::move(*File)));
43  }
44 
45 private:
46  class VolatileFile : public llvm::vfs::File {
47  public:
48  VolatileFile(std::unique_ptr<llvm::vfs::File> Wrapped)
49  : Wrapped(std::move(Wrapped)) {
50  assert(this->Wrapped);
51  }
52 
53  virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
54  getBuffer(const llvm::Twine &Name, int64_t FileSize,
55  bool RequiresNullTerminator, bool /*IsVolatile*/) override {
56  return Wrapped->getBuffer(Name, FileSize, RequiresNullTerminator,
57  /*IsVolatile=*/true);
58  }
59 
60  llvm::ErrorOr<llvm::vfs::Status> status() override {
61  return Wrapped->status();
62  }
63  llvm::ErrorOr<std::string> getName() override { return Wrapped->getName(); }
64  std::error_code close() override { return Wrapped->close(); }
65 
66  private:
67  std::unique_ptr<File> Wrapped;
68  };
69 };
70 } // namespace
71 
72 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
74 // Avoid using memory-mapped files on Windows, they cause file locking issues.
75 // FIXME: Try to use a similar approach in Sema instead of relying on
76 // propagation of the 'isVolatile' flag through all layers.
77 #ifdef _WIN32
78  return new VolatileFileSystem(llvm::vfs::getRealFileSystem());
79 #else
80  return llvm::vfs::getRealFileSystem();
81 #endif
82 }
83 } // namespace clangd
84 } // namespace clang
std::string Path
A typedef to represent a file path.
Definition: Path.h:21
static constexpr llvm::StringLiteral Name
PathRef FileName
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > getFileSystem() const override
Called by ClangdServer to obtain a vfs::FileSystem to be used for parsing.
Definition: FSProvider.cpp:73