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