clang-tools  16.0.0git
DraftStore.cpp
Go to the documentation of this file.
1 //===--- DraftStore.cpp - File contents container ---------------*- 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 "DraftStore.h"
10 #include "support/Logger.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/Support/VirtualFileSystem.h"
13 #include <memory>
14 
15 namespace clang {
16 namespace clangd {
17 
18 llvm::Optional<DraftStore::Draft> DraftStore::getDraft(PathRef File) const {
19  std::lock_guard<std::mutex> Lock(Mutex);
20 
21  auto It = Drafts.find(File);
22  if (It == Drafts.end())
23  return None;
24 
25  return It->second.D;
26 }
27 
28 std::vector<Path> DraftStore::getActiveFiles() const {
29  std::lock_guard<std::mutex> Lock(Mutex);
30  std::vector<Path> ResultVector;
31 
32  for (auto DraftIt = Drafts.begin(); DraftIt != Drafts.end(); DraftIt++)
33  ResultVector.push_back(std::string(DraftIt->getKey()));
34 
35  return ResultVector;
36 }
37 
38 static void increment(std::string &S) {
39  // Ensure there is a numeric suffix.
40  if (S.empty() || !llvm::isDigit(S.back())) {
41  S.push_back('0');
42  return;
43  }
44  // Increment the numeric suffix.
45  auto I = S.rbegin(), E = S.rend();
46  for (;;) {
47  if (I == E || !llvm::isDigit(*I)) {
48  // Reached start of numeric section, it was all 9s.
49  S.insert(I.base(), '1');
50  break;
51  }
52  if (*I != '9') {
53  // Found a digit we can increment, we're done.
54  ++*I;
55  break;
56  }
57  *I = '0'; // and keep incrementing to the left.
58  }
59 }
60 
62  llvm::StringRef SpecifiedVersion) {
63  if (!SpecifiedVersion.empty()) {
64  // We treat versions as opaque, but the protocol says they increase.
65  if (SpecifiedVersion.compare_numeric(D.Version) <= 0)
66  log("File version went from {0} to {1}", D.Version, SpecifiedVersion);
67  D.Version = SpecifiedVersion.str();
68  } else {
69  // Note that if D was newly-created, this will bump D.Version from "" to 1.
70  increment(D.Version);
71  }
72 }
73 
74 std::string DraftStore::addDraft(PathRef File, llvm::StringRef Version,
75  llvm::StringRef Contents) {
76  std::lock_guard<std::mutex> Lock(Mutex);
77 
78  auto &D = Drafts[File];
79  updateVersion(D.D, Version);
80  std::time(&D.MTime);
81  D.D.Contents = std::make_shared<std::string>(Contents);
82  return D.D.Version;
83 }
84 
86  std::lock_guard<std::mutex> Lock(Mutex);
87 
88  Drafts.erase(File);
89 }
90 
91 namespace {
92 
93 /// A read only MemoryBuffer shares ownership of a ref counted string. The
94 /// shared string object must not be modified while an owned by this buffer.
95 class SharedStringBuffer : public llvm::MemoryBuffer {
96  const std::shared_ptr<const std::string> BufferContents;
97  const std::string Name;
98 
99 public:
100  BufferKind getBufferKind() const override {
101  return MemoryBuffer::MemoryBuffer_Malloc;
102  }
103 
104  StringRef getBufferIdentifier() const override { return Name; }
105 
106  SharedStringBuffer(std::shared_ptr<const std::string> Data, StringRef Name)
107  : BufferContents(std::move(Data)), Name(Name) {
108  assert(BufferContents && "Can't create from empty shared_ptr");
109  MemoryBuffer::init(BufferContents->c_str(),
110  BufferContents->c_str() + BufferContents->size(),
111  /*RequiresNullTerminator=*/true);
112  }
113 };
114 } // namespace
115 
116 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> DraftStore::asVFS() const {
117  auto MemFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
118  std::lock_guard<std::mutex> Guard(Mutex);
119  for (const auto &Draft : Drafts)
120  MemFS->addFile(Draft.getKey(), Draft.getValue().MTime,
121  std::make_unique<SharedStringBuffer>(
122  Draft.getValue().D.Contents, Draft.getKey()));
123  return MemFS;
124 }
125 } // namespace clangd
126 } // namespace clang
clang::clangd::updateVersion
static void updateVersion(DraftStore::Draft &D, llvm::StringRef SpecifiedVersion)
Definition: DraftStore.cpp:61
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
clang::clangd::DraftStore::addDraft
std::string addDraft(PathRef File, llvm::StringRef Version, StringRef Contents)
Replace contents of the draft for File with Contents.
Definition: DraftStore.cpp:74
DraftStore.h
clang::clangd::increment
static void increment(std::string &S)
Definition: ClangdLSPServer.cpp:1470
clang::clangd::DraftStore::removeDraft
void removeDraft(PathRef File)
Remove the draft from the store.
Definition: DraftStore.cpp:85
ns1::ns2::D
@ D
Definition: CategoricalFeature.h:3
Logger.h
clang::clangd::DraftStore::getActiveFiles
std::vector< Path > getActiveFiles() const
Definition: DraftStore.cpp:28
clang::clangd::DraftStore::getDraft
llvm::Optional< Draft > getDraft(PathRef File) const
Definition: DraftStore.cpp:18
clang::clangd::DraftStore::Draft::Contents
std::shared_ptr< const std::string > Contents
Definition: DraftStore.h:30
clang::clangd::DraftStore::asVFS
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > asVFS() const
Definition: DraftStore.cpp:116
Name
Token Name
Definition: MacroToEnumCheck.cpp:89
clang::clangd::DraftStore::Draft
Definition: DraftStore.h:29
clang::clangd::log
void log(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:67
clang::clangd::PathRef
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:29
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27