<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body 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><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="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits<br class=""></div></div></blockquote></div><br class=""></div></body></html>