//===--- DraftStore.cpp - File contents container ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "DraftStore.h" #include "SourceCode.h" #include "llvm/Support/Errc.h" using namespace clang; using namespace clang::clangd; llvm::Optional DraftStore::getDraft(PathRef File) const { std::lock_guard Lock(Mutex); auto It = Drafts.find(File); if (It == Drafts.end()) return llvm::None; return It->second; } std::vector DraftStore::getActiveFiles() const { std::lock_guard Lock(Mutex); std::vector ResultVector; for (auto DraftIt = Drafts.begin(); DraftIt != Drafts.end(); DraftIt++) ResultVector.push_back(DraftIt->getKey()); return ResultVector; } void DraftStore::addDraft(PathRef File, StringRef Contents) { std::lock_guard Lock(Mutex); Drafts[File] = Contents; } llvm::Expected DraftStore::updateDraft( PathRef File, llvm::ArrayRef Changes) { std::lock_guard Lock(Mutex); auto EntryIt = Drafts.find(File); if (EntryIt == Drafts.end()) { return llvm::make_error( "Trying to do incremental update on non-added document: " + File, llvm::errc::invalid_argument); } std::string Contents = EntryIt->second; for (const TextDocumentContentChangeEvent &Change : Changes) { if (!Change.range) { Contents = Change.text; continue; } const Position &Start = Change.range->start; llvm::Expected StartIndex = positionToOffset(Contents, Start, false); if (!StartIndex) return StartIndex.takeError(); const Position &End = Change.range->end; llvm::Expected EndIndex = positionToOffset(Contents, End, false); if (!EndIndex) return EndIndex.takeError(); if (*EndIndex < *StartIndex) return llvm::make_error( llvm::formatv( "Range's end position ({0}) is before start position ({1})", End, Start), llvm::errc::invalid_argument); if (Change.rangeLength && (ssize_t)(*EndIndex - *StartIndex) != *Change.rangeLength) return llvm::make_error( llvm::formatv("Change's rangeLength ({0}) doesn't match the " "computed range length ({1}).", *Change.rangeLength, *EndIndex - *StartIndex), llvm::errc::invalid_argument); std::string NewContents; NewContents.reserve(*StartIndex + Change.text.length() + (Contents.length() - *EndIndex)); NewContents = Contents.substr(0, *StartIndex); NewContents += Change.text; NewContents += Contents.substr(*EndIndex); Contents = std::move(NewContents); } EntryIt->second = Contents; return Contents; } void DraftStore::removeDraft(PathRef File) { std::lock_guard Lock(Mutex); Drafts.erase(File); }