<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Even after Simon’s fix there is still a test failure (<a href="http://lab.llvm.org:8080/green/job/clang-stage1-configure-RA_check/31377/consoleFull#18373900728254eaf0-7326-4999-85b0-388101f2d404" class="">http://lab.llvm.org:8080/green/job/clang-stage1-configure-RA_check/31377/consoleFull#18373900728254eaf0-7326-4999-85b0-388101f2d404</a>). Reverted the original commit and the fix in r303093 and r303094.<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On May 15, 2017, at 10:06 AM, Adam Nemet <<a href="mailto:anemet@apple.com" class="">anemet@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi Simon,<div class=""><br class=""></div><div class="">Is r303078 supposed to fix this?</div><div class=""><br class=""></div><div class="">Adam</div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On May 15, 2017, at 9:28 AM, Adam Nemet <<a href="mailto:anemet@apple.com" class="">anemet@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">This broke the build <a href="http://green.lab.llvm.org/green/job/clang-stage1-configure-RA/34305/" class="">http://green.lab.llvm.org/green/job/clang-stage1-configure-RA/34305/</a>, please take a look.<div class=""><br class=""></div><div class="">Adam</div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On May 15, 2017, at 7:17 AM, Ilya Biryukov via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Author: ibiryukov<br class="">Date: Mon May 15 09:17:35 2017<br class="">New Revision: 303067<br class=""><br class="">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=303067&view=rev" class="">http://llvm.org/viewvc/llvm-project?rev=303067&view=rev</a><br class="">Log:<br class="">[ClangD] Refactor clangd into separate components<br class=""><br class="">Summary: Major refactoring to split LSP implementation, Clang API calls and threading(mostly synchronization)<br class=""><br class="">Reviewers: bkramer, krasimir<br class=""><br class="">Reviewed By: bkramer<br class=""><br class="">Subscribers: cfe-commits, mgorny, klimek<br class=""><br class="">Tags: #clang-tools-extra<br class=""><br class="">Differential Revision: <a href="https://reviews.llvm.org/D33047" class="">https://reviews.llvm.org/D33047</a><br class=""><br class="">Added:<br class=""> clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp<br class=""> clang-tools-extra/trunk/clangd/ClangdLSPServer.h<br class=""> clang-tools-extra/trunk/clangd/ClangdServer.cpp<br class=""> - copied, changed from r303060, clang-tools-extra/trunk/clangd/ASTManager.cpp<br class=""> clang-tools-extra/trunk/clangd/ClangdServer.h<br class=""> - copied, changed from r303063, clang-tools-extra/trunk/clangd/ASTManager.h<br class=""> clang-tools-extra/trunk/clangd/ClangdUnit.cpp<br class=""> clang-tools-extra/trunk/clangd/ClangdUnit.h<br class=""> clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp<br class=""> clang-tools-extra/trunk/clangd/ClangdUnitStore.h<br class=""> clang-tools-extra/trunk/clangd/DraftStore.cpp<br class=""> clang-tools-extra/trunk/clangd/DraftStore.h<br class=""> - copied, changed from r303060, clang-tools-extra/trunk/clangd/DocumentStore.h<br class=""> clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp<br class=""> clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h<br class=""> clang-tools-extra/trunk/clangd/Path.h<br class="">Removed:<br class=""> clang-tools-extra/trunk/clangd/ASTManager.cpp<br class=""> clang-tools-extra/trunk/clangd/ASTManager.h<br class=""> clang-tools-extra/trunk/clangd/DocumentStore.h<br class="">Modified:<br class=""> clang-tools-extra/trunk/clangd/CMakeLists.txt<br class=""> clang-tools-extra/trunk/clangd/ClangdMain.cpp<br class=""> clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp<br class=""> clang-tools-extra/trunk/clangd/ProtocolHandlers.h<br class=""><br class="">Removed: clang-tools-extra/trunk/clangd/ASTManager.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ASTManager.cpp?rev=303066&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ASTManager.cpp?rev=303066&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ASTManager.cpp (original)<br class="">+++ clang-tools-extra/trunk/clangd/ASTManager.cpp (removed)<br class="">@@ -1,440 +0,0 @@<br class="">-//===--- ASTManager.cpp - Clang AST manager -------------------------------===//<br class="">-//<br class="">-// The LLVM Compiler Infrastructure<br class="">-//<br class="">-// This file is distributed under the University of Illinois Open Source<br class="">-// License. See LICENSE.TXT for details.<br class="">-//<br class="">-//===----------------------------------------------------------------------===//<br class="">-<br class="">-#include "ASTManager.h"<br class="">-#include "JSONRPCDispatcher.h"<br class="">-#include "Protocol.h"<br class="">-#include "clang/Frontend/ASTUnit.h"<br class="">-#include "clang/Frontend/CompilerInstance.h"<br class="">-#include "clang/Tooling/CompilationDatabase.h"<br class="">-#include "llvm/Support/Format.h"<br class="">-#include "llvm/Support/Path.h"<br class="">-#include <mutex><br class="">-#include <thread><br class="">-using namespace clang;<br class="">-using namespace clangd;<br class="">-<br class="">-void DocData::setAST(std::unique_ptr<ASTUnit> AST) {<br class="">- this->AST = std::move(AST);<br class="">-}<br class="">-<br class="">-ASTUnit *DocData::getAST() const { return AST.get(); }<br class="">-<br class="">-void DocData::cacheFixIts(DiagnosticToReplacementMap FixIts) {<br class="">- this->FixIts = std::move(FixIts);<br class="">-}<br class="">-<br class="">-std::vector<clang::tooling::Replacement><br class="">-DocData::getFixIts(const clangd::Diagnostic &D) const {<br class="">- auto it = FixIts.find(D);<br class="">- if (it != FixIts.end())<br class="">- return it->second;<br class="">- return {};<br class="">-}<br class="">-<br class="">-ASTManagerRequest::ASTManagerRequest(ASTManagerRequestType Type,<br class="">- std::string File,<br class="">- DocVersion Version)<br class="">- : Type(Type), File(File), Version(Version) {}<br class="">-<br class="">-/// Retrieve a copy of the contents of every file in the store, for feeding into<br class="">-/// ASTUnit.<br class="">-static std::vector<ASTUnit::RemappedFile><br class="">-getRemappedFiles(const DocumentStore &Docs) {<br class="">- // FIXME: Use VFS instead. This would allow us to get rid of the chdir below.<br class="">- std::vector<ASTUnit::RemappedFile> RemappedFiles;<br class="">- for (const auto &P : Docs.getAllDocuments()) {<br class="">- StringRef FileName = P.first;<br class="">- RemappedFiles.push_back(ASTUnit::RemappedFile(<br class="">- FileName,<br class="">- llvm::MemoryBuffer::getMemBufferCopy(P.second, FileName).release()));<br class="">- }<br class="">- return RemappedFiles;<br class="">-}<br class="">-<br class="">-/// Convert from clang diagnostic level to LSP severity.<br class="">-static int getSeverity(DiagnosticsEngine::Level L) {<br class="">- switch (L) {<br class="">- case DiagnosticsEngine::Remark:<br class="">- return 4;<br class="">- case DiagnosticsEngine::Note:<br class="">- return 3;<br class="">- case DiagnosticsEngine::Warning:<br class="">- return 2;<br class="">- case DiagnosticsEngine::Fatal:<br class="">- case DiagnosticsEngine::Error:<br class="">- return 1;<br class="">- case DiagnosticsEngine::Ignored:<br class="">- return 0;<br class="">- }<br class="">- llvm_unreachable("Unknown diagnostic level!");<br class="">-}<br class="">-<br class="">-static CompletionItemKind getKind(CXCursorKind K) {<br class="">- switch (K) {<br class="">- case CXCursor_MacroInstantiation:<br class="">- case CXCursor_MacroDefinition:<br class="">- return CompletionItemKind::Text;<br class="">- case CXCursor_CXXMethod:<br class="">- return CompletionItemKind::Method;<br class="">- case CXCursor_FunctionDecl:<br class="">- case CXCursor_FunctionTemplate:<br class="">- return CompletionItemKind::Function;<br class="">- case CXCursor_Constructor:<br class="">- case CXCursor_Destructor:<br class="">- return CompletionItemKind::Constructor;<br class="">- case CXCursor_FieldDecl:<br class="">- return CompletionItemKind::Field;<br class="">- case CXCursor_VarDecl:<br class="">- case CXCursor_ParmDecl:<br class="">- return CompletionItemKind::Variable;<br class="">- case CXCursor_ClassDecl:<br class="">- case CXCursor_StructDecl:<br class="">- case CXCursor_UnionDecl:<br class="">- case CXCursor_ClassTemplate:<br class="">- case CXCursor_ClassTemplatePartialSpecialization:<br class="">- return CompletionItemKind::Class;<br class="">- case CXCursor_Namespace:<br class="">- case CXCursor_NamespaceAlias:<br class="">- case CXCursor_NamespaceRef:<br class="">- return CompletionItemKind::Module;<br class="">- case CXCursor_EnumConstantDecl:<br class="">- return CompletionItemKind::Value;<br class="">- case CXCursor_EnumDecl:<br class="">- return CompletionItemKind::Enum;<br class="">- case CXCursor_TypeAliasDecl:<br class="">- case CXCursor_TypeAliasTemplateDecl:<br class="">- case CXCursor_TypedefDecl:<br class="">- case CXCursor_MemberRef:<br class="">- case CXCursor_TypeRef:<br class="">- return CompletionItemKind::Reference;<br class="">- default:<br class="">- return CompletionItemKind::Missing;<br class="">- }<br class="">-}<br class="">-<br class="">-ASTManager::ASTManager(JSONOutput &Output, DocumentStore &Store,<br class="">- bool RunSynchronously)<br class="">- : Output(Output), Store(Store), RunSynchronously(RunSynchronously),<br class="">- PCHs(std::make_shared<PCHContainerOperations>()),<br class="">- ClangWorker([this]() { runWorker(); }) {}<br class="">-<br class="">-void ASTManager::runWorker() {<br class="">- while (true) {<br class="">- ASTManagerRequest Request;<br class="">-<br class="">- // Pick request from the queue<br class="">- {<br class="">- std::unique_lock<std::mutex> Lock(RequestLock);<br class="">- // Wait for more requests.<br class="">- ClangRequestCV.wait(Lock,<br class="">- [this] { return !RequestQueue.empty() || Done; });<br class="">- if (Done)<br class="">- return;<br class="">- assert(!RequestQueue.empty() && "RequestQueue was empty");<br class="">-<br class="">- Request = std::move(RequestQueue.back());<br class="">- RequestQueue.pop_back();<br class="">-<br class="">- // Skip outdated requests<br class="">- if (Request.Version != DocVersions.find(Request.File)->second) {<br class="">- Output.log("Version for " + Twine(Request.File) +<br class="">- " in request is outdated, skipping request\n");<br class="">- continue;<br class="">- }<br class="">- } // unlock RequestLock<br class="">-<br class="">- handleRequest(Request.Type, Request.File);<br class="">- }<br class="">-}<br class="">-<br class="">-void ASTManager::queueOrRun(ASTManagerRequestType RequestType, StringRef File) {<br class="">- if (RunSynchronously) {<br class="">- handleRequest(RequestType, File);<br class="">- return;<br class="">- }<br class="">-<br class="">- std::lock_guard<std::mutex> Guard(RequestLock);<br class="">- // We increment the version of the added document immediately and schedule<br class="">- // the requested operation to be run on a worker thread<br class="">- DocVersion version = ++DocVersions[File];<br class="">- RequestQueue.push_back(ASTManagerRequest(RequestType, File, version));<br class="">- ClangRequestCV.notify_one();<br class="">-}<br class="">-<br class="">-void ASTManager::handleRequest(ASTManagerRequestType RequestType,<br class="">- StringRef File) {<br class="">- switch (RequestType) {<br class="">- case ASTManagerRequestType::ParseAndPublishDiagnostics:<br class="">- parseFileAndPublishDiagnostics(File);<br class="">- break;<br class="">- case ASTManagerRequestType::RemoveDocData: {<br class="">- std::lock_guard<std::mutex> Lock(ClangObjectLock);<br class="">- auto DocDataIt = DocDatas.find(File);<br class="">- // We could get the remove request before parsing for the document is<br class="">- // started, just do nothing in that case, parsing request will be discarded<br class="">- // because it has a lower version value<br class="">- if (DocDataIt == DocDatas.end())<br class="">- return;<br class="">- DocDatas.erase(DocDataIt);<br class="">- break;<br class="">- } // unlock ClangObjectLock<br class="">- }<br class="">-}<br class="">-<br class="">-void ASTManager::parseFileAndPublishDiagnostics(StringRef File) {<br class="">- std::unique_lock<std::mutex> ClangObjectLockGuard(ClangObjectLock);<br class="">-<br class="">- auto &DocData = DocDatas[File];<br class="">- ASTUnit *Unit = DocData.getAST();<br class="">- if (!Unit) {<br class="">- auto newAST = createASTUnitForFile(File, this->Store);<br class="">- Unit = newAST.get();<br class="">-<br class="">- DocData.setAST(std::move(newAST));<br class="">- } else {<br class="">- // Do a reparse if this wasn't the first parse.<br class="">- // FIXME: This might have the wrong working directory if it changed in the<br class="">- // meantime.<br class="">- Unit->Reparse(PCHs, getRemappedFiles(this->Store));<br class="">- }<br class="">-<br class="">- if (!Unit)<br class="">- return;<br class="">-<br class="">- // Send the diagnotics to the editor.<br class="">- // FIXME: If the diagnostic comes from a different file, do we want to<br class="">- // show them all? Right now we drop everything not coming from the<br class="">- // main file.<br class="">- std::string Diagnostics;<br class="">- DocData::DiagnosticToReplacementMap LocalFixIts; // Temporary storage<br class="">- for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),<br class="">- DEnd = Unit->stored_diag_end();<br class="">- D != DEnd; ++D) {<br class="">- if (!D->getLocation().isValid() ||<br class="">- !D->getLocation().getManager().isInMainFile(D->getLocation()))<br class="">- continue;<br class="">- Position P;<br class="">- P.line = D->getLocation().getSpellingLineNumber() - 1;<br class="">- P.character = D->getLocation().getSpellingColumnNumber();<br class="">- Range R = {P, P};<br class="">- Diagnostics +=<br class="">- R"({"range":)" + Range::unparse(R) +<br class="">- R"(,"severity":)" + std::to_string(getSeverity(D->getLevel())) +<br class="">- R"(,"message":")" + llvm::yaml::escape(D->getMessage()) +<br class="">- R"("},)";<br class="">-<br class="">- // We convert to Replacements to become independent of the SourceManager.<br class="">- clangd::Diagnostic Diag = {R, getSeverity(D->getLevel()), D->getMessage()};<br class="">- auto &FixItsForDiagnostic = LocalFixIts[Diag];<br class="">- for (const FixItHint &Fix : D->getFixIts()) {<br class="">- FixItsForDiagnostic.push_back(clang::tooling::Replacement(<br class="">- Unit->getSourceManager(), Fix.RemoveRange, Fix.CodeToInsert));<br class="">- }<br class="">- }<br class="">-<br class="">- // Put FixIts into place.<br class="">- DocData.cacheFixIts(std::move(LocalFixIts));<br class="">-<br class="">- ClangObjectLockGuard.unlock();<br class="">- // No accesses to clang objects are allowed after this point.<br class="">-<br class="">- // Publish diagnostics.<br class="">- if (!Diagnostics.empty())<br class="">- Diagnostics.pop_back(); // Drop trailing comma.<br class="">- Output.writeMessage(<br class="">- R"({"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":")" +<br class="">- URI::fromFile(File).uri + R"(","diagnostics":[)" + Diagnostics + R"(]}})");<br class="">-}<br class="">-<br class="">-ASTManager::~ASTManager() {<br class="">- {<br class="">- std::lock_guard<std::mutex> Guard(RequestLock);<br class="">- // Wake up the clang worker thread, then exit.<br class="">- Done = true;<br class="">- ClangRequestCV.notify_one();<br class="">- } // unlock DocDataLock<br class="">- ClangWorker.join();<br class="">-}<br class="">-<br class="">-void ASTManager::onDocumentAdd(StringRef File) {<br class="">- queueOrRun(ASTManagerRequestType::ParseAndPublishDiagnostics, File);<br class="">-}<br class="">-<br class="">-void ASTManager::onDocumentRemove(StringRef File) {<br class="">- queueOrRun(ASTManagerRequestType::RemoveDocData, File);<br class="">-}<br class="">-<br class="">-tooling::CompilationDatabase *<br class="">-ASTManager::getOrCreateCompilationDatabaseForFile(StringRef File) {<br class="">- namespace path = llvm::sys::path;<br class="">-<br class="">- assert((path::is_absolute(File, path::Style::posix) ||<br class="">- path::is_absolute(File, path::Style::windows)) &&<br class="">- "path must be absolute");<br class="">-<br class="">- for (auto Path = path::parent_path(File); !Path.empty();<br class="">- Path = path::parent_path(Path)) {<br class="">-<br class="">- auto CachedIt = CompilationDatabases.find(Path);<br class="">- if (CachedIt != CompilationDatabases.end())<br class="">- return CachedIt->second.get();<br class="">- std::string Error;<br class="">- auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error);<br class="">- if (!CDB) {<br class="">- if (!Error.empty()) {<br class="">- Output.log("Error when trying to load compilation database from " +<br class="">- Twine(Path) + ": " + Twine(Error) + "\n");<br class="">- }<br class="">- continue;<br class="">- }<br class="">-<br class="">- // TODO(ibiryukov): Invalidate cached compilation databases on changes<br class="">- auto result = CDB.get();<br class="">- CompilationDatabases.insert(std::make_pair(Path, std::move(CDB)));<br class="">- return result;<br class="">- }<br class="">-<br class="">- Output.log("Failed to find compilation database for " + Twine(File) + "\n");<br class="">- return nullptr;<br class="">-}<br class="">-<br class="">-std::unique_ptr<clang::ASTUnit><br class="">-ASTManager::createASTUnitForFile(StringRef File, const DocumentStore &Docs) {<br class="">- tooling::CompilationDatabase *CDB =<br class="">- getOrCreateCompilationDatabaseForFile(File);<br class="">-<br class="">- std::vector<tooling::CompileCommand> Commands;<br class="">-<br class="">- if (CDB) {<br class="">- Commands = CDB->getCompileCommands(File);<br class="">- // chdir. This is thread hostile.<br class="">- if (!Commands.empty())<br class="">- llvm::sys::fs::set_current_path(Commands.front().Directory);<br class="">- }<br class="">- if (Commands.empty()) {<br class="">- // Add a fake command line if we know nothing.<br class="">- Commands.push_back(tooling::CompileCommand(<br class="">- llvm::sys::path::parent_path(File), llvm::sys::path::filename(File),<br class="">- {"clang", "-fsyntax-only", File.str()}, ""));<br class="">- }<br class="">-<br class="">- // Inject the resource dir.<br class="">- // FIXME: Don't overwrite it if it's already there.<br class="">- static int Dummy; // Just an address in this process.<br class="">- std::string ResourceDir =<br class="">- CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);<br class="">- Commands.front().CommandLine.push_back("-resource-dir=" + ResourceDir);<br class="">-<br class="">- IntrusiveRefCntPtr<DiagnosticsEngine> Diags =<br class="">- CompilerInstance::createDiagnostics(new DiagnosticOptions);<br class="">-<br class="">- std::vector<const char *> ArgStrs;<br class="">- for (const auto &S : Commands.front().CommandLine)<br class="">- ArgStrs.push_back(S.c_str());<br class="">-<br class="">- auto ArgP = &*ArgStrs.begin();<br class="">- return std::unique_ptr<clang::ASTUnit>(ASTUnit::LoadFromCommandLine(<br class="">- ArgP, ArgP + ArgStrs.size(), PCHs, Diags, ResourceDir,<br class="">- /*OnlyLocalDecls=*/false, /*CaptureDiagnostics=*/true,<br class="">- getRemappedFiles(Docs),<br class="">- /*RemappedFilesKeepOriginalName=*/true,<br class="">- /*PrecompilePreambleAfterNParses=*/1, /*TUKind=*/TU_Complete,<br class="">- /*CacheCodeCompletionResults=*/true,<br class="">- /*IncludeBriefCommentsInCodeCompletion=*/true,<br class="">- /*AllowPCHWithCompilerErrors=*/true));<br class="">-}<br class="">-<br class="">-std::vector<clang::tooling::Replacement><br class="">-ASTManager::getFixIts(StringRef File, const clangd::Diagnostic &D) {<br class="">- // TODO(ibiryukov): the FixIts should be available immediately<br class="">- // even when parsing is being run on a worker thread<br class="">- std::lock_guard<std::mutex> Guard(ClangObjectLock);<br class="">- return DocDatas[File].getFixIts(D);<br class="">-}<br class="">-<br class="">-namespace {<br class="">-class CompletionItemsCollector : public CodeCompleteConsumer {<br class="">- std::vector<CompletionItem> *Items;<br class="">- std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;<br class="">- CodeCompletionTUInfo CCTUInfo;<br class="">-<br class="">-public:<br class="">- CompletionItemsCollector(std::vector<CompletionItem> *Items,<br class="">- const CodeCompleteOptions &CodeCompleteOpts)<br class="">- : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),<br class="">- Items(Items),<br class="">- Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),<br class="">- CCTUInfo(Allocator) {}<br class="">-<br class="">- void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,<br class="">- CodeCompletionResult *Results,<br class="">- unsigned NumResults) override {<br class="">- for (unsigned I = 0; I != NumResults; ++I) {<br class="">- CodeCompletionResult &Result = Results[I];<br class="">- CodeCompletionString *CCS = Result.CreateCodeCompletionString(<br class="">- S, Context, *Allocator, CCTUInfo,<br class="">- CodeCompleteOpts.IncludeBriefComments);<br class="">- if (CCS) {<br class="">- CompletionItem Item;<br class="">- assert(CCS->getTypedText());<br class="">- Item.label = CCS->getTypedText();<br class="">- Item.kind = getKind(Result.CursorKind);<br class="">- if (CCS->getBriefComment())<br class="">- Item.documentation = CCS->getBriefComment();<br class="">- Items->push_back(std::move(Item));<br class="">- }<br class="">- }<br class="">- }<br class="">-<br class="">- GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }<br class="">-<br class="">- CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }<br class="">-};<br class="">-<br class="">-} // namespace<br class="">-<br class="">-std::vector<CompletionItem><br class="">-ASTManager::codeComplete(StringRef File, unsigned Line, unsigned Column) {<br class="">- CodeCompleteOptions CCO;<br class="">- CCO.IncludeBriefComments = 1;<br class="">- // This is where code completion stores dirty buffers. Need to free after<br class="">- // completion.<br class="">- SmallVector<const llvm::MemoryBuffer *, 4> OwnedBuffers;<br class="">- SmallVector<StoredDiagnostic, 4> StoredDiagnostics;<br class="">- IntrusiveRefCntPtr<DiagnosticsEngine> DiagEngine(<br class="">- new DiagnosticsEngine(new DiagnosticIDs, new DiagnosticOptions));<br class="">- std::vector<CompletionItem> Items;<br class="">- CompletionItemsCollector Collector(&Items, CCO);<br class="">-<br class="">- std::lock_guard<std::mutex> Guard(ClangObjectLock);<br class="">- auto &DocData = DocDatas[File];<br class="">- auto Unit = DocData.getAST();<br class="">- if (!Unit) {<br class="">- auto newAST = createASTUnitForFile(File, this->Store);<br class="">- Unit = newAST.get();<br class="">- DocData.setAST(std::move(newAST));<br class="">- }<br class="">- if (!Unit)<br class="">- return {};<br class="">- IntrusiveRefCntPtr<SourceManager> SourceMgr(<br class="">- new SourceManager(*DiagEngine, Unit->getFileManager()));<br class="">- // CodeComplete seems to require fresh LangOptions.<br class="">- LangOptions LangOpts = Unit->getLangOpts();<br class="">- // The language server protocol uses zero-based line and column numbers.<br class="">- // The clang code completion uses one-based numbers.<br class="">- Unit->CodeComplete(File, Line + 1, Column + 1, getRemappedFiles(this->Store),<br class="">- CCO.IncludeMacros, CCO.IncludeCodePatterns,<br class="">- CCO.IncludeBriefComments, Collector, PCHs, *DiagEngine,<br class="">- LangOpts, *SourceMgr, Unit->getFileManager(),<br class="">- StoredDiagnostics, OwnedBuffers);<br class="">- for (const llvm::MemoryBuffer *Buffer : OwnedBuffers)<br class="">- delete Buffer;<br class="">- return Items;<br class="">-}<br class=""><br class="">Removed: clang-tools-extra/trunk/clangd/ASTManager.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ASTManager.h?rev=303066&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ASTManager.h?rev=303066&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ASTManager.h (original)<br class="">+++ clang-tools-extra/trunk/clangd/ASTManager.h (removed)<br class="">@@ -1,162 +0,0 @@<br class="">-//===--- ASTManager.h - Clang AST manager -----------------------*- C++ -*-===//<br class="">-//<br class="">-// The LLVM Compiler Infrastructure<br class="">-//<br class="">-// This file is distributed under the University of Illinois Open Source<br class="">-// License. See LICENSE.TXT for details.<br class="">-//<br class="">-//===----------------------------------------------------------------------===//<br class="">-<br class="">-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTMANAGER_H<br class="">-#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTMANAGER_H<br class="">-<br class="">-#include "DocumentStore.h"<br class="">-#include "JSONRPCDispatcher.h"<br class="">-#include "Protocol.h"<br class="">-#include "clang/Tooling/Core/Replacement.h"<br class="">-#include "llvm/ADT/IntrusiveRefCntPtr.h"<br class="">-#include <condition_variable><br class="">-#include <deque><br class="">-#include <thread><br class="">-<br class="">-namespace clang {<br class="">-class ASTUnit;<br class="">-class DiagnosticsEngine;<br class="">-class PCHContainerOperations;<br class="">-namespace tooling {<br class="">-class CompilationDatabase;<br class="">-} // namespace tooling<br class="">-<br class="">-namespace clangd {<br class="">-<br class="">-/// Using 'unsigned' here to avoid undefined behaviour on overflow.<br class="">-typedef unsigned DocVersion;<br class="">-<br class="">-/// Stores ASTUnit and FixIts map for an opened document.<br class="">-class DocData {<br class="">-public:<br class="">- typedef std::map<clangd::Diagnostic, std::vector<clang::tooling::Replacement>><br class="">- DiagnosticToReplacementMap;<br class="">-<br class="">-public:<br class="">- void setAST(std::unique_ptr<ASTUnit> AST);<br class="">- ASTUnit *getAST() const;<br class="">-<br class="">- void cacheFixIts(DiagnosticToReplacementMap FixIts);<br class="">- std::vector<clang::tooling::Replacement><br class="">- getFixIts(const clangd::Diagnostic &D) const;<br class="">-<br class="">-private:<br class="">- std::unique_ptr<ASTUnit> AST;<br class="">- DiagnosticToReplacementMap FixIts;<br class="">-};<br class="">-<br class="">-enum class ASTManagerRequestType { ParseAndPublishDiagnostics, RemoveDocData };<br class="">-<br class="">-/// A request to the worker thread<br class="">-class ASTManagerRequest {<br class="">-public:<br class="">- ASTManagerRequest() = default;<br class="">- ASTManagerRequest(ASTManagerRequestType Type, std::string File,<br class="">- DocVersion Version);<br class="">-<br class="">- ASTManagerRequestType Type;<br class="">- std::string File;<br class="">- DocVersion Version;<br class="">-};<br class="">-<br class="">-class ASTManager : public DocumentStoreListener {<br class="">-public:<br class="">- ASTManager(JSONOutput &Output, DocumentStore &Store, bool RunSynchronously);<br class="">- ~ASTManager() override;<br class="">-<br class="">- void onDocumentAdd(StringRef File) override;<br class="">- void onDocumentRemove(StringRef File) override;<br class="">-<br class="">- /// Get code completions at a specified \p Line and \p Column in \p File.<br class="">- ///<br class="">- /// This function is thread-safe and returns completion items that own the<br class="">- /// data they contain.<br class="">- std::vector<CompletionItem> codeComplete(StringRef File, unsigned Line,<br class="">- unsigned Column);<br class="">-<br class="">- /// Get the fixes associated with a certain diagnostic in a specified file as<br class="">- /// replacements.<br class="">- ///<br class="">- /// This function is thread-safe. It returns a copy to avoid handing out<br class="">- /// references to unguarded data.<br class="">- std::vector<clang::tooling::Replacement><br class="">- getFixIts(StringRef File, const clangd::Diagnostic &D);<br class="">-<br class="">- DocumentStore &getStore() const { return Store; }<br class="">-<br class="">-private:<br class="">- JSONOutput &Output;<br class="">- DocumentStore &Store;<br class="">-<br class="">- // Set to true if requests should block instead of being processed<br class="">- // asynchronously.<br class="">- bool RunSynchronously;<br class="">-<br class="">- /// Loads a compilation database for File. May return nullptr if it fails. The<br class="">- /// database is cached for subsequent accesses.<br class="">- clang::tooling::CompilationDatabase *<br class="">- getOrCreateCompilationDatabaseForFile(StringRef File);<br class="">- // Creates a new ASTUnit for the document at File.<br class="">- // FIXME: This calls chdir internally, which is thread unsafe.<br class="">- std::unique_ptr<clang::ASTUnit><br class="">- createASTUnitForFile(StringRef File, const DocumentStore &Docs);<br class="">-<br class="">- /// If RunSynchronously is false, queues the request to be run on the worker<br class="">- /// thread.<br class="">- /// If RunSynchronously is true, runs the request handler immediately on the<br class="">- /// main thread.<br class="">- void queueOrRun(ASTManagerRequestType RequestType, StringRef File);<br class="">-<br class="">- void runWorker();<br class="">- void handleRequest(ASTManagerRequestType RequestType, StringRef File);<br class="">-<br class="">- /// Parses files and publishes diagnostics.<br class="">- /// This function is called on the worker thread in asynchronous mode and<br class="">- /// on the main thread in synchronous mode.<br class="">- void parseFileAndPublishDiagnostics(StringRef File);<br class="">-<br class="">- /// Caches compilation databases loaded from directories(keys are directories).<br class="">- llvm::StringMap<std::unique_ptr<clang::tooling::CompilationDatabase>><br class="">- CompilationDatabases;<br class="">-<br class="">- /// Clang objects.<br class="">- /// A map from filenames to DocData structures that store ASTUnit and Fixits for<br class="">- /// the files. The ASTUnits are used for generating diagnostics and fix-it-s<br class="">- /// asynchronously by the worker thread and synchronously for code completion.<br class="">- llvm::StringMap<DocData> DocDatas;<br class="">- std::shared_ptr<clang::PCHContainerOperations> PCHs;<br class="">- /// A lock for access to the DocDatas, CompilationDatabases and PCHs.<br class="">- std::mutex ClangObjectLock;<br class="">-<br class="">- /// Stores latest versions of the tracked documents to discard outdated requests.<br class="">- /// Guarded by RequestLock.<br class="">- /// TODO(ibiryukov): the entries are neved deleted from this map.<br class="">- llvm::StringMap<DocVersion> DocVersions;<br class="">-<br class="">- /// A LIFO queue of requests. Note that requests are discarded if the `version`<br class="">- /// field is not equal to the one stored inside DocVersions.<br class="">- /// TODO(krasimir): code completion should always have priority over parsing<br class="">- /// for diagnostics.<br class="">- std::deque<ASTManagerRequest> RequestQueue;<br class="">- /// Setting Done to true will make the worker thread terminate.<br class="">- bool Done = false;<br class="">- /// Condition variable to wake up the worker thread.<br class="">- std::condition_variable ClangRequestCV;<br class="">- /// Lock for accesses to RequestQueue, DocVersions and Done.<br class="">- std::mutex RequestLock;<br class="">-<br class="">- /// We run parsing on a separate thread. This thread looks into RequestQueue to<br class="">- /// find requests to handle and terminates when Done is set to true.<br class="">- std::thread ClangWorker;<br class="">-};<br class="">-<br class="">-} // namespace clangd<br class="">-} // namespace clang<br class="">-<br class="">-#endif<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=303067&r1=303066&r2=303067&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=303067&r1=303066&r2=303067&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/CMakeLists.txt (original)<br class="">+++ clang-tools-extra/trunk/clangd/CMakeLists.txt Mon May 15 09:17:35 2017<br class="">@@ -1,6 +1,11 @@<br class=""> add_clang_executable(clangd<br class="">- ASTManager.cpp<br class="">+ ClangdLSPServer.cpp<br class=""> ClangdMain.cpp<br class="">+ ClangdServer.cpp<br class="">+ ClangdUnit.cpp<br class="">+ ClangdUnitStore.cpp<br class="">+ DraftStore.cpp<br class="">+ GlobalCompilationDatabase.cpp<br class=""> JSONRPCDispatcher.cpp<br class=""> Protocol.cpp<br class=""> ProtocolHandlers.cpp<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (added)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,100 @@<br class="">+//===--- ClangdLSPServer.cpp - LSP server ------------------------*- C++-*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===---------------------------------------------------------------------===//<br class="">+<br class="">+#include "ClangdLSPServer.h"<br class="">+#include "JSONRPCDispatcher.h"<br class="">+<br class="">+using namespace clang::clangd;<br class="">+using namespace clang;<br class="">+<br class="">+class ClangdLSPServer::LSPDiagnosticsConsumer : public DiagnosticsConsumer {<br class="">+public:<br class="">+ LSPDiagnosticsConsumer(ClangdLSPServer &Server) : Server(Server) {}<br class="">+<br class="">+ virtual void onDiagnosticsReady(PathRef File,<br class="">+ std::vector<DiagWithFixIts> Diagnostics) {<br class="">+ Server.consumeDiagnostics(File, Diagnostics);<br class="">+ }<br class="">+<br class="">+private:<br class="">+ ClangdLSPServer &Server;<br class="">+};<br class="">+<br class="">+ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, bool RunSynchronously)<br class="">+ : Out(Out),<br class="">+ Server(llvm::make_unique<DirectoryBasedGlobalCompilationDatabase>(),<br class="">+ llvm::make_unique<LSPDiagnosticsConsumer>(*this),<br class="">+ RunSynchronously) {}<br class="">+<br class="">+void ClangdLSPServer::openDocument(StringRef File, StringRef Contents) {<br class="">+ Server.addDocument(File, Contents);<br class="">+}<br class="">+<br class="">+void ClangdLSPServer::closeDocument(StringRef File) {<br class="">+ Server.removeDocument(File);<br class="">+}<br class="">+<br class="">+std::vector<CompletionItem> ClangdLSPServer::codeComplete(PathRef File,<br class="">+ Position Pos) {<br class="">+ return Server.codeComplete(File, Pos);<br class="">+}<br class="">+<br class="">+std::vector<clang::tooling::Replacement><br class="">+ClangdLSPServer::getFixIts(StringRef File, const clangd::Diagnostic &D) {<br class="">+ std::lock_guard<std::mutex> Lock(FixItsMutex);<br class="">+ auto DiagToFixItsIter = FixItsMap.find(File);<br class="">+ if (DiagToFixItsIter == FixItsMap.end())<br class="">+ return {};<br class="">+<br class="">+ const auto &DiagToFixItsMap = DiagToFixItsIter->second;<br class="">+ auto FixItsIter = DiagToFixItsMap.find(D);<br class="">+ if (FixItsIter == DiagToFixItsMap.end())<br class="">+ return {};<br class="">+<br class="">+ return FixItsIter->second;<br class="">+}<br class="">+<br class="">+std::string ClangdLSPServer::getDocument(PathRef File) {<br class="">+ return Server.getDocument(File);<br class="">+}<br class="">+<br class="">+void ClangdLSPServer::consumeDiagnostics(<br class="">+ PathRef File, std::vector<DiagWithFixIts> Diagnostics) {<br class="">+ std::string DiagnosticsJSON;<br class="">+<br class="">+ DiagnosticToReplacementMap LocalFixIts; // Temporary storage<br class="">+ for (auto &DiagWithFixes : Diagnostics) {<br class="">+ auto Diag = DiagWithFixes.Diag;<br class="">+ DiagnosticsJSON +=<br class="">+ R"({"range":)" + Range::unparse(Diag.range) +<br class="">+ R"(,"severity":)" + std::to_string(Diag.severity) +<br class="">+ R"(,"message":")" + llvm::yaml::escape(Diag.message) +<br class="">+ R"("},)";<br class="">+<br class="">+ // We convert to Replacements to become independent of the SourceManager.<br class="">+ auto &FixItsForDiagnostic = LocalFixIts[Diag];<br class="">+ std::copy(DiagWithFixes.FixIts.begin(), DiagWithFixes.FixIts.end(),<br class="">+ std::back_inserter(FixItsForDiagnostic));<br class="">+ }<br class="">+<br class="">+ // Cache FixIts<br class="">+ {<br class="">+ // FIXME(ibiryukov): should be deleted when documents are removed<br class="">+ std::lock_guard<std::mutex> Lock(FixItsMutex);<br class="">+ FixItsMap[File] = LocalFixIts;<br class="">+ }<br class="">+<br class="">+ // Publish diagnostics.<br class="">+ if (!DiagnosticsJSON.empty())<br class="">+ DiagnosticsJSON.pop_back(); // Drop trailing comma.<br class="">+ Out.writeMessage(<br class="">+ R"({"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":")" +<br class="">+ URI::fromFile(File).uri + R"(","diagnostics":[)" + DiagnosticsJSON +<br class="">+ R"(]}})");<br class="">+}<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/ClangdLSPServer.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.h?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.h?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdLSPServer.h (added)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.h Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,79 @@<br class="">+//===--- ClangdLSPServer.h - LSP server --------------------------*- C++-*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===---------------------------------------------------------------------===//<br class="">+<br class="">+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H<br class="">+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H<br class="">+<br class="">+#include "ClangdServer.h"<br class="">+#include "Path.h"<br class="">+#include "Protocol.h"<br class="">+#include "clang/Tooling/Core/Replacement.h"<br class="">+<br class="">+namespace clang {<br class="">+namespace clangd {<br class="">+<br class="">+class JSONOutput;<br class="">+<br class="">+/// This class serves as an intermediate layer of LSP server implementation,<br class="">+/// glueing the JSON LSP protocol layer and ClangdServer together. It doesn't<br class="">+/// directly handle input from LSP client.<br class="">+/// Most methods are synchronous and return their result directly, but<br class="">+/// diagnostics are provided asynchronously when ready via<br class="">+/// JSONOutput::writeMessage.<br class="">+class ClangdLSPServer {<br class="">+public:<br class="">+ ClangdLSPServer(JSONOutput &Out, bool RunSynchronously);<br class="">+<br class="">+ /// Update the document text for \p File with \p Contents, schedule update of<br class="">+ /// diagnostics. Out.writeMessage will called to push diagnostics to LSP<br class="">+ /// client asynchronously when they are ready.<br class="">+ void openDocument(PathRef File, StringRef Contents);<br class="">+ /// Stop tracking the document for \p File.<br class="">+ void closeDocument(PathRef File);<br class="">+<br class="">+ /// Run code completion synchronously.<br class="">+ std::vector<CompletionItem> codeComplete(PathRef File, Position Pos);<br class="">+<br class="">+ /// Get the fixes associated with a certain diagnostic in a specified file as<br class="">+ /// replacements.<br class="">+ ///<br class="">+ /// This function is thread-safe. It returns a copy to avoid handing out<br class="">+ /// references to unguarded data.<br class="">+ std::vector<clang::tooling::Replacement><br class="">+ getFixIts(StringRef File, const clangd::Diagnostic &D);<br class="">+<br class="">+ /// Get the current document contents stored for \p File.<br class="">+ /// FIXME(ibiryukov): This function is here to allow implementation of<br class="">+ /// formatCode from ProtocolHandlers.cpp. We should move formatCode to<br class="">+ /// ClangdServer class and remove this function from public interface.<br class="">+ std::string getDocument(PathRef File);<br class="">+<br class="">+private:<br class="">+ class LSPDiagnosticsConsumer;<br class="">+<br class="">+ /// Function that will be called on a separate thread when diagnostics are<br class="">+ /// ready. Sends the Dianostics to LSP client via Out.writeMessage and caches<br class="">+ /// corresponding fixits in the FixItsMap.<br class="">+ void consumeDiagnostics(PathRef File,<br class="">+ std::vector<DiagWithFixIts> Diagnostics);<br class="">+<br class="">+ JSONOutput &Out;<br class="">+ ClangdServer Server;<br class="">+<br class="">+ std::mutex FixItsMutex;<br class="">+ typedef std::map<clangd::Diagnostic, std::vector<clang::tooling::Replacement>><br class="">+ DiagnosticToReplacementMap;<br class="">+ /// Caches FixIts per file and diagnostics<br class="">+ llvm::StringMap<DiagnosticToReplacementMap> FixItsMap;<br class="">+};<br class="">+<br class="">+} // namespace clangd<br class="">+} // namespace clang<br class="">+<br class="">+#endif<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/ClangdMain.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdMain.cpp?rev=303067&r1=303066&r2=303067&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdMain.cpp?rev=303067&r1=303066&r2=303067&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdMain.cpp (original)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdMain.cpp Mon May 15 09:17:35 2017<br class="">@@ -7,15 +7,19 @@<br class=""> //<br class=""> //===----------------------------------------------------------------------===//<br class=""><br class="">-#include "ASTManager.h"<br class="">-#include "DocumentStore.h"<br class=""> #include "JSONRPCDispatcher.h"<br class="">+#include "ClangdLSPServer.h"<br class="">+#include "Protocol.h"<br class=""> #include "ProtocolHandlers.h"<br class=""> #include "llvm/Support/CommandLine.h"<br class=""> #include "llvm/Support/FileSystem.h"<br class=""> #include "llvm/Support/Program.h"<br class="">+<br class=""> #include <iostream><br class="">+#include <memory><br class=""> #include <string><br class="">+<br class="">+using namespace clang;<br class=""> using namespace clang::clangd;<br class=""><br class=""> static llvm::cl::opt<bool><br class="">@@ -34,9 +38,7 @@ int main(int argc, char *argv[]) {<br class=""><br class=""> // Set up a document store and intialize all the method handlers for JSONRPC<br class=""> // dispatching.<br class="">- DocumentStore Store;<br class="">- ASTManager AST(Out, Store, RunSynchronously);<br class="">- Store.addListener(&AST);<br class="">+ ClangdLSPServer LSPServer(Out, RunSynchronously);<br class=""> JSONRPCDispatcher Dispatcher(llvm::make_unique<Handler>(Out));<br class=""> Dispatcher.registerHandler("initialize",<br class=""> llvm::make_unique<InitializeHandler>(Out));<br class="">@@ -45,26 +47,26 @@ int main(int argc, char *argv[]) {<br class=""> Dispatcher.registerHandler("shutdown", std::move(ShutdownPtr));<br class=""> Dispatcher.registerHandler(<br class=""> "textDocument/didOpen",<br class="">- llvm::make_unique<TextDocumentDidOpenHandler>(Out, Store));<br class="">+ llvm::make_unique<TextDocumentDidOpenHandler>(Out, LSPServer));<br class=""> Dispatcher.registerHandler(<br class=""> "textDocument/didClose",<br class="">- llvm::make_unique<TextDocumentDidCloseHandler>(Out, Store));<br class="">+ llvm::make_unique<TextDocumentDidCloseHandler>(Out, LSPServer));<br class=""> Dispatcher.registerHandler(<br class=""> "textDocument/didChange",<br class="">- llvm::make_unique<TextDocumentDidChangeHandler>(Out, Store));<br class="">+ llvm::make_unique<TextDocumentDidChangeHandler>(Out, LSPServer));<br class=""> Dispatcher.registerHandler(<br class=""> "textDocument/rangeFormatting",<br class="">- llvm::make_unique<TextDocumentRangeFormattingHandler>(Out, Store));<br class="">+ llvm::make_unique<TextDocumentRangeFormattingHandler>(Out, LSPServer));<br class=""> Dispatcher.registerHandler(<br class=""> "textDocument/onTypeFormatting",<br class="">- llvm::make_unique<TextDocumentOnTypeFormattingHandler>(Out, Store));<br class="">+ llvm::make_unique<TextDocumentOnTypeFormattingHandler>(Out, LSPServer));<br class=""> Dispatcher.registerHandler(<br class=""> "textDocument/formatting",<br class="">- llvm::make_unique<TextDocumentFormattingHandler>(Out, Store));<br class="">+ llvm::make_unique<TextDocumentFormattingHandler>(Out, LSPServer));<br class=""> Dispatcher.registerHandler("textDocument/codeAction",<br class="">- llvm::make_unique<CodeActionHandler>(Out, AST));<br class="">+ llvm::make_unique<CodeActionHandler>(Out, LSPServer));<br class=""> Dispatcher.registerHandler("textDocument/completion",<br class="">- llvm::make_unique<CompletionHandler>(Out, AST));<br class="">+ llvm::make_unique<CompletionHandler>(Out, LSPServer));<br class=""><br class=""> while (std::cin.good()) {<br class=""> // A Language Server Protocol message starts with a HTTP header, delimited<br class=""><br class="">Copied: clang-tools-extra/trunk/clangd/ClangdServer.cpp (from r303060, clang-tools-extra/trunk/clangd/ASTManager.cpp)<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?p2=clang-tools-extra/trunk/clangd/ClangdServer.cpp&p1=clang-tools-extra/trunk/clangd/ASTManager.cpp&r1=303060&r2=303067&rev=303067&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?p2=clang-tools-extra/trunk/clangd/ClangdServer.cpp&p1=clang-tools-extra/trunk/clangd/ASTManager.cpp&r1=303060&r2=303067&rev=303067&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ASTManager.cpp (original)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Mon May 15 09:17:35 2017<br class="">@@ -1,440 +1,149 @@<br class="">-//===--- ASTManager.cpp - Clang AST manager -------------------------------===//<br class="">+//===--- ClangdServer.cpp - Main clangd server code --------------*- C++-*-===//<br class=""> //<br class=""> // The LLVM Compiler Infrastructure<br class=""> //<br class=""> // This file is distributed under the University of Illinois Open Source<br class=""> // License. See LICENSE.TXT for details.<br class=""> //<br class="">-//===----------------------------------------------------------------------===//<br class="">+//===-------------------------------------------------------------------===//<br class=""><br class="">-#include "ASTManager.h"<br class="">-#include "JSONRPCDispatcher.h"<br class="">-#include "Protocol.h"<br class="">+#include "ClangdServer.h"<br class=""> #include "clang/Frontend/ASTUnit.h"<br class=""> #include "clang/Frontend/CompilerInstance.h"<br class="">+#include "clang/Frontend/CompilerInvocation.h"<br class=""> #include "clang/Tooling/CompilationDatabase.h"<br class="">-#include "llvm/Support/Format.h"<br class="">-#include "llvm/Support/Path.h"<br class="">-#include <mutex><br class="">-#include <thread><br class="">-using namespace clang;<br class="">-using namespace clangd;<br class="">+#include "llvm/Support/FileSystem.h"<br class=""><br class="">-void DocData::setAST(std::unique_ptr<ASTUnit> AST) {<br class="">- this->AST = std::move(AST);<br class="">-}<br class="">-<br class="">-ASTUnit *DocData::getAST() const { return AST.get(); }<br class="">-<br class="">-void DocData::cacheFixIts(DiagnosticToReplacementMap FixIts) {<br class="">- this->FixIts = std::move(FixIts);<br class="">-}<br class="">+using namespace clang::clangd;<br class=""><br class="">-std::vector<clang::tooling::Replacement><br class="">-DocData::getFixIts(const clangd::Diagnostic &D) const {<br class="">- auto it = FixIts.find(D);<br class="">- if (it != FixIts.end())<br class="">- return it->second;<br class="">- return {};<br class="">-}<br class="">-<br class="">-ASTManagerRequest::ASTManagerRequest(ASTManagerRequestType Type,<br class="">- std::string File,<br class="">- DocVersion Version)<br class="">- : Type(Type), File(File), Version(Version) {}<br class="">-<br class="">-/// Retrieve a copy of the contents of every file in the store, for feeding into<br class="">-/// ASTUnit.<br class="">-static std::vector<ASTUnit::RemappedFile><br class="">-getRemappedFiles(const DocumentStore &Docs) {<br class="">- // FIXME: Use VFS instead. This would allow us to get rid of the chdir below.<br class="">- std::vector<ASTUnit::RemappedFile> RemappedFiles;<br class="">- for (const auto &P : Docs.getAllDocuments()) {<br class="">- StringRef FileName = P.first;<br class="">- RemappedFiles.push_back(ASTUnit::RemappedFile(<br class="">- FileName,<br class="">- llvm::MemoryBuffer::getMemBufferCopy(P.second, FileName).release()));<br class="">- }<br class="">- return RemappedFiles;<br class="">-}<br class="">+WorkerRequest::WorkerRequest(WorkerRequestKind Kind, Path File,<br class="">+ DocVersion Version)<br class="">+ : Kind(Kind), File(File), Version(Version) {}<br class=""><br class="">-/// Convert from clang diagnostic level to LSP severity.<br class="">-static int getSeverity(DiagnosticsEngine::Level L) {<br class="">- switch (L) {<br class="">- case DiagnosticsEngine::Remark:<br class="">- return 4;<br class="">- case DiagnosticsEngine::Note:<br class="">- return 3;<br class="">- case DiagnosticsEngine::Warning:<br class="">- return 2;<br class="">- case DiagnosticsEngine::Fatal:<br class="">- case DiagnosticsEngine::Error:<br class="">- return 1;<br class="">- case DiagnosticsEngine::Ignored:<br class="">- return 0;<br class="">- }<br class="">- llvm_unreachable("Unknown diagnostic level!");<br class="">-}<br class="">-<br class="">-static CompletionItemKind getKind(CXCursorKind K) {<br class="">- switch (K) {<br class="">- case CXCursor_MacroInstantiation:<br class="">- case CXCursor_MacroDefinition:<br class="">- return CompletionItemKind::Text;<br class="">- case CXCursor_CXXMethod:<br class="">- return CompletionItemKind::Method;<br class="">- case CXCursor_FunctionDecl:<br class="">- case CXCursor_FunctionTemplate:<br class="">- return CompletionItemKind::Function;<br class="">- case CXCursor_Constructor:<br class="">- case CXCursor_Destructor:<br class="">- return CompletionItemKind::Constructor;<br class="">- case CXCursor_FieldDecl:<br class="">- return CompletionItemKind::Field;<br class="">- case CXCursor_VarDecl:<br class="">- case CXCursor_ParmDecl:<br class="">- return CompletionItemKind::Variable;<br class="">- case CXCursor_ClassDecl:<br class="">- case CXCursor_StructDecl:<br class="">- case CXCursor_UnionDecl:<br class="">- case CXCursor_ClassTemplate:<br class="">- case CXCursor_ClassTemplatePartialSpecialization:<br class="">- return CompletionItemKind::Class;<br class="">- case CXCursor_Namespace:<br class="">- case CXCursor_NamespaceAlias:<br class="">- case CXCursor_NamespaceRef:<br class="">- return CompletionItemKind::Module;<br class="">- case CXCursor_EnumConstantDecl:<br class="">- return CompletionItemKind::Value;<br class="">- case CXCursor_EnumDecl:<br class="">- return CompletionItemKind::Enum;<br class="">- case CXCursor_TypeAliasDecl:<br class="">- case CXCursor_TypeAliasTemplateDecl:<br class="">- case CXCursor_TypedefDecl:<br class="">- case CXCursor_MemberRef:<br class="">- case CXCursor_TypeRef:<br class="">- return CompletionItemKind::Reference;<br class="">- default:<br class="">- return CompletionItemKind::Missing;<br class="">- }<br class="">-}<br class="">-<br class="">-ASTManager::ASTManager(JSONOutput &Output, DocumentStore &Store,<br class="">- bool RunSynchronously)<br class="">- : Output(Output), Store(Store), RunSynchronously(RunSynchronously),<br class="">- PCHs(std::make_shared<PCHContainerOperations>()),<br class="">- ClangWorker([this]() { runWorker(); }) {}<br class="">-<br class="">-void ASTManager::runWorker() {<br class="">- while (true) {<br class="">- ASTManagerRequest Request;<br class="">-<br class="">- // Pick request from the queue<br class="">- {<br class="">- std::unique_lock<std::mutex> Lock(RequestLock);<br class="">- // Wait for more requests.<br class="">- ClangRequestCV.wait(Lock,<br class="">- [this] { return !RequestQueue.empty() || Done; });<br class="">- if (Done)<br class="">- return;<br class="">- assert(!RequestQueue.empty() && "RequestQueue was empty");<br class="">-<br class="">- Request = std::move(RequestQueue.back());<br class="">- RequestQueue.pop_back();<br class="">-<br class="">- // Skip outdated requests<br class="">- if (Request.Version != DocVersions.find(Request.File)->second) {<br class="">- Output.log("Version for " + Twine(Request.File) +<br class="">- " in request is outdated, skipping request\n");<br class="">- continue;<br class="">- }<br class="">- } // unlock RequestLock<br class="">-<br class="">- handleRequest(Request.Type, Request.File);<br class="">- }<br class="">-}<br class="">-<br class="">-void ASTManager::queueOrRun(ASTManagerRequestType RequestType, StringRef File) {<br class="">+ClangdScheduler::ClangdScheduler(ClangdServer &Server, bool RunSynchronously)<br class="">+ : RunSynchronously(RunSynchronously) {<br class=""> if (RunSynchronously) {<br class="">- handleRequest(RequestType, File);<br class="">+ // Don't start the worker thread if we're running synchronously<br class=""> return;<br class=""> }<br class=""><br class="">- std::lock_guard<std::mutex> Guard(RequestLock);<br class="">- // We increment the version of the added document immediately and schedule<br class="">- // the requested operation to be run on a worker thread<br class="">- DocVersion version = ++DocVersions[File];<br class="">- RequestQueue.push_back(ASTManagerRequest(RequestType, File, version));<br class="">- ClangRequestCV.notify_one();<br class="">-}<br class="">-<br class="">-void ASTManager::handleRequest(ASTManagerRequestType RequestType,<br class="">- StringRef File) {<br class="">- switch (RequestType) {<br class="">- case ASTManagerRequestType::ParseAndPublishDiagnostics:<br class="">- parseFileAndPublishDiagnostics(File);<br class="">- break;<br class="">- case ASTManagerRequestType::RemoveDocData: {<br class="">- std::lock_guard<std::mutex> Lock(ClangObjectLock);<br class="">- auto DocDataIt = DocDatas.find(File);<br class="">- // We could get the remove request before parsing for the document is<br class="">- // started, just do nothing in that case, parsing request will be discarded<br class="">- // because it has a lower version value<br class="">- if (DocDataIt == DocDatas.end())<br class="">- return;<br class="">- DocDatas.erase(DocDataIt);<br class="">- break;<br class="">- } // unlock ClangObjectLock<br class="">- }<br class="">-}<br class="">-<br class="">-void ASTManager::parseFileAndPublishDiagnostics(StringRef File) {<br class="">- std::unique_lock<std::mutex> ClangObjectLockGuard(ClangObjectLock);<br class="">-<br class="">- auto &DocData = DocDatas[File];<br class="">- ASTUnit *Unit = DocData.getAST();<br class="">- if (!Unit) {<br class="">- auto newAST = createASTUnitForFile(File, this->Store);<br class="">- Unit = newAST.get();<br class="">-<br class="">- DocData.setAST(std::move(newAST));<br class="">- } else {<br class="">- // Do a reparse if this wasn't the first parse.<br class="">- // FIXME: This might have the wrong working directory if it changed in the<br class="">- // meantime.<br class="">- Unit->Reparse(PCHs, getRemappedFiles(this->Store));<br class="">- }<br class="">+ // Initialize Worker in ctor body, rather than init list to avoid potentially<br class="">+ // using not-yet-initialized members<br class="">+ Worker = std::thread([&Server, this]() {<br class="">+ while (true) {<br class="">+ WorkerRequest Request;<br class="">+<br class="">+ // Pick request from the queue<br class="">+ {<br class="">+ std::unique_lock<std::mutex> Lock(Mutex);<br class="">+ // Wait for more requests.<br class="">+ RequestCV.wait(Lock, [this] { return !RequestQueue.empty() || Done; });<br class="">+ if (Done)<br class="">+ return;<br class="">+<br class="">+ assert(!RequestQueue.empty() && "RequestQueue was empty");<br class="">+<br class="">+ Request = std::move(RequestQueue.back());<br class="">+ RequestQueue.pop_back();<br class="">+<br class="">+ // Skip outdated requests<br class="">+ if (Request.Version != Server.DraftMgr.getVersion(Request.File)) {<br class="">+ // FIXME(ibiryukov): Logging<br class="">+ // Output.log("Version for " + Twine(Request.File) +<br class="">+ // " in request is outdated, skipping request\n");<br class="">+ continue;<br class="">+ }<br class="">+ } // unlock Mutex<br class=""><br class="">- if (!Unit)<br class="">- return;<br class="">-<br class="">- // Send the diagnotics to the editor.<br class="">- // FIXME: If the diagnostic comes from a different file, do we want to<br class="">- // show them all? Right now we drop everything not coming from the<br class="">- // main file.<br class="">- std::string Diagnostics;<br class="">- DocData::DiagnosticToReplacementMap LocalFixIts; // Temporary storage<br class="">- for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),<br class="">- DEnd = Unit->stored_diag_end();<br class="">- D != DEnd; ++D) {<br class="">- if (!D->getLocation().isValid() ||<br class="">- !D->getLocation().getManager().isInMainFile(D->getLocation()))<br class="">- continue;<br class="">- Position P;<br class="">- P.line = D->getLocation().getSpellingLineNumber() - 1;<br class="">- P.character = D->getLocation().getSpellingColumnNumber();<br class="">- Range R = {P, P};<br class="">- Diagnostics +=<br class="">- R"({"range":)" + Range::unparse(R) +<br class="">- R"(,"severity":)" + std::to_string(getSeverity(D->getLevel())) +<br class="">- R"(,"message":")" + llvm::yaml::escape(D->getMessage()) +<br class="">- R"("},)";<br class="">-<br class="">- // We convert to Replacements to become independent of the SourceManager.<br class="">- clangd::Diagnostic Diag = {R, getSeverity(D->getLevel()), D->getMessage()};<br class="">- auto &FixItsForDiagnostic = LocalFixIts[Diag];<br class="">- for (const FixItHint &Fix : D->getFixIts()) {<br class="">- FixItsForDiagnostic.push_back(clang::tooling::Replacement(<br class="">- Unit->getSourceManager(), Fix.RemoveRange, Fix.CodeToInsert));<br class="">+ Server.handleRequest(std::move(Request));<br class=""> }<br class="">- }<br class="">-<br class="">- // Put FixIts into place.<br class="">- DocData.cacheFixIts(std::move(LocalFixIts));<br class="">-<br class="">- ClangObjectLockGuard.unlock();<br class="">- // No accesses to clang objects are allowed after this point.<br class="">-<br class="">- // Publish diagnostics.<br class="">- if (!Diagnostics.empty())<br class="">- Diagnostics.pop_back(); // Drop trailing comma.<br class="">- Output.writeMessage(<br class="">- R"({"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":")" +<br class="">- URI::fromFile(File).uri + R"(","diagnostics":[)" + Diagnostics + R"(]}})");<br class="">+ });<br class=""> }<br class=""><br class="">-ASTManager::~ASTManager() {<br class="">+ClangdScheduler::~ClangdScheduler() {<br class="">+ if (RunSynchronously)<br class="">+ return; // no worker thread is running in that case<br class="">+<br class=""> {<br class="">- std::lock_guard<std::mutex> Guard(RequestLock);<br class="">- // Wake up the clang worker thread, then exit.<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+ // Wake up the worker thread<br class=""> Done = true;<br class="">- ClangRequestCV.notify_one();<br class="">- } // unlock DocDataLock<br class="">- ClangWorker.join();<br class="">-}<br class="">-<br class="">-void ASTManager::onDocumentAdd(StringRef File) {<br class="">- queueOrRun(ASTManagerRequestType::ParseAndPublishDiagnostics, File);<br class="">-}<br class="">-<br class="">-void ASTManager::onDocumentRemove(StringRef File) {<br class="">- queueOrRun(ASTManagerRequestType::RemoveDocData, File);<br class="">-}<br class="">-<br class="">-tooling::CompilationDatabase *<br class="">-ASTManager::getOrCreateCompilationDatabaseForFile(StringRef File) {<br class="">- namespace path = llvm::sys::path;<br class="">-<br class="">- assert((path::is_absolute(File, path::Style::posix) ||<br class="">- path::is_absolute(File, path::Style::windows)) &&<br class="">- "path must be absolute");<br class="">-<br class="">- for (auto Path = path::parent_path(File); !Path.empty();<br class="">- Path = path::parent_path(Path)) {<br class="">-<br class="">- auto CachedIt = CompilationDatabases.find(Path);<br class="">- if (CachedIt != CompilationDatabases.end())<br class="">- return CachedIt->second.get();<br class="">- std::string Error;<br class="">- auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error);<br class="">- if (!CDB) {<br class="">- if (!Error.empty()) {<br class="">- Output.log("Error when trying to load compilation database from " +<br class="">- Twine(Path) + ": " + Twine(Error) + "\n");<br class="">- }<br class="">- continue;<br class="">- }<br class="">-<br class="">- // TODO(ibiryukov): Invalidate cached compilation databases on changes<br class="">- auto result = CDB.get();<br class="">- CompilationDatabases.insert(std::make_pair(Path, std::move(CDB)));<br class="">- return result;<br class="">- }<br class="">-<br class="">- Output.log("Failed to find compilation database for " + Twine(File) + "\n");<br class="">- return nullptr;<br class="">+ RequestCV.notify_one();<br class="">+ } // unlock Mutex<br class="">+ Worker.join();<br class=""> }<br class=""><br class="">-std::unique_ptr<clang::ASTUnit><br class="">-ASTManager::createASTUnitForFile(StringRef File, const DocumentStore &Docs) {<br class="">- tooling::CompilationDatabase *CDB =<br class="">- getOrCreateCompilationDatabaseForFile(File);<br class="">-<br class="">- std::vector<tooling::CompileCommand> Commands;<br class="">-<br class="">- if (CDB) {<br class="">- Commands = CDB->getCompileCommands(File);<br class="">- // chdir. This is thread hostile.<br class="">- if (!Commands.empty())<br class="">- llvm::sys::fs::set_current_path(Commands.front().Directory);<br class="">- }<br class="">- if (Commands.empty()) {<br class="">- // Add a fake command line if we know nothing.<br class="">- Commands.push_back(tooling::CompileCommand(<br class="">- llvm::sys::path::parent_path(File), llvm::sys::path::filename(File),<br class="">- {"clang", "-fsyntax-only", File.str()}, ""));<br class="">+void ClangdScheduler::enqueue(ClangdServer &Server, WorkerRequest Request) {<br class="">+ if (RunSynchronously) {<br class="">+ Server.handleRequest(Request);<br class="">+ return;<br class=""> }<br class=""><br class="">- // Inject the resource dir.<br class="">- // FIXME: Don't overwrite it if it's already there.<br class="">- static int Dummy; // Just an address in this process.<br class="">- std::string ResourceDir =<br class="">- CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);<br class="">- Commands.front().CommandLine.push_back("-resource-dir=" + ResourceDir);<br class="">-<br class="">- IntrusiveRefCntPtr<DiagnosticsEngine> Diags =<br class="">- CompilerInstance::createDiagnostics(new DiagnosticOptions);<br class="">-<br class="">- std::vector<const char *> ArgStrs;<br class="">- for (const auto &S : Commands.front().CommandLine)<br class="">- ArgStrs.push_back(S.c_str());<br class="">-<br class="">- auto ArgP = &*ArgStrs.begin();<br class="">- return std::unique_ptr<clang::ASTUnit>(ASTUnit::LoadFromCommandLine(<br class="">- ArgP, ArgP + ArgStrs.size(), PCHs, Diags, ResourceDir,<br class="">- /*OnlyLocalDecls=*/false, /*CaptureDiagnostics=*/true,<br class="">- getRemappedFiles(Docs),<br class="">- /*RemappedFilesKeepOriginalName=*/true,<br class="">- /*PrecompilePreambleAfterNParses=*/1, /*TUKind=*/TU_Complete,<br class="">- /*CacheCodeCompletionResults=*/true,<br class="">- /*IncludeBriefCommentsInCodeCompletion=*/true,<br class="">- /*AllowPCHWithCompilerErrors=*/true));<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+ RequestQueue.push_back(Request);<br class="">+ RequestCV.notify_one();<br class=""> }<br class=""><br class="">-std::vector<clang::tooling::Replacement><br class="">-ASTManager::getFixIts(StringRef File, const clangd::Diagnostic &D) {<br class="">- // TODO(ibiryukov): the FixIts should be available immediately<br class="">- // even when parsing is being run on a worker thread<br class="">- std::lock_guard<std::mutex> Guard(ClangObjectLock);<br class="">- return DocDatas[File].getFixIts(D);<br class="">-}<br class="">+ClangdServer::ClangdServer(std::unique_ptr<GlobalCompilationDatabase> CDB,<br class="">+ std::unique_ptr<DiagnosticsConsumer> DiagConsumer,<br class="">+ bool RunSynchronously)<br class="">+ : CDB(std::move(CDB)), DiagConsumer(std::move(DiagConsumer)),<br class="">+ PCHs(std::make_shared<PCHContainerOperations>()),<br class="">+ WorkScheduler(*this, RunSynchronously) {}<br class=""><br class="">-namespace {<br class="">-class CompletionItemsCollector : public CodeCompleteConsumer {<br class="">- std::vector<CompletionItem> *Items;<br class="">- std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;<br class="">- CodeCompletionTUInfo CCTUInfo;<br class="">-<br class="">-public:<br class="">- CompletionItemsCollector(std::vector<CompletionItem> *Items,<br class="">- const CodeCompleteOptions &CodeCompleteOpts)<br class="">- : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),<br class="">- Items(Items),<br class="">- Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),<br class="">- CCTUInfo(Allocator) {}<br class="">-<br class="">- void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,<br class="">- CodeCompletionResult *Results,<br class="">- unsigned NumResults) override {<br class="">- for (unsigned I = 0; I != NumResults; ++I) {<br class="">- CodeCompletionResult &Result = Results[I];<br class="">- CodeCompletionString *CCS = Result.CreateCodeCompletionString(<br class="">- S, Context, *Allocator, CCTUInfo,<br class="">- CodeCompleteOpts.IncludeBriefComments);<br class="">- if (CCS) {<br class="">- CompletionItem Item;<br class="">- assert(CCS->getTypedText());<br class="">- Item.label = CCS->getTypedText();<br class="">- Item.kind = getKind(Result.CursorKind);<br class="">- if (CCS->getBriefComment())<br class="">- Item.documentation = CCS->getBriefComment();<br class="">- Items->push_back(std::move(Item));<br class="">- }<br class="">- }<br class="">+void ClangdServer::addDocument(PathRef File, StringRef Contents) {<br class="">+ DocVersion NewVersion = DraftMgr.updateDraft(File, Contents);<br class="">+ WorkScheduler.enqueue(<br class="">+ *this, WorkerRequest(WorkerRequestKind::ParseAndPublishDiagnostics, File,<br class="">+ NewVersion));<br class="">+}<br class="">+<br class="">+void ClangdServer::removeDocument(PathRef File) {<br class="">+ auto NewVersion = DraftMgr.removeDraft(File);<br class="">+ WorkScheduler.enqueue(<br class="">+ *this, WorkerRequest(WorkerRequestKind::RemoveDocData, File, NewVersion));<br class="">+}<br class="">+<br class="">+std::vector<CompletionItem> ClangdServer::codeComplete(PathRef File,<br class="">+ Position Pos) {<br class="">+ auto FileContents = DraftMgr.getDraft(File);<br class="">+ assert(FileContents.Draft && "codeComplete is called for non-added document");<br class="">+<br class="">+ std::vector<CompletionItem> Result;<br class="">+ Units.runOnUnitWithoutReparse(<br class="">+ File, *FileContents.Draft, *CDB, PCHs, [&](ClangdUnit &Unit) {<br class="">+ Result = Unit.codeComplete(*FileContents.Draft, Pos);<br class="">+ });<br class="">+ return Result;<br class="">+}<br class="">+<br class="">+std::string ClangdServer::getDocument(PathRef File) {<br class="">+ auto draft = DraftMgr.getDraft(File);<br class="">+ assert(draft.Draft && "File is not tracked, cannot get contents");<br class="">+ return *draft.Draft;<br class="">+}<br class="">+<br class="">+void ClangdServer::handleRequest(WorkerRequest Request) {<br class="">+ switch (Request.Kind) {<br class="">+ case WorkerRequestKind::ParseAndPublishDiagnostics: {<br class="">+ auto FileContents = DraftMgr.getDraft(Request.File);<br class="">+ if (FileContents.Version != Request.Version)<br class="">+ return; // This request is outdated, do nothing<br class="">+<br class="">+ assert(FileContents.Draft &&<br class="">+ "No contents inside a file that was scheduled for reparse");<br class="">+ Units.runOnUnit(Request.File, *FileContents.Draft, *CDB, PCHs,<br class="">+ [&](ClangdUnit const &Unit) {<br class="">+ DiagConsumer->onDiagnosticsReady(<br class="">+ Request.File, Unit.getLocalDiagnostics());<br class="">+ });<br class="">+ break;<br class=""> }<br class="">+ case WorkerRequestKind::RemoveDocData:<br class="">+ if (Request.Version != DraftMgr.getVersion(Request.File))<br class="">+ return; // This request is outdated, do nothing<br class=""><br class="">- GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }<br class="">-<br class="">- CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }<br class="">-};<br class="">-<br class="">-} // namespace<br class="">-<br class="">-std::vector<CompletionItem><br class="">-ASTManager::codeComplete(StringRef File, unsigned Line, unsigned Column) {<br class="">- CodeCompleteOptions CCO;<br class="">- CCO.IncludeBriefComments = 1;<br class="">- // This is where code completion stores dirty buffers. Need to free after<br class="">- // completion.<br class="">- SmallVector<const llvm::MemoryBuffer *, 4> OwnedBuffers;<br class="">- SmallVector<StoredDiagnostic, 4> StoredDiagnostics;<br class="">- IntrusiveRefCntPtr<DiagnosticsEngine> DiagEngine(<br class="">- new DiagnosticsEngine(new DiagnosticIDs, new DiagnosticOptions));<br class="">- std::vector<CompletionItem> Items;<br class="">- CompletionItemsCollector Collector(&Items, CCO);<br class="">-<br class="">- std::lock_guard<std::mutex> Guard(ClangObjectLock);<br class="">- auto &DocData = DocDatas[File];<br class="">- auto Unit = DocData.getAST();<br class="">- if (!Unit) {<br class="">- auto newAST = createASTUnitForFile(File, this->Store);<br class="">- Unit = newAST.get();<br class="">- DocData.setAST(std::move(newAST));<br class="">+ Units.removeUnitIfPresent(Request.File);<br class="">+ break;<br class=""> }<br class="">- if (!Unit)<br class="">- return {};<br class="">- IntrusiveRefCntPtr<SourceManager> SourceMgr(<br class="">- new SourceManager(*DiagEngine, Unit->getFileManager()));<br class="">- // CodeComplete seems to require fresh LangOptions.<br class="">- LangOptions LangOpts = Unit->getLangOpts();<br class="">- // The language server protocol uses zero-based line and column numbers.<br class="">- // The clang code completion uses one-based numbers.<br class="">- Unit->CodeComplete(File, Line + 1, Column + 1, getRemappedFiles(this->Store),<br class="">- CCO.IncludeMacros, CCO.IncludeCodePatterns,<br class="">- CCO.IncludeBriefComments, Collector, PCHs, *DiagEngine,<br class="">- LangOpts, *SourceMgr, Unit->getFileManager(),<br class="">- StoredDiagnostics, OwnedBuffers);<br class="">- for (const llvm::MemoryBuffer *Buffer : OwnedBuffers)<br class="">- delete Buffer;<br class="">- return Items;<br class=""> }<br class=""><br class="">Copied: clang-tools-extra/trunk/clangd/ClangdServer.h (from r303063, clang-tools-extra/trunk/clangd/ASTManager.h)<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?p2=clang-tools-extra/trunk/clangd/ClangdServer.h&p1=clang-tools-extra/trunk/clangd/ASTManager.h&r1=303063&r2=303067&rev=303067&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?p2=clang-tools-extra/trunk/clangd/ClangdServer.h&p1=clang-tools-extra/trunk/clangd/ASTManager.h&r1=303063&r2=303067&rev=303067&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ASTManager.h (original)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdServer.h Mon May 15 09:17:35 2017<br class="">@@ -1,4 +1,4 @@<br class="">-//===--- ASTManager.h - Clang AST manager -----------------------*- C++ -*-===//<br class="">+//===--- ClangdServer.h - Main clangd server code ----------------*- C++-*-===//<br class=""> //<br class=""> // The LLVM Compiler Infrastructure<br class=""> //<br class="">@@ -7,153 +7,129 @@<br class=""> //<br class=""> //===----------------------------------------------------------------------===//<br class=""><br class="">-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTMANAGER_H<br class="">-#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTMANAGER_H<br class="">+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H<br class="">+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H<br class=""><br class="">-#include "DocumentStore.h"<br class="">-#include "JSONRPCDispatcher.h"<br class="">-#include "Protocol.h"<br class="">+#include "ClangdUnitStore.h"<br class="">+#include "DraftStore.h"<br class="">+#include "GlobalCompilationDatabase.h"<br class="">+#include "clang/Frontend/ASTUnit.h"<br class="">+#include "clang/Tooling/CompilationDatabase.h"<br class=""> #include "clang/Tooling/Core/Replacement.h"<br class=""> #include "llvm/ADT/IntrusiveRefCntPtr.h"<br class="">+#include "llvm/ADT/Optional.h"<br class="">+#include "llvm/ADT/StringRef.h"<br class="">+<br class="">+#include "ClangdUnit.h"<br class="">+#include "Protocol.h"<br class="">+<br class=""> #include <condition_variable><br class="">-#include <deque><br class="">+#include <mutex><br class="">+#include <string><br class=""> #include <thread><br class="">+#include <utility><br class=""><br class=""> namespace clang {<br class="">-class ASTUnit;<br class="">-class DiagnosticsEngine;<br class=""> class PCHContainerOperations;<br class="">-namespace tooling {<br class="">-class CompilationDatabase;<br class="">-} // namespace tooling<br class=""><br class=""> namespace clangd {<br class=""><br class="">-/// Using 'unsigned' here to avoid undefined behaviour on overflow.<br class="">-typedef unsigned DocVersion;<br class="">-<br class="">-/// Stores ASTUnit and FixIts map for an opened document.<br class="">-class DocData {<br class="">-public:<br class="">- typedef std::map<clangd::Diagnostic, std::vector<clang::tooling::Replacement>><br class="">- DiagnosticToReplacementMap;<br class="">-<br class="">+class DiagnosticsConsumer {<br class=""> public:<br class="">- void setAST(std::unique_ptr<ASTUnit> AST);<br class="">- ASTUnit *getAST() const;<br class="">-<br class="">- void cacheFixIts(DiagnosticToReplacementMap FixIts);<br class="">- std::vector<clang::tooling::Replacement><br class="">- getFixIts(const clangd::Diagnostic &D) const;<br class="">+ virtual ~DiagnosticsConsumer() = default;<br class=""><br class="">-private:<br class="">- std::unique_ptr<ASTUnit> AST;<br class="">- DiagnosticToReplacementMap FixIts;<br class="">+ /// Called by ClangdServer when \p Diagnostics for \p File are ready.<br class="">+ virtual void onDiagnosticsReady(PathRef File,<br class="">+ std::vector<DiagWithFixIts> Diagnostics) = 0;<br class=""> };<br class=""><br class="">-enum class ASTManagerRequestType { ParseAndPublishDiagnostics, RemoveDocData };<br class="">+enum class WorkerRequestKind { ParseAndPublishDiagnostics, RemoveDocData };<br class=""><br class=""> /// A request to the worker thread<br class="">-class ASTManagerRequest {<br class="">+class WorkerRequest {<br class=""> public:<br class="">- ASTManagerRequest() = default;<br class="">- ASTManagerRequest(ASTManagerRequestType Type, std::string File,<br class="">- DocVersion Version);<br class="">+ WorkerRequest() = default;<br class="">+ WorkerRequest(WorkerRequestKind Kind, Path File, DocVersion Version);<br class=""><br class="">- ASTManagerRequestType Type;<br class="">- std::string File;<br class="">+ WorkerRequestKind Kind;<br class="">+ Path File;<br class=""> DocVersion Version;<br class=""> };<br class=""><br class="">-class ASTManager : public DocumentStoreListener {<br class="">-public:<br class="">- ASTManager(JSONOutput &Output, DocumentStore &Store, bool RunSynchronously);<br class="">- ~ASTManager() override;<br class="">-<br class="">- void onDocumentAdd(StringRef File) override;<br class="">- void onDocumentRemove(StringRef File) override;<br class="">+class ClangdServer;<br class=""><br class="">- /// Get code completions at a specified \p Line and \p Column in \p File.<br class="">- ///<br class="">- /// This function is thread-safe and returns completion items that own the<br class="">- /// data they contain.<br class="">- std::vector<CompletionItem> codeComplete(StringRef File, unsigned Line,<br class="">- unsigned Column);<br class="">-<br class="">- /// Get the fixes associated with a certain diagnostic in a specified file as<br class="">- /// replacements.<br class="">- ///<br class="">- /// This function is thread-safe. It returns a copy to avoid handing out<br class="">- /// references to unguarded data.<br class="">- std::vector<clang::tooling::Replacement><br class="">- getFixIts(StringRef File, const clangd::Diagnostic &D);<br class="">+/// Handles running WorkerRequests of ClangdServer on a separate threads.<br class="">+/// Currently runs only one worker thread.<br class="">+class ClangdScheduler {<br class="">+public:<br class="">+ ClangdScheduler(ClangdServer &Server, bool RunSynchronously);<br class="">+ ~ClangdScheduler();<br class=""><br class="">- DocumentStore &getStore() const { return Store; }<br class="">+ /// Enqueue WorkerRequest to be run on a worker thread<br class="">+ void enqueue(ClangdServer &Server, WorkerRequest Request);<br class=""><br class=""> private:<br class="">- JSONOutput &Output;<br class="">- DocumentStore &Store;<br class="">-<br class="">- // Set to true if requests should block instead of being processed<br class="">- // asynchronously.<br class=""> bool RunSynchronously;<br class="">-<br class="">- /// Loads a compilation database for File. May return nullptr if it fails. The<br class="">- /// database is cached for subsequent accesses.<br class="">- clang::tooling::CompilationDatabase *<br class="">- getOrCreateCompilationDatabaseForFile(StringRef File);<br class="">- // Creates a new ASTUnit for the document at File.<br class="">- // FIXME: This calls chdir internally, which is thread unsafe.<br class="">- std::unique_ptr<clang::ASTUnit><br class="">- createASTUnitForFile(StringRef File, const DocumentStore &Docs);<br class="">-<br class="">- /// If RunSynchronously is false, queues the request to be run on the worker<br class="">- /// thread.<br class="">- /// If RunSynchronously is true, runs the request handler immediately on the<br class="">- /// main thread.<br class="">- void queueOrRun(ASTManagerRequestType RequestType, StringRef File);<br class="">-<br class="">- void runWorker();<br class="">- void handleRequest(ASTManagerRequestType RequestType, StringRef File);<br class="">-<br class="">- /// Parses files and publishes diagnostics.<br class="">- /// This function is called on the worker thread in asynchronous mode and<br class="">- /// on the main thread in synchronous mode.<br class="">- void parseFileAndPublishDiagnostics(StringRef File);<br class="">-<br class="">- /// Caches compilation databases loaded from directories(keys are directories).<br class="">- llvm::StringMap<std::unique_ptr<clang::tooling::CompilationDatabase>><br class="">- CompilationDatabases;<br class="">-<br class="">- /// Clang objects.<br class="">- /// A map from filenames to DocData structures that store ASTUnit and Fixits for<br class="">- /// the files. The ASTUnits are used for generating diagnostics and fix-it-s<br class="">- /// asynchronously by the worker thread and synchronously for code completion.<br class="">- llvm::StringMap<DocData> DocDatas;<br class="">- std::shared_ptr<clang::PCHContainerOperations> PCHs;<br class="">- /// A lock for access to the DocDatas, CompilationDatabases and PCHs.<br class="">- std::mutex ClangObjectLock;<br class="">-<br class="">- /// Stores latest versions of the tracked documents to discard outdated requests.<br class="">- /// Guarded by RequestLock.<br class="">- /// TODO(ibiryukov): the entries are neved deleted from this map.<br class="">- llvm::StringMap<DocVersion> DocVersions;<br class="">-<br class="">- /// A LIFO queue of requests. Note that requests are discarded if the `version`<br class="">- /// field is not equal to the one stored inside DocVersions.<br class="">- /// TODO(krasimir): code completion should always have priority over parsing<br class="">- /// for diagnostics.<br class="">- std::deque<ASTManagerRequest> RequestQueue;<br class="">+ std::mutex Mutex;<br class="">+ /// We run some tasks on a separate thread(parsing, ClangdUnit cleanup).<br class="">+ /// This thread looks into RequestQueue to find requests to handle and<br class="">+ /// terminates when Done is set to true.<br class="">+ std::thread Worker;<br class=""> /// Setting Done to true will make the worker thread terminate.<br class=""> bool Done = false;<br class="">+ /// A LIFO queue of requests. Note that requests are discarded if the<br class="">+ /// `version` field is not equal to the one stored inside DraftStore.<br class="">+ /// FIXME(krasimir): code completion should always have priority over parsing<br class="">+ /// for diagnostics.<br class="">+ std::deque<WorkerRequest> RequestQueue;<br class=""> /// Condition variable to wake up the worker thread.<br class="">- std::condition_variable ClangRequestCV;<br class="">- /// Lock for accesses to RequestQueue, DocVersions and Done.<br class="">- std::mutex RequestLock;<br class="">-<br class="">- /// We run parsing on a separate thread. This thread looks into RequestQueue to<br class="">- /// find requests to handle and terminates when Done is set to true.<br class="">- std::thread ClangWorker;<br class="">+ std::condition_variable RequestCV;<br class="">+};<br class="">+<br class="">+/// Provides API to manage ASTs for a collection of C++ files and request<br class="">+/// various language features(currently, only codeCompletion and async<br class="">+/// diagnostics for tracked files).<br class="">+class ClangdServer {<br class="">+public:<br class="">+ ClangdServer(std::unique_ptr<GlobalCompilationDatabase> CDB,<br class="">+ std::unique_ptr<DiagnosticsConsumer> DiagConsumer,<br class="">+ bool RunSynchronously);<br class="">+<br class="">+ /// Add a \p File to the list of tracked C++ files or update the contents if<br class="">+ /// \p File is already tracked. Also schedules parsing of the AST for it on a<br class="">+ /// separate thread. When the parsing is complete, DiagConsumer passed in<br class="">+ /// constructor will receive onDiagnosticsReady callback.<br class="">+ void addDocument(PathRef File, StringRef Contents);<br class="">+<br class="">+ /// Remove \p File from list of tracked files, schedule a request to free<br class="">+ /// resources associated with it.<br class="">+ void removeDocument(PathRef File);<br class="">+<br class="">+ /// Run code completion for \p File at \p Pos.<br class="">+ std::vector<CompletionItem> codeComplete(PathRef File, Position Pos);<br class="">+<br class="">+ /// Gets current document contents for \p File. \p File must point to a<br class="">+ /// currently tracked file.<br class="">+ /// FIXME(ibiryukov): This function is here to allow implementation of<br class="">+ /// formatCode from ProtocolHandlers.cpp. We should move formatCode to this<br class="">+ /// class and remove this function from public interface.<br class="">+ std::string getDocument(PathRef File);<br class="">+<br class="">+private:<br class="">+ friend class ClangdScheduler;<br class="">+<br class="">+ /// This function is called on a worker thread.<br class="">+ void handleRequest(WorkerRequest Request);<br class="">+<br class="">+ std::unique_ptr<GlobalCompilationDatabase> CDB;<br class="">+ std::unique_ptr<DiagnosticsConsumer> DiagConsumer;<br class="">+ DraftStore DraftMgr;<br class="">+ ClangdUnitStore Units;<br class="">+ std::shared_ptr<PCHContainerOperations> PCHs;<br class="">+ // WorkScheduler has to be the last member, because its destructor has to be<br class="">+ // called before all other members to stop the worker thread that references<br class="">+ // ClangdServer<br class="">+ ClangdScheduler WorkScheduler;<br class=""> };<br class=""><br class=""> } // namespace clangd<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/ClangdUnit.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (added)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,224 @@<br class="">+//===--- ClangdUnit.cpp -----------------------------------------*- C++-*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===---------------------------------------------------------------------===//<br class="">+<br class="">+#include "ClangdUnit.h"<br class="">+#include "clang/Frontend/ASTUnit.h"<br class="">+#include "clang/Frontend/CompilerInstance.h"<br class="">+#include "clang/Frontend/CompilerInvocation.h"<br class="">+#include "clang/Tooling/CompilationDatabase.h"<br class="">+<br class="">+using namespace clang::clangd;<br class="">+using namespace clang;<br class="">+<br class="">+ClangdUnit::ClangdUnit(PathRef FileName, StringRef Contents,<br class="">+ std::shared_ptr<PCHContainerOperations> PCHs,<br class="">+ std::vector<tooling::CompileCommand> Commands)<br class="">+ : FileName(FileName), PCHs(PCHs) {<br class="">+ assert(!Commands.empty() && "No compile commands provided");<br class="">+<br class="">+ // Inject the resource dir.<br class="">+ // FIXME: Don't overwrite it if it's already there.<br class="">+ static int Dummy; // Just an address in this process.<br class="">+ std::string ResourceDir =<br class="">+ CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);<br class="">+ Commands.front().CommandLine.push_back("-resource-dir=" + ResourceDir);<br class="">+<br class="">+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags =<br class="">+ CompilerInstance::createDiagnostics(new DiagnosticOptions);<br class="">+<br class="">+ std::vector<const char *> ArgStrs;<br class="">+ for (const auto &S : Commands.front().CommandLine)<br class="">+ ArgStrs.push_back(S.c_str());<br class="">+<br class="">+ ASTUnit::RemappedFile RemappedSource(<br class="">+ FileName,<br class="">+ llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName).release());<br class="">+<br class="">+ auto ArgP = &*ArgStrs.begin();<br class="">+ Unit = std::unique_ptr<ASTUnit>(ASTUnit::LoadFromCommandLine(<br class="">+ ArgP, ArgP + ArgStrs.size(), PCHs, Diags, ResourceDir,<br class="">+ /*OnlyLocalDecls=*/false, /*CaptureDiagnostics=*/true, RemappedSource,<br class="">+ /*RemappedFilesKeepOriginalName=*/true,<br class="">+ /*PrecompilePreambleAfterNParses=*/1, /*TUKind=*/TU_Complete,<br class="">+ /*CacheCodeCompletionResults=*/true,<br class="">+ /*IncludeBriefCommentsInCodeCompletion=*/true,<br class="">+ /*AllowPCHWithCompilerErrors=*/true));<br class="">+}<br class="">+<br class="">+void ClangdUnit::reparse(StringRef Contents) {<br class="">+ // Do a reparse if this wasn't the first parse.<br class="">+ // FIXME: This might have the wrong working directory if it changed in the<br class="">+ // meantime.<br class="">+ ASTUnit::RemappedFile RemappedSource(<br class="">+ FileName,<br class="">+ llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName).release());<br class="">+<br class="">+ Unit->Reparse(PCHs, RemappedSource);<br class="">+}<br class="">+<br class="">+namespace {<br class="">+<br class="">+CompletionItemKind getKind(CXCursorKind K) {<br class="">+ switch (K) {<br class="">+ case CXCursor_MacroInstantiation:<br class="">+ case CXCursor_MacroDefinition:<br class="">+ return CompletionItemKind::Text;<br class="">+ case CXCursor_CXXMethod:<br class="">+ return CompletionItemKind::Method;<br class="">+ case CXCursor_FunctionDecl:<br class="">+ case CXCursor_FunctionTemplate:<br class="">+ return CompletionItemKind::Function;<br class="">+ case CXCursor_Constructor:<br class="">+ case CXCursor_Destructor:<br class="">+ return CompletionItemKind::Constructor;<br class="">+ case CXCursor_FieldDecl:<br class="">+ return CompletionItemKind::Field;<br class="">+ case CXCursor_VarDecl:<br class="">+ case CXCursor_ParmDecl:<br class="">+ return CompletionItemKind::Variable;<br class="">+ case CXCursor_ClassDecl:<br class="">+ case CXCursor_StructDecl:<br class="">+ case CXCursor_UnionDecl:<br class="">+ case CXCursor_ClassTemplate:<br class="">+ case CXCursor_ClassTemplatePartialSpecialization:<br class="">+ return CompletionItemKind::Class;<br class="">+ case CXCursor_Namespace:<br class="">+ case CXCursor_NamespaceAlias:<br class="">+ case CXCursor_NamespaceRef:<br class="">+ return CompletionItemKind::Module;<br class="">+ case CXCursor_EnumConstantDecl:<br class="">+ return CompletionItemKind::Value;<br class="">+ case CXCursor_EnumDecl:<br class="">+ return CompletionItemKind::Enum;<br class="">+ case CXCursor_TypeAliasDecl:<br class="">+ case CXCursor_TypeAliasTemplateDecl:<br class="">+ case CXCursor_TypedefDecl:<br class="">+ case CXCursor_MemberRef:<br class="">+ case CXCursor_TypeRef:<br class="">+ return CompletionItemKind::Reference;<br class="">+ default:<br class="">+ return CompletionItemKind::Missing;<br class="">+ }<br class="">+}<br class="">+<br class="">+class CompletionItemsCollector : public CodeCompleteConsumer {<br class="">+ std::vector<CompletionItem> *Items;<br class="">+ std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;<br class="">+ CodeCompletionTUInfo CCTUInfo;<br class="">+<br class="">+public:<br class="">+ CompletionItemsCollector(std::vector<CompletionItem> *Items,<br class="">+ const CodeCompleteOptions &CodeCompleteOpts)<br class="">+ : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),<br class="">+ Items(Items),<br class="">+ Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),<br class="">+ CCTUInfo(Allocator) {}<br class="">+<br class="">+ void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,<br class="">+ CodeCompletionResult *Results,<br class="">+ unsigned NumResults) override {<br class="">+ for (unsigned I = 0; I != NumResults; ++I) {<br class="">+ CodeCompletionResult &Result = Results[I];<br class="">+ CodeCompletionString *CCS = Result.CreateCodeCompletionString(<br class="">+ S, Context, *Allocator, CCTUInfo,<br class="">+ CodeCompleteOpts.IncludeBriefComments);<br class="">+ if (CCS) {<br class="">+ CompletionItem Item;<br class="">+ assert(CCS->getTypedText());<br class="">+ Item.label = CCS->getTypedText();<br class="">+ Item.kind = getKind(Result.CursorKind);<br class="">+ if (CCS->getBriefComment())<br class="">+ Item.documentation = CCS->getBriefComment();<br class="">+ Items->push_back(std::move(Item));<br class="">+ }<br class="">+ }<br class="">+ }<br class="">+<br class="">+ GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }<br class="">+<br class="">+ CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }<br class="">+};<br class="">+} // namespace<br class="">+<br class="">+std::vector<CompletionItem> ClangdUnit::codeComplete(StringRef Contents,<br class="">+ Position Pos) {<br class="">+ CodeCompleteOptions CCO;<br class="">+ CCO.IncludeBriefComments = 1;<br class="">+ // This is where code completion stores dirty buffers. Need to free after<br class="">+ // completion.<br class="">+ SmallVector<const llvm::MemoryBuffer *, 4> OwnedBuffers;<br class="">+ SmallVector<StoredDiagnostic, 4> StoredDiagnostics;<br class="">+ IntrusiveRefCntPtr<DiagnosticsEngine> DiagEngine(<br class="">+ new DiagnosticsEngine(new DiagnosticIDs, new DiagnosticOptions));<br class="">+ std::vector<CompletionItem> Items;<br class="">+ CompletionItemsCollector Collector(&Items, CCO);<br class="">+<br class="">+ ASTUnit::RemappedFile RemappedSource(<br class="">+ FileName,<br class="">+ llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName).release());<br class="">+<br class="">+ IntrusiveRefCntPtr<SourceManager> SourceMgr(<br class="">+ new SourceManager(*DiagEngine, Unit->getFileManager()));<br class="">+ // CodeComplete seems to require fresh LangOptions.<br class="">+ LangOptions LangOpts = Unit->getLangOpts();<br class="">+ // The language server protocol uses zero-based line and column numbers.<br class="">+ // The clang code completion uses one-based numbers.<br class="">+ Unit->CodeComplete(FileName, Pos.line + 1, Pos.character + 1, RemappedSource,<br class="">+ CCO.IncludeMacros, CCO.IncludeCodePatterns,<br class="">+ CCO.IncludeBriefComments, Collector, PCHs, *DiagEngine,<br class="">+ LangOpts, *SourceMgr, Unit->getFileManager(),<br class="">+ StoredDiagnostics, OwnedBuffers);<br class="">+ for (const llvm::MemoryBuffer *Buffer : OwnedBuffers)<br class="">+ delete Buffer;<br class="">+ return Items;<br class="">+}<br class="">+<br class="">+namespace {<br class="">+/// Convert from clang diagnostic level to LSP severity.<br class="">+static int getSeverity(DiagnosticsEngine::Level L) {<br class="">+ switch (L) {<br class="">+ case DiagnosticsEngine::Remark:<br class="">+ return 4;<br class="">+ case DiagnosticsEngine::Note:<br class="">+ return 3;<br class="">+ case DiagnosticsEngine::Warning:<br class="">+ return 2;<br class="">+ case DiagnosticsEngine::Fatal:<br class="">+ case DiagnosticsEngine::Error:<br class="">+ return 1;<br class="">+ case DiagnosticsEngine::Ignored:<br class="">+ return 0;<br class="">+ }<br class="">+ llvm_unreachable("Unknown diagnostic level!");<br class="">+}<br class="">+} // namespace<br class="">+<br class="">+std::vector<DiagWithFixIts> ClangdUnit::getLocalDiagnostics() const {<br class="">+ std::vector<DiagWithFixIts> Result;<br class="">+ for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),<br class="">+ DEnd = Unit->stored_diag_end();<br class="">+ D != DEnd; ++D) {<br class="">+ if (!D->getLocation().isValid() ||<br class="">+ !D->getLocation().getManager().isInMainFile(D->getLocation()))<br class="">+ continue;<br class="">+ Position P;<br class="">+ P.line = D->getLocation().getSpellingLineNumber() - 1;<br class="">+ P.character = D->getLocation().getSpellingColumnNumber();<br class="">+ Range R = {P, P};<br class="">+ clangd::Diagnostic Diag = {R, getSeverity(D->getLevel()), D->getMessage()};<br class="">+<br class="">+ llvm::SmallVector<tooling::Replacement, 1> FixItsForDiagnostic;<br class="">+ for (const FixItHint &Fix : D->getFixIts()) {<br class="">+ FixItsForDiagnostic.push_back(clang::tooling::Replacement(<br class="">+ Unit->getSourceManager(), Fix.RemoveRange, Fix.CodeToInsert));<br class="">+ }<br class="">+ Result.push_back({Diag, std::move(FixItsForDiagnostic)});<br class="">+ }<br class="">+ return Result;<br class="">+}<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/ClangdUnit.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdUnit.h (added)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdUnit.h Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,63 @@<br class="">+//===--- ClangdUnit.h -------------------------------------------*- C++-*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===---------------------------------------------------------------------===//<br class="">+<br class="">+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H<br class="">+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H<br class="">+<br class="">+#include "Protocol.h"<br class="">+#include "Path.h"<br class="">+#include "clang/Frontend/ASTUnit.h"<br class="">+#include "clang/Tooling/Core/Replacement.h"<br class="">+#include <memory><br class="">+<br class="">+namespace clang {<br class="">+class ASTUnit;<br class="">+class PCHContainerOperations;<br class="">+<br class="">+namespace tooling {<br class="">+struct CompileCommand;<br class="">+}<br class="">+<br class="">+namespace clangd {<br class="">+<br class="">+/// A diagnostic with its FixIts.<br class="">+struct DiagWithFixIts {<br class="">+ clangd::Diagnostic Diag;<br class="">+ llvm::SmallVector<tooling::Replacement, 1> FixIts;<br class="">+};<br class="">+<br class="">+/// Stores parsed C++ AST and provides implementations of all operations clangd<br class="">+/// would want to perform on parsed C++ files.<br class="">+class ClangdUnit {<br class="">+public:<br class="">+ ClangdUnit(PathRef FileName, StringRef Contents,<br class="">+ std::shared_ptr<PCHContainerOperations> PCHs,<br class="">+ std::vector<tooling::CompileCommand> Commands);<br class="">+<br class="">+ /// Reparse with new contents.<br class="">+ void reparse(StringRef Contents);<br class="">+<br class="">+ /// Get code completions at a specified \p Line and \p Column in \p File.<br class="">+ ///<br class="">+ /// This function is thread-safe and returns completion items that own the<br class="">+ /// data they contain.<br class="">+ std::vector<CompletionItem> codeComplete(StringRef Contents, Position Pos);<br class="">+ /// Returns diagnostics and corresponding FixIts for each diagnostic that are<br class="">+ /// located in the current file.<br class="">+ std::vector<DiagWithFixIts> getLocalDiagnostics() const;<br class="">+<br class="">+private:<br class="">+ Path FileName;<br class="">+ std::unique_ptr<ASTUnit> Unit;<br class="">+ std::shared_ptr<PCHContainerOperations> PCHs;<br class="">+};<br class="">+<br class="">+} // namespace clangd<br class="">+} // namespace clang<br class="">+#endif<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp (added)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,34 @@<br class="">+//===--- ClangdUnitStore.cpp - A ClangdUnits container -----------*-C++-*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+#include "ClangdUnitStore.h"<br class="">+#include "llvm/Support/Path.h"<br class="">+<br class="">+using namespace clang::clangd;<br class="">+using namespace clang;<br class="">+<br class="">+void ClangdUnitStore::removeUnitIfPresent(PathRef File) {<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+<br class="">+ auto It = OpenedFiles.find(File);<br class="">+ if (It == OpenedFiles.end())<br class="">+ return;<br class="">+ OpenedFiles.erase(It);<br class="">+}<br class="">+<br class="">+std::vector<tooling::CompileCommand> ClangdUnitStore::getCompileCommands(GlobalCompilationDatabase &CDB, PathRef File) {<br class="">+ std::vector<tooling::CompileCommand> Commands = CDB.getCompileCommands(File);<br class="">+ if (Commands.empty()) {<br class="">+ // Add a fake command line if we know nothing.<br class="">+ Commands.push_back(tooling::CompileCommand(<br class="">+ llvm::sys::path::parent_path(File), llvm::sys::path::filename(File),<br class="">+ {"clang", "-fsyntax-only", File.str()}, ""));<br class="">+ }<br class="">+ return Commands;<br class="">+}<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/ClangdUnitStore.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnitStore.h?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnitStore.h?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdUnitStore.h (added)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdUnitStore.h Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,93 @@<br class="">+//===--- ClangdUnitStore.h - A ClangdUnits container -------------*-C++-*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===---------------------------------------------------------------------===//<br class="">+<br class="">+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNITSTORE_H<br class="">+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNITSTORE_H<br class="">+<br class="">+#include <mutex><br class="">+<br class="">+#include "ClangdUnit.h"<br class="">+#include "GlobalCompilationDatabase.h"<br class="">+#include "Path.h"<br class="">+#include "clang/Tooling/CompilationDatabase.h"<br class="">+<br class="">+namespace clang {<br class="">+namespace clangd {<br class="">+<br class="">+/// Thread-safe collection of ASTs built for specific files. Provides<br class="">+/// synchronized access to ASTs.<br class="">+class ClangdUnitStore {<br class="">+public:<br class="">+ /// Run specified \p Action on the ClangdUnit for \p File.<br class="">+ /// If the file is not present in ClangdUnitStore, a new ClangdUnit will be<br class="">+ /// created from the \p FileContents. If the file is already present in the<br class="">+ /// store, ClangdUnit::reparse will be called with the new contents before<br class="">+ /// running \p Action.<br class="">+ template <class Func><br class="">+ void runOnUnit(PathRef File, StringRef FileContents,<br class="">+ GlobalCompilationDatabase &CDB,<br class="">+ std::shared_ptr<PCHContainerOperations> PCHs, Func Action) {<br class="">+ runOnUnitImpl(File, FileContents, CDB, PCHs, /*ReparseBeforeAction=*/true,<br class="">+ std::forward<Func>(Action));<br class="">+ }<br class="">+<br class="">+ /// Run specified \p Action on the ClangdUnit for \p File.<br class="">+ /// If the file is not present in ClangdUnitStore, a new ClangdUnit will be<br class="">+ /// created from the \p FileContents. If the file is already present in the<br class="">+ /// store, the \p Action will be run directly on it.<br class="">+ template <class Func><br class="">+ void runOnUnitWithoutReparse(PathRef File, StringRef FileContents,<br class="">+ GlobalCompilationDatabase &CDB,<br class="">+ std::shared_ptr<PCHContainerOperations> PCHs,<br class="">+ Func Action) {<br class="">+ runOnUnitImpl(File, FileContents, CDB, PCHs, /*ReparseBeforeAction=*/false,<br class="">+ std::forward<Func>(Action));<br class="">+ }<br class="">+<br class="">+ /// Remove ClangdUnit for \p File, if any<br class="">+ void removeUnitIfPresent(PathRef File);<br class="">+<br class="">+private:<br class="">+ /// Run specified \p Action on the ClangdUnit for \p File.<br class="">+ template <class Func><br class="">+ void runOnUnitImpl(PathRef File, StringRef FileContents,<br class="">+ GlobalCompilationDatabase &CDB,<br class="">+ std::shared_ptr<PCHContainerOperations> PCHs,<br class="">+ bool ReparseBeforeAction, Func Action) {<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+<br class="">+ auto Commands = getCompileCommands(CDB, File);<br class="">+ assert(!Commands.empty() &&<br class="">+ "getCompileCommands should add default command");<br class="">+ // chdir. This is thread hostile.<br class="">+ // FIXME(ibiryukov): get rid of this<br class="">+ llvm::sys::fs::set_current_path(Commands.front().Directory);<br class="">+<br class="">+ auto It = OpenedFiles.find(File);<br class="">+ if (It == OpenedFiles.end()) {<br class="">+ It = OpenedFiles<br class="">+ .insert(std::make_pair(<br class="">+ File, ClangdUnit(File, FileContents, PCHs, Commands)))<br class="">+ .first;<br class="">+ } else if (ReparseBeforeAction) {<br class="">+ It->second.reparse(FileContents);<br class="">+ }<br class="">+ return Action(It->second);<br class="">+ }<br class="">+<br class="">+ std::vector<tooling::CompileCommand><br class="">+ getCompileCommands(GlobalCompilationDatabase &CDB, PathRef File);<br class="">+<br class="">+ std::mutex Mutex;<br class="">+ llvm::StringMap<ClangdUnit> OpenedFiles;<br class="">+};<br class="">+} // namespace clangd<br class="">+} // namespace clang<br class="">+<br class="">+#endif<br class=""><br class="">Removed: clang-tools-extra/trunk/clangd/DocumentStore.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/DocumentStore.h?rev=303066&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/DocumentStore.h?rev=303066&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/DocumentStore.h (original)<br class="">+++ clang-tools-extra/trunk/clangd/DocumentStore.h (removed)<br class="">@@ -1,86 +0,0 @@<br class="">-//===--- DocumentStore.h - File contents container --------------*- C++ -*-===//<br class="">-//<br class="">-// The LLVM Compiler Infrastructure<br class="">-//<br class="">-// This file is distributed under the University of Illinois Open Source<br class="">-// License. See LICENSE.TXT for details.<br class="">-//<br class="">-//===----------------------------------------------------------------------===//<br class="">-<br class="">-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DOCUMENTSTORE_H<br class="">-#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DOCUMENTSTORE_H<br class="">-<br class="">-#include "clang/Basic/LLVM.h"<br class="">-#include "llvm/ADT/StringMap.h"<br class="">-#include <mutex><br class="">-#include <string><br class="">-#include <vector><br class="">-<br class="">-namespace clang {<br class="">-namespace clangd {<br class="">-class DocumentStore;<br class="">-<br class="">-struct DocumentStoreListener {<br class="">- virtual ~DocumentStoreListener() = default;<br class="">- virtual void onDocumentAdd(StringRef File) {}<br class="">- virtual void onDocumentRemove(StringRef File) {}<br class="">-};<br class="">-<br class="">-/// A container for files opened in a workspace, addressed by File. The contents<br class="">-/// are owned by the DocumentStore.<br class="">-class DocumentStore {<br class="">-public:<br class="">- /// Add a document to the store. Overwrites existing contents.<br class="">- void addDocument(StringRef File, StringRef Text) {<br class="">- {<br class="">- std::lock_guard<std::mutex> Guard(DocsMutex);<br class="">- Docs[File] = Text;<br class="">- }<br class="">- for (const auto &Listener : Listeners)<br class="">- Listener->onDocumentAdd(File);<br class="">- }<br class="">- /// Delete a document from the store.<br class="">- void removeDocument(StringRef File) {<br class="">- {<br class="">- std::lock_guard<std::mutex> Guard(DocsMutex);<br class="">- Docs.erase(File);<br class="">- }<br class="">- for (const auto &Listener : Listeners)<br class="">- Listener->onDocumentRemove(File);<br class="">- }<br class="">- /// Retrieve a document from the store. Empty string if it's unknown.<br class="">- ///<br class="">- /// This function is thread-safe. It returns a copy to avoid handing out<br class="">- /// references to unguarded data.<br class="">- std::string getDocument(StringRef File) const {<br class="">- // FIXME: This could be a reader lock.<br class="">- std::lock_guard<std::mutex> Guard(DocsMutex);<br class="">- return Docs.lookup(File);<br class="">- }<br class="">-<br class="">- /// Add a listener. Does not take ownership.<br class="">- void addListener(DocumentStoreListener *DSL) { Listeners.push_back(DSL); }<br class="">-<br class="">- /// Get name and constents of all documents in this store.<br class="">- ///<br class="">- /// This function is thread-safe. It returns a copies to avoid handing out<br class="">- /// references to unguarded data.<br class="">- std::vector<std::pair<std::string, std::string>> getAllDocuments() const {<br class="">- std::vector<std::pair<std::string, std::string>> AllDocs;<br class="">- std::lock_guard<std::mutex> Guard(DocsMutex);<br class="">- for (const auto &P : Docs)<br class="">- AllDocs.emplace_back(P.first(), P.second);<br class="">- return AllDocs;<br class="">- }<br class="">-<br class="">-private:<br class="">- llvm::StringMap<std::string> Docs;<br class="">- std::vector<DocumentStoreListener *> Listeners;<br class="">-<br class="">- mutable std::mutex DocsMutex;<br class="">-};<br class="">-<br class="">-} // namespace clangd<br class="">-} // namespace clang<br class="">-<br class="">-#endif<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/DraftStore.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/DraftStore.cpp?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/DraftStore.cpp?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/DraftStore.cpp (added)<br class="">+++ clang-tools-extra/trunk/clangd/DraftStore.cpp Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,48 @@<br class="">+//===--- DraftStore.cpp - File contents container ---------------*- C++ -*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+#include "DraftStore.h"<br class="">+<br class="">+using namespace clang::clangd;<br class="">+<br class="">+VersionedDraft DraftStore::getDraft(PathRef File) const {<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+<br class="">+ auto It = Drafts.find(File);<br class="">+ if (It == Drafts.end())<br class="">+ return {0, llvm::None};<br class="">+ return It->second;<br class="">+}<br class="">+<br class="">+DocVersion DraftStore::getVersion(PathRef File) const {<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+<br class="">+ auto It = Drafts.find(File);<br class="">+ if (It == Drafts.end())<br class="">+ return 0;<br class="">+ return It->second.Version;<br class="">+}<br class="">+<br class="">+DocVersion DraftStore::updateDraft(PathRef File, StringRef Contents) {<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+<br class="">+ auto &Entry = Drafts[File];<br class="">+ DocVersion NewVersion = ++Entry.Version;<br class="">+ Entry.Draft = Contents;<br class="">+ return NewVersion;<br class="">+}<br class="">+<br class="">+DocVersion DraftStore::removeDraft(PathRef File) {<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+<br class="">+ auto &Entry = Drafts[File];<br class="">+ DocVersion NewVersion = ++Entry.Version;<br class="">+ Entry.Draft = llvm::None;<br class="">+ return NewVersion;<br class="">+}<br class=""><br class="">Copied: clang-tools-extra/trunk/clangd/DraftStore.h (from r303060, clang-tools-extra/trunk/clangd/DocumentStore.h)<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/DraftStore.h?p2=clang-tools-extra/trunk/clangd/DraftStore.h&p1=clang-tools-extra/trunk/clangd/DocumentStore.h&r1=303060&r2=303067&rev=303067&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/DraftStore.h?p2=clang-tools-extra/trunk/clangd/DraftStore.h&p1=clang-tools-extra/trunk/clangd/DocumentStore.h&r1=303060&r2=303067&rev=303067&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/DocumentStore.h (original)<br class="">+++ clang-tools-extra/trunk/clangd/DraftStore.h Mon May 15 09:17:35 2017<br class="">@@ -1,4 +1,4 @@<br class="">-//===--- DocumentStore.h - File contents container --------------*- C++ -*-===//<br class="">+//===--- DraftStore.h - File contents container -----------------*- C++ -*-===//<br class=""> //<br class=""> // The LLVM Compiler Infrastructure<br class=""> //<br class="">@@ -7,9 +7,10 @@<br class=""> //<br class=""> //===----------------------------------------------------------------------===//<br class=""><br class="">-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DOCUMENTSTORE_H<br class="">-#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DOCUMENTSTORE_H<br class="">+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DRAFTSTORE_H<br class="">+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DRAFTSTORE_H<br class=""><br class="">+#include "Path.h"<br class=""> #include "clang/Basic/LLVM.h"<br class=""> #include "llvm/ADT/StringMap.h"<br class=""> #include <mutex><br class="">@@ -18,66 +19,40 @@<br class=""><br class=""> namespace clang {<br class=""> namespace clangd {<br class="">-class DocumentStore;<br class=""><br class="">-struct DocumentStoreListener {<br class="">- virtual ~DocumentStoreListener() = default;<br class="">- virtual void onDocumentAdd(StringRef File) {}<br class="">- virtual void onDocumentRemove(StringRef File) {}<br class="">+/// Using 'unsigned' here to avoid undefined behaviour on overflow.<br class="">+typedef unsigned DocVersion;<br class="">+<br class="">+/// Document draft with a version of this draft.<br class="">+struct VersionedDraft {<br class="">+ DocVersion Version;<br class="">+ /// If the value of the field is None, draft is now deleted<br class="">+ llvm::Optional<std::string> Draft;<br class=""> };<br class=""><br class="">-/// A container for files opened in a workspace, addressed by File. The contents<br class="">-/// are owned by the DocumentStore.<br class="">-class DocumentStore {<br class="">+/// A thread-safe container for files opened in a workspace, addressed by<br class="">+/// filenames. The contents are owned by the DraftStore. Versions are mantained<br class="">+/// for the all added documents, including removed ones. The document version is<br class="">+/// incremented on each update and removal of the document.<br class="">+class DraftStore {<br class=""> public:<br class="">- /// Add a document to the store. Overwrites existing contents.<br class="">- void addDocument(StringRef File, StringRef Text) {<br class="">- {<br class="">- std::lock_guard<std::mutex> Guard(DocsMutex);<br class="">- Docs[File] = Text;<br class="">- }<br class="">- for (const auto &Listener : Listeners)<br class="">- Listener->onDocumentAdd(File);<br class="">- }<br class="">- /// Delete a document from the store.<br class="">- void removeDocument(StringRef File) {<br class="">- {<br class="">- std::lock_guard<std::mutex> Guard(DocsMutex);<br class="">- Docs.erase(File);<br class="">- }<br class="">- for (const auto &Listener : Listeners)<br class="">- Listener->onDocumentRemove(File);<br class="">- }<br class="">- /// Retrieve a document from the store. Empty string if it's unknown.<br class="">- ///<br class="">- /// This function is thread-safe. It returns a copy to avoid handing out<br class="">- /// references to unguarded data.<br class="">- std::string getDocument(StringRef File) const {<br class="">- // FIXME: This could be a reader lock.<br class="">- std::lock_guard<std::mutex> Guard(DocsMutex);<br class="">- return Docs.lookup(File);<br class="">- }<br class="">-<br class="">- /// Add a listener. Does not take ownership.<br class="">- void addListener(DocumentStoreListener *DSL) { Listeners.push_back(DSL); }<br class="">-<br class="">- /// Get name and constents of all documents in this store.<br class="">- ///<br class="">- /// This function is thread-safe. It returns a copies to avoid handing out<br class="">- /// references to unguarded data.<br class="">- std::vector<std::pair<std::string, std::string>> getAllDocuments() const {<br class="">- std::vector<std::pair<std::string, std::string>> AllDocs;<br class="">- std::lock_guard<std::mutex> Guard(DocsMutex);<br class="">- for (const auto &P : Docs)<br class="">- AllDocs.emplace_back(P.first(), P.second);<br class="">- return AllDocs;<br class="">- }<br class="">+ /// \return version and contents of the stored document.<br class="">+ /// For untracked files, a (0, None) pair is returned.<br class="">+ VersionedDraft getDraft(PathRef File) const;<br class="">+ /// \return version of the tracked document.<br class="">+ /// For untracked files, 0 is returned.<br class="">+ DocVersion getVersion(PathRef File) const;<br class="">+<br class="">+ /// Replace contents of the draft for \p File with \p Contents.<br class="">+ /// \return The new version of the draft for \p File.<br class="">+ DocVersion updateDraft(PathRef File, StringRef Contents);<br class="">+ /// Remove the contents of the draft<br class="">+ /// \return The new version of the draft for \p File.<br class="">+ DocVersion removeDraft(PathRef File);<br class=""><br class=""> private:<br class="">- llvm::StringMap<std::string> Docs;<br class="">- std::vector<DocumentStoreListener *> Listeners;<br class="">-<br class="">- mutable std::mutex DocsMutex;<br class="">+ mutable std::mutex Mutex;<br class="">+ llvm::StringMap<VersionedDraft> Drafts;<br class=""> };<br class=""><br class=""> } // namespace clangd<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp (added)<br class="">+++ clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,65 @@<br class="">+//===--- GlobalCompilationDatabase.cpp --------------------------*- C++-*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===---------------------------------------------------------------------===//<br class="">+<br class="">+#include "GlobalCompilationDatabase.h"<br class="">+#include "clang/Tooling/CompilationDatabase.h"<br class="">+#include "llvm/Support/FileSystem.h"<br class="">+#include "llvm/Support/Path.h"<br class="">+<br class="">+using namespace clang::clangd;<br class="">+using namespace clang;<br class="">+<br class="">+std::vector<tooling::CompileCommand><br class="">+DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) {<br class="">+ std::vector<tooling::CompileCommand> Commands;<br class="">+<br class="">+ auto CDB = getCompilationDatabase(File);<br class="">+ if (!CDB)<br class="">+ return {};<br class="">+ return CDB->getCompileCommands(File);<br class="">+}<br class="">+<br class="">+tooling::CompilationDatabase *<br class="">+DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) {<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+<br class="">+ namespace path = llvm::sys::path;<br class="">+<br class="">+ assert((path::is_absolute(File, path::Style::posix) ||<br class="">+ path::is_absolute(File, path::Style::windows)) &&<br class="">+ "path must be absolute");<br class="">+<br class="">+ for (auto Path = path::parent_path(File); !Path.empty();<br class="">+ Path = path::parent_path(Path)) {<br class="">+<br class="">+ auto CachedIt = CompilationDatabases.find(Path);<br class="">+ if (CachedIt != CompilationDatabases.end())<br class="">+ return CachedIt->second.get();<br class="">+ std::string Error;<br class="">+ auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error);<br class="">+ if (!CDB) {<br class="">+ if (!Error.empty()) {<br class="">+ // FIXME(ibiryukov): logging<br class="">+ // Output.log("Error when trying to load compilation database from " +<br class="">+ // Twine(Path) + ": " + Twine(Error) + "\n");<br class="">+ }<br class="">+ continue;<br class="">+ }<br class="">+<br class="">+ // FIXME(ibiryukov): Invalidate cached compilation databases on changes<br class="">+ auto result = CDB.get();<br class="">+ CompilationDatabases.insert(std::make_pair(Path, std::move(CDB)));<br class="">+ return result;<br class="">+ }<br class="">+<br class="">+ // FIXME(ibiryukov): logging<br class="">+ // Output.log("Failed to find compilation database for " + Twine(File) +<br class="">+ // "\n");<br class="">+ return nullptr;<br class="">+}<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h (added)<br class="">+++ clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,59 @@<br class="">+//===--- GlobalCompilationDatabase.h ----------------------------*- C++-*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===---------------------------------------------------------------------===//<br class="">+<br class="">+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H<br class="">+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H<br class="">+<br class="">+#include "Path.h"<br class="">+#include "llvm/ADT/StringMap.h"<br class="">+#include <memory><br class="">+#include <mutex><br class="">+<br class="">+namespace clang {<br class="">+<br class="">+namespace tooling {<br class="">+class CompilationDatabase;<br class="">+struct CompileCommand;<br class="">+} // namespace tooling<br class="">+<br class="">+namespace clangd {<br class="">+<br class="">+/// Provides compilation arguments used for building ClangdUnit.<br class="">+class GlobalCompilationDatabase {<br class="">+public:<br class="">+ virtual ~GlobalCompilationDatabase() = default;<br class="">+<br class="">+ virtual std::vector<tooling::CompileCommand><br class="">+ getCompileCommands(PathRef File) = 0;<br class="">+<br class="">+ /// FIXME(ibiryukov): add facilities to track changes to compilation flags of<br class="">+ /// existing targets.<br class="">+};<br class="">+<br class="">+/// Gets compile args from tooling::CompilationDatabases built for parent<br class="">+/// directories.<br class="">+class DirectoryBasedGlobalCompilationDatabase<br class="">+ : public GlobalCompilationDatabase {<br class="">+public:<br class="">+ std::vector<tooling::CompileCommand><br class="">+ getCompileCommands(PathRef File) override;<br class="">+<br class="">+private:<br class="">+ tooling::CompilationDatabase *getCompilationDatabase(PathRef File);<br class="">+<br class="">+ std::mutex Mutex;<br class="">+ /// Caches compilation databases loaded from directories(keys are<br class="">+ /// directories).<br class="">+ llvm::StringMap<std::unique_ptr<clang::tooling::CompilationDatabase>><br class="">+ CompilationDatabases;<br class="">+};<br class="">+} // namespace clangd<br class="">+} // namespace clang<br class="">+<br class="">+#endif<br class=""><br class="">Added: clang-tools-extra/trunk/clangd/Path.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Path.h?rev=303067&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Path.h?rev=303067&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/Path.h (added)<br class="">+++ clang-tools-extra/trunk/clangd/Path.h Mon May 15 09:17:35 2017<br class="">@@ -0,0 +1,29 @@<br class="">+//===--- Path.h - Helper typedefs --------------------------------*- C++-*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATH_H<br class="">+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATH_H<br class="">+<br class="">+#include "llvm/ADT/StringRef.h"<br class="">+#include <string><br class="">+<br class="">+namespace clang {<br class="">+namespace clangd {<br class="">+<br class="">+/// A typedef to represent a file path. Used solely for more descriptive<br class="">+/// signatures.<br class="">+using Path = std::string;<br class="">+/// A typedef to represent a ref to file path. Used solely for more descriptive<br class="">+/// signatures.<br class="">+using PathRef = llvm::StringRef;<br class="">+<br class="">+} // namespace clangd<br class="">+} // namespace clang<br class="">+<br class="">+#endif<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp?rev=303067&r1=303066&r2=303067&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp?rev=303067&r1=303066&r2=303067&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp (original)<br class="">+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp Mon May 15 09:17:35 2017<br class="">@@ -8,9 +8,10 @@<br class=""> //===----------------------------------------------------------------------===//<br class=""><br class=""> #include "ProtocolHandlers.h"<br class="">-#include "ASTManager.h"<br class="">-#include "DocumentStore.h"<br class="">+#include "ClangdServer.h"<br class="">+#include "DraftStore.h"<br class=""> #include "clang/Format/Format.h"<br class="">+#include "ClangdLSPServer.h"<br class=""> using namespace clang;<br class=""> using namespace clangd;<br class=""><br class="">@@ -21,7 +22,7 @@ void TextDocumentDidOpenHandler::handleN<br class=""> Output.log("Failed to decode DidOpenTextDocumentParams!\n");<br class=""> return;<br class=""> }<br class="">- Store.addDocument(DOTDP->textDocument.uri.file, DOTDP->textDocument.text);<br class="">+ AST.openDocument(DOTDP->textDocument.uri.file, DOTDP->textDocument.text);<br class=""> }<br class=""><br class=""> void TextDocumentDidCloseHandler::handleNotification(<br class="">@@ -32,7 +33,7 @@ void TextDocumentDidCloseHandler::handle<br class=""> return;<br class=""> }<br class=""><br class="">- Store.removeDocument(DCTDP->textDocument.uri.file);<br class="">+ AST.closeDocument(DCTDP->textDocument.uri.file);<br class=""> }<br class=""><br class=""> void TextDocumentDidChangeHandler::handleNotification(<br class="">@@ -43,7 +44,7 @@ void TextDocumentDidChangeHandler::handl<br class=""> return;<br class=""> }<br class=""> // We only support full syncing right now.<br class="">- Store.addDocument(DCTDP->textDocument.uri.file, DCTDP->contentChanges[0].text);<br class="">+ AST.openDocument(DCTDP->textDocument.uri.file, DCTDP->contentChanges[0].text);<br class=""> }<br class=""><br class=""> /// Turn a [line, column] pair into an offset in Code.<br class="">@@ -110,7 +111,7 @@ void TextDocumentRangeFormattingHandler:<br class=""> return;<br class=""> }<br class=""><br class="">- std::string Code = Store.getDocument(DRFP->textDocument.uri.file);<br class="">+ std::string Code = AST.getDocument(DRFP->textDocument.uri.file);<br class=""><br class=""> size_t Begin = positionToOffset(Code, DRFP->range.start);<br class=""> size_t Len = positionToOffset(Code, DRFP->range.end) - Begin;<br class="">@@ -129,7 +130,7 @@ void TextDocumentOnTypeFormattingHandler<br class=""><br class=""> // Look for the previous opening brace from the character position and format<br class=""> // starting from there.<br class="">- std::string Code = Store.getDocument(DOTFP->textDocument.uri.file);<br class="">+ std::string Code = AST.getDocument(DOTFP->textDocument.uri.file);<br class=""> size_t CursorPos = positionToOffset(Code, DOTFP->position);<br class=""> size_t PreviousLBracePos = StringRef(Code).find_last_of('{', CursorPos);<br class=""> if (PreviousLBracePos == StringRef::npos)<br class="">@@ -149,7 +150,7 @@ void TextDocumentFormattingHandler::hand<br class=""> }<br class=""><br class=""> // Format everything.<br class="">- std::string Code = Store.getDocument(DFP->textDocument.uri.file);<br class="">+ std::string Code = AST.getDocument(DFP->textDocument.uri.file);<br class=""> writeMessage(formatCode(Code, DFP->textDocument.uri.file,<br class=""> {clang::tooling::Range(0, Code.size())}, ID));<br class=""> }<br class="">@@ -164,7 +165,7 @@ void CodeActionHandler::handleMethod(llv<br class=""><br class=""> // We provide a code action for each diagnostic at the requested location<br class=""> // which has FixIts available.<br class="">- std::string Code = AST.getStore().getDocument(CAP->textDocument.uri.file);<br class="">+ std::string Code = AST.getDocument(CAP->textDocument.uri.file);<br class=""> std::string Commands;<br class=""> for (Diagnostic &D : CAP->context.diagnostics) {<br class=""> std::vector<clang::tooling::Replacement> Fixes = AST.getFixIts(CAP->textDocument.uri.file, D);<br class="">@@ -195,8 +196,8 @@ void CompletionHandler::handleMethod(llv<br class=""> return;<br class=""> }<br class=""><br class="">- auto Items = AST.codeComplete(TDPP->textDocument.uri.file, TDPP->position.line,<br class="">- TDPP->position.character);<br class="">+ auto Items = AST.codeComplete(TDPP->textDocument.uri.file, Position{TDPP->position.line,<br class="">+ TDPP->position.character});<br class=""> std::string Completions;<br class=""> for (const auto &Item : Items) {<br class=""> Completions += CompletionItem::unparse(Item);<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.h?rev=303067&r1=303066&r2=303067&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.h?rev=303067&r1=303066&r2=303067&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ProtocolHandlers.h (original)<br class="">+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.h Mon May 15 09:17:35 2017<br class="">@@ -22,8 +22,8 @@<br class=""><br class=""> namespace clang {<br class=""> namespace clangd {<br class="">-class ASTManager;<br class="">-class DocumentStore;<br class="">+class ClangdLSPServer;<br class="">+class ClangdLSPServer;<br class=""><br class=""> struct InitializeHandler : Handler {<br class=""> InitializeHandler(JSONOutput &Output) : Handler(Output) {}<br class="">@@ -56,83 +56,83 @@ private:<br class=""> };<br class=""><br class=""> struct TextDocumentDidOpenHandler : Handler {<br class="">- TextDocumentDidOpenHandler(JSONOutput &Output, DocumentStore &Store)<br class="">- : Handler(Output), Store(Store) {}<br class="">+ TextDocumentDidOpenHandler(JSONOutput &Output, ClangdLSPServer &AST)<br class="">+ : Handler(Output), AST(AST) {}<br class=""><br class=""> void handleNotification(llvm::yaml::MappingNode *Params) override;<br class=""><br class=""> private:<br class="">- DocumentStore &Store;<br class="">+ ClangdLSPServer &AST;<br class=""> };<br class=""><br class=""> struct TextDocumentDidChangeHandler : Handler {<br class="">- TextDocumentDidChangeHandler(JSONOutput &Output, DocumentStore &Store)<br class="">- : Handler(Output), Store(Store) {}<br class="">+ TextDocumentDidChangeHandler(JSONOutput &Output, ClangdLSPServer &AST)<br class="">+ : Handler(Output), AST(AST) {}<br class=""><br class=""> void handleNotification(llvm::yaml::MappingNode *Params) override;<br class=""><br class=""> private:<br class="">- DocumentStore &Store;<br class="">+ ClangdLSPServer &AST;<br class=""> };<br class=""><br class=""> struct TextDocumentDidCloseHandler : Handler {<br class="">- TextDocumentDidCloseHandler(JSONOutput &Output, DocumentStore &Store)<br class="">- : Handler(Output), Store(Store) {}<br class="">+ TextDocumentDidCloseHandler(JSONOutput &Output, ClangdLSPServer &AST)<br class="">+ : Handler(Output), AST(AST) {}<br class=""><br class=""> void handleNotification(llvm::yaml::MappingNode *Params) override;<br class=""><br class=""> private:<br class="">- DocumentStore &Store;<br class="">+ ClangdLSPServer &AST;<br class=""> };<br class=""><br class=""> struct TextDocumentOnTypeFormattingHandler : Handler {<br class="">- TextDocumentOnTypeFormattingHandler(JSONOutput &Output, DocumentStore &Store)<br class="">- : Handler(Output), Store(Store) {}<br class="">+ TextDocumentOnTypeFormattingHandler(JSONOutput &Output, ClangdLSPServer &AST)<br class="">+ : Handler(Output), AST(AST) {}<br class=""><br class=""> void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;<br class=""><br class=""> private:<br class="">- DocumentStore &Store;<br class="">+ ClangdLSPServer &AST;<br class=""> };<br class=""><br class=""> struct TextDocumentRangeFormattingHandler : Handler {<br class="">- TextDocumentRangeFormattingHandler(JSONOutput &Output, DocumentStore &Store)<br class="">- : Handler(Output), Store(Store) {}<br class="">+ TextDocumentRangeFormattingHandler(JSONOutput &Output, ClangdLSPServer &AST)<br class="">+ : Handler(Output), AST(AST) {}<br class=""><br class=""> void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;<br class=""><br class=""> private:<br class="">- DocumentStore &Store;<br class="">+ ClangdLSPServer &AST;<br class=""> };<br class=""><br class=""> struct TextDocumentFormattingHandler : Handler {<br class="">- TextDocumentFormattingHandler(JSONOutput &Output, DocumentStore &Store)<br class="">- : Handler(Output), Store(Store) {}<br class="">+ TextDocumentFormattingHandler(JSONOutput &Output, ClangdLSPServer &AST)<br class="">+ : Handler(Output), AST(AST) {}<br class=""><br class=""> void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;<br class=""><br class=""> private:<br class="">- DocumentStore &Store;<br class="">+ ClangdLSPServer &AST;<br class=""> };<br class=""><br class=""> struct CodeActionHandler : Handler {<br class="">- CodeActionHandler(JSONOutput &Output, ASTManager &AST)<br class="">+ CodeActionHandler(JSONOutput &Output, ClangdLSPServer &AST)<br class=""> : Handler(Output), AST(AST) {}<br class=""><br class=""> void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;<br class=""><br class=""> private:<br class="">- ASTManager &AST;<br class="">+ ClangdLSPServer &AST;<br class=""> };<br class=""><br class=""> struct CompletionHandler : Handler {<br class="">- CompletionHandler(JSONOutput &Output, ASTManager &AST)<br class="">+ CompletionHandler(JSONOutput &Output, ClangdLSPServer &AST)<br class=""> : Handler(Output), AST(AST) {}<br class=""><br class=""> void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;<br class=""><br class=""> private:<br class="">- ASTManager &AST;<br class="">+ ClangdLSPServer &AST;<br class=""> };<br class=""><br class=""> } // namespace clangd<br class=""><br class=""><br class="">_______________________________________________<br class="">cfe-commits mailing list<br class=""><a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a><br class=""><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class=""></div></div></blockquote></div><br class=""></div></div></div></blockquote></div><br class=""></div></div></div></blockquote></div><br class=""></div></body></html>