Mercurial > hg > CbC > CbC_llvm
view clang-tools-extra/clangd/DraftStore.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 0572611fdcc8 |
line wrap: on
line source
//===--- DraftStore.cpp - File contents container ---------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "DraftStore.h" #include "SourceCode.h" #include "llvm/Support/Errc.h" namespace clang { namespace clangd { llvm::Optional<std::string> DraftStore::getDraft(PathRef File) const { std::lock_guard<std::mutex> Lock(Mutex); auto It = Drafts.find(File); if (It == Drafts.end()) return None; return It->second; } std::vector<Path> DraftStore::getActiveFiles() const { std::lock_guard<std::mutex> Lock(Mutex); std::vector<Path> ResultVector; for (auto DraftIt = Drafts.begin(); DraftIt != Drafts.end(); DraftIt++) ResultVector.push_back(std::string(DraftIt->getKey())); return ResultVector; } void DraftStore::addDraft(PathRef File, llvm::StringRef Contents) { std::lock_guard<std::mutex> Lock(Mutex); Drafts[File] = std::string(Contents); } llvm::Expected<std::string> DraftStore::updateDraft( PathRef File, llvm::ArrayRef<TextDocumentContentChangeEvent> Changes) { std::lock_guard<std::mutex> Lock(Mutex); auto EntryIt = Drafts.find(File); if (EntryIt == Drafts.end()) { return llvm::make_error<llvm::StringError>( "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<size_t> StartIndex = positionToOffset(Contents, Start, false); if (!StartIndex) return StartIndex.takeError(); const Position &End = Change.range->end; llvm::Expected<size_t> EndIndex = positionToOffset(Contents, End, false); if (!EndIndex) return EndIndex.takeError(); if (*EndIndex < *StartIndex) return llvm::make_error<llvm::StringError>( llvm::formatv( "Range's end position ({0}) is before start position ({1})", End, Start), llvm::errc::invalid_argument); // Since the range length between two LSP positions is dependent on the // contents of the buffer we compute the range length between the start and // end position ourselves and compare it to the range length of the LSP // message to verify the buffers of the client and server are in sync. // EndIndex and StartIndex are in bytes, but Change.rangeLength is in UTF-16 // code units. ssize_t ComputedRangeLength = lspLength(Contents.substr(*StartIndex, *EndIndex - *StartIndex)); if (Change.rangeLength && ComputedRangeLength != *Change.rangeLength) return llvm::make_error<llvm::StringError>( llvm::formatv("Change's rangeLength ({0}) doesn't match the " "computed range length ({1}).", *Change.rangeLength, ComputedRangeLength), 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<std::mutex> Lock(Mutex); Drafts.erase(File); } } // namespace clangd } // namespace clang