brintos

brintos / llvm-project-archived public Read only

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