[clang-tools-extra] r303151 - Restored r303067 and fixed failing test.

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Tue May 16 02:38:59 PDT 2017


Author: ibiryukov
Date: Tue May 16 04:38:59 2017
New Revision: 303151

URL: http://llvm.org/viewvc/llvm-project?rev=303151&view=rev
Log:
Restored r303067 and fixed failing test.

Summary:
This commit restores r303067(reverted by r303094) and fixes the 'formatting.test'
failure.
The failure is due to destructors of `ClangdLSPServer`'s fields(`FixItsMap` and
`FixItsMutex`) being called before destructor of `Server`. It led to the worker
thread calling `consumeDiagnostics` after `FixItsMutex` and `FixItsMap`
destructors were called.
Also, clangd is now run with '-run-synchronously' flag in 'formatting.test'.

Reviewers: bkramer, krasimir

Reviewed By: krasimir

Subscribers: mgorny, cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D33233

Added:
    clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
    clang-tools-extra/trunk/clangd/ClangdLSPServer.h
      - copied, changed from r303093, clang-tools-extra/trunk/clangd/ClangdLSPServer.h
    clang-tools-extra/trunk/clangd/ClangdServer.cpp
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/ClangdServer.cpp
    clang-tools-extra/trunk/clangd/ClangdServer.h
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/ClangdServer.h
    clang-tools-extra/trunk/clangd/ClangdUnit.cpp
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/ClangdUnit.cpp
    clang-tools-extra/trunk/clangd/ClangdUnit.h
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/ClangdUnit.h
    clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp
    clang-tools-extra/trunk/clangd/ClangdUnitStore.h
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/ClangdUnitStore.h
    clang-tools-extra/trunk/clangd/DraftStore.cpp
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/DraftStore.cpp
    clang-tools-extra/trunk/clangd/DraftStore.h
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/DraftStore.h
    clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp
    clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h
    clang-tools-extra/trunk/clangd/Path.h
      - copied unchanged from r303093, clang-tools-extra/trunk/clangd/Path.h
Removed:
    clang-tools-extra/trunk/clangd/ASTManager.cpp
    clang-tools-extra/trunk/clangd/ASTManager.h
    clang-tools-extra/trunk/clangd/DocumentStore.h
Modified:
    clang-tools-extra/trunk/clangd/CMakeLists.txt
    clang-tools-extra/trunk/clangd/ClangdMain.cpp
    clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
    clang-tools-extra/trunk/clangd/ProtocolHandlers.h
    clang-tools-extra/trunk/test/clangd/formatting.test

Removed: clang-tools-extra/trunk/clangd/ASTManager.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ASTManager.cpp?rev=303150&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/ASTManager.cpp (original)
+++ clang-tools-extra/trunk/clangd/ASTManager.cpp (removed)
@@ -1,440 +0,0 @@
-//===--- ASTManager.cpp - Clang AST manager -------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ASTManager.h"
-#include "JSONRPCDispatcher.h"
-#include "Protocol.h"
-#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Tooling/CompilationDatabase.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/Path.h"
-#include <mutex>
-#include <thread>
-using namespace clang;
-using namespace clangd;
-
-void DocData::setAST(std::unique_ptr<ASTUnit> AST) {
-  this->AST = std::move(AST);
-}
-
-ASTUnit *DocData::getAST() const { return AST.get(); }
-
-void DocData::cacheFixIts(DiagnosticToReplacementMap FixIts) {
-  this->FixIts = std::move(FixIts);
-}
-
-std::vector<clang::tooling::Replacement>
-DocData::getFixIts(const clangd::Diagnostic &D) const {
-  auto it = FixIts.find(D);
-  if (it != FixIts.end())
-    return it->second;
-  return {};
-}
-
-ASTManagerRequest::ASTManagerRequest(ASTManagerRequestType Type,
-                                     std::string File,
-                                     DocVersion Version)
-    : Type(Type), File(File), Version(Version) {}
-
-/// Retrieve a copy of the contents of every file in the store, for feeding into
-/// ASTUnit.
-static std::vector<ASTUnit::RemappedFile>
-getRemappedFiles(const DocumentStore &Docs) {
-  // FIXME: Use VFS instead. This would allow us to get rid of the chdir below.
-  std::vector<ASTUnit::RemappedFile> RemappedFiles;
-  for (const auto &P : Docs.getAllDocuments()) {
-    StringRef FileName = P.first;
-    RemappedFiles.push_back(ASTUnit::RemappedFile(
-        FileName,
-        llvm::MemoryBuffer::getMemBufferCopy(P.second, FileName).release()));
-  }
-  return RemappedFiles;
-}
-
-/// Convert from clang diagnostic level to LSP severity.
-static int getSeverity(DiagnosticsEngine::Level L) {
-  switch (L) {
-  case DiagnosticsEngine::Remark:
-    return 4;
-  case DiagnosticsEngine::Note:
-    return 3;
-  case DiagnosticsEngine::Warning:
-    return 2;
-  case DiagnosticsEngine::Fatal:
-  case DiagnosticsEngine::Error:
-    return 1;
-  case DiagnosticsEngine::Ignored:
-    return 0;
-  }
-  llvm_unreachable("Unknown diagnostic level!");
-}
-
-static CompletionItemKind getKind(CXCursorKind K) {
-  switch (K) {
-  case CXCursor_MacroInstantiation:
-  case CXCursor_MacroDefinition:
-    return CompletionItemKind::Text;
-  case CXCursor_CXXMethod:
-    return CompletionItemKind::Method;
-  case CXCursor_FunctionDecl:
-  case CXCursor_FunctionTemplate:
-    return CompletionItemKind::Function;
-  case CXCursor_Constructor:
-  case CXCursor_Destructor:
-    return CompletionItemKind::Constructor;
-  case CXCursor_FieldDecl:
-    return CompletionItemKind::Field;
-  case CXCursor_VarDecl:
-  case CXCursor_ParmDecl:
-    return CompletionItemKind::Variable;
-  case CXCursor_ClassDecl:
-  case CXCursor_StructDecl:
-  case CXCursor_UnionDecl:
-  case CXCursor_ClassTemplate:
-  case CXCursor_ClassTemplatePartialSpecialization:
-    return CompletionItemKind::Class;
-  case CXCursor_Namespace:
-  case CXCursor_NamespaceAlias:
-  case CXCursor_NamespaceRef:
-    return CompletionItemKind::Module;
-  case CXCursor_EnumConstantDecl:
-    return CompletionItemKind::Value;
-  case CXCursor_EnumDecl:
-    return CompletionItemKind::Enum;
-  case CXCursor_TypeAliasDecl:
-  case CXCursor_TypeAliasTemplateDecl:
-  case CXCursor_TypedefDecl:
-  case CXCursor_MemberRef:
-  case CXCursor_TypeRef:
-    return CompletionItemKind::Reference;
-  default:
-    return CompletionItemKind::Missing;
-  }
-}
-
-ASTManager::ASTManager(JSONOutput &Output, DocumentStore &Store,
-                       bool RunSynchronously)
-    : Output(Output), Store(Store), RunSynchronously(RunSynchronously),
-      PCHs(std::make_shared<PCHContainerOperations>()),
-      ClangWorker([this]() { runWorker(); }) {}
-
-void ASTManager::runWorker() {
-  while (true) {
-    ASTManagerRequest Request;
-
-    // Pick request from the queue
-    {
-      std::unique_lock<std::mutex> Lock(RequestLock);
-      // Wait for more requests.
-      ClangRequestCV.wait(Lock,
-                          [this] { return !RequestQueue.empty() || Done; });
-      if (Done)
-        return;
-      assert(!RequestQueue.empty() && "RequestQueue was empty");
-
-      Request = std::move(RequestQueue.back());
-      RequestQueue.pop_back();
-
-      // Skip outdated requests
-      if (Request.Version != DocVersions.find(Request.File)->second) {
-        Output.log("Version for " + Twine(Request.File) +
-                   " in request is outdated, skipping request\n");
-        continue;
-      }
-    } // unlock RequestLock
-
-    handleRequest(Request.Type, Request.File);
-  }
-}
-
-void ASTManager::queueOrRun(ASTManagerRequestType RequestType, StringRef File) {
-  if (RunSynchronously) {
-    handleRequest(RequestType, File);
-    return;
-  }
-
-  std::lock_guard<std::mutex> Guard(RequestLock);
-  // We increment the version of the added document immediately and schedule
-  // the requested operation to be run on a worker thread
-  DocVersion version = ++DocVersions[File];
-  RequestQueue.push_back(ASTManagerRequest(RequestType, File, version));
-  ClangRequestCV.notify_one();
-}
-
-void ASTManager::handleRequest(ASTManagerRequestType RequestType,
-                               StringRef File) {
-  switch (RequestType) {
-  case ASTManagerRequestType::ParseAndPublishDiagnostics:
-    parseFileAndPublishDiagnostics(File);
-    break;
-  case ASTManagerRequestType::RemoveDocData: {
-    std::lock_guard<std::mutex> Lock(ClangObjectLock);
-    auto DocDataIt = DocDatas.find(File);
-    // We could get the remove request before parsing for the document is
-    // started, just do nothing in that case, parsing request will be discarded
-    // because it has a lower version value
-    if (DocDataIt == DocDatas.end())
-      return;
-    DocDatas.erase(DocDataIt);
-    break;
-  } // unlock ClangObjectLock
-  }
-}
-
-void ASTManager::parseFileAndPublishDiagnostics(StringRef File) {
-  std::unique_lock<std::mutex> ClangObjectLockGuard(ClangObjectLock);
-
-  auto &DocData = DocDatas[File];
-  ASTUnit *Unit = DocData.getAST();
-  if (!Unit) {
-    auto newAST = createASTUnitForFile(File, this->Store);
-    Unit = newAST.get();
-
-    DocData.setAST(std::move(newAST));
-  } else {
-    // Do a reparse if this wasn't the first parse.
-    // FIXME: This might have the wrong working directory if it changed in the
-    // meantime.
-    Unit->Reparse(PCHs, getRemappedFiles(this->Store));
-  }
-
-  if (!Unit)
-    return;
-
-  // Send the diagnotics to the editor.
-  // FIXME: If the diagnostic comes from a different file, do we want to
-  // show them all? Right now we drop everything not coming from the
-  // main file.
-  std::string Diagnostics;
-  DocData::DiagnosticToReplacementMap LocalFixIts; // Temporary storage
-  for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
-                                     DEnd = Unit->stored_diag_end();
-       D != DEnd; ++D) {
-    if (!D->getLocation().isValid() ||
-        !D->getLocation().getManager().isInMainFile(D->getLocation()))
-      continue;
-    Position P;
-    P.line = D->getLocation().getSpellingLineNumber() - 1;
-    P.character = D->getLocation().getSpellingColumnNumber();
-    Range R = {P, P};
-    Diagnostics +=
-        R"({"range":)" + Range::unparse(R) +
-        R"(,"severity":)" + std::to_string(getSeverity(D->getLevel())) +
-        R"(,"message":")" + llvm::yaml::escape(D->getMessage()) +
-        R"("},)";
-
-    // We convert to Replacements to become independent of the SourceManager.
-    clangd::Diagnostic Diag = {R, getSeverity(D->getLevel()), D->getMessage()};
-    auto &FixItsForDiagnostic = LocalFixIts[Diag];
-    for (const FixItHint &Fix : D->getFixIts()) {
-      FixItsForDiagnostic.push_back(clang::tooling::Replacement(
-          Unit->getSourceManager(), Fix.RemoveRange, Fix.CodeToInsert));
-    }
-  }
-
-  // Put FixIts into place.
-  DocData.cacheFixIts(std::move(LocalFixIts));
-
-  ClangObjectLockGuard.unlock();
-  // No accesses to clang objects are allowed after this point.
-
-  // Publish diagnostics.
-  if (!Diagnostics.empty())
-    Diagnostics.pop_back(); // Drop trailing comma.
-  Output.writeMessage(
-      R"({"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":")" +
-      URI::fromFile(File).uri + R"(","diagnostics":[)" + Diagnostics + R"(]}})");
-}
-
-ASTManager::~ASTManager() {
-  {
-    std::lock_guard<std::mutex> Guard(RequestLock);
-    // Wake up the clang worker thread, then exit.
-    Done = true;
-    ClangRequestCV.notify_one();
-  } // unlock DocDataLock
-  ClangWorker.join();
-}
-
-void ASTManager::onDocumentAdd(StringRef File) {
-  queueOrRun(ASTManagerRequestType::ParseAndPublishDiagnostics, File);
-}
-
-void ASTManager::onDocumentRemove(StringRef File) {
-  queueOrRun(ASTManagerRequestType::RemoveDocData, File);
-}
-
-tooling::CompilationDatabase *
-ASTManager::getOrCreateCompilationDatabaseForFile(StringRef File) {
-  namespace path = llvm::sys::path;
-
-  assert((path::is_absolute(File, path::Style::posix) ||
-          path::is_absolute(File, path::Style::windows)) &&
-         "path must be absolute");
-
-  for (auto Path = path::parent_path(File); !Path.empty();
-       Path = path::parent_path(Path)) {
-
-    auto CachedIt = CompilationDatabases.find(Path);
-    if (CachedIt != CompilationDatabases.end())
-      return CachedIt->second.get();
-    std::string Error;
-    auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error);
-    if (!CDB) {
-      if (!Error.empty()) {
-        Output.log("Error when trying to load compilation database from " +
-                   Twine(Path) + ": " + Twine(Error) + "\n");
-      }
-      continue;
-    }
-
-    // TODO(ibiryukov): Invalidate cached compilation databases on changes
-    auto result = CDB.get();
-    CompilationDatabases.insert(std::make_pair(Path, std::move(CDB)));
-    return result;
-  }
-
-  Output.log("Failed to find compilation database for " + Twine(File) + "\n");
-  return nullptr;
-}
-
-std::unique_ptr<clang::ASTUnit>
-ASTManager::createASTUnitForFile(StringRef File, const DocumentStore &Docs) {
-  tooling::CompilationDatabase *CDB =
-      getOrCreateCompilationDatabaseForFile(File);
-
-  std::vector<tooling::CompileCommand> Commands;
-
-  if (CDB) {
-    Commands = CDB->getCompileCommands(File);
-    // chdir. This is thread hostile.
-    if (!Commands.empty())
-      llvm::sys::fs::set_current_path(Commands.front().Directory);
-  }
-  if (Commands.empty()) {
-    // Add a fake command line if we know nothing.
-    Commands.push_back(tooling::CompileCommand(
-        llvm::sys::path::parent_path(File), llvm::sys::path::filename(File),
-        {"clang", "-fsyntax-only", File.str()}, ""));
-  }
-
-  // Inject the resource dir.
-  // FIXME: Don't overwrite it if it's already there.
-  static int Dummy; // Just an address in this process.
-  std::string ResourceDir =
-      CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);
-  Commands.front().CommandLine.push_back("-resource-dir=" + ResourceDir);
-
-  IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
-      CompilerInstance::createDiagnostics(new DiagnosticOptions);
-
-  std::vector<const char *> ArgStrs;
-  for (const auto &S : Commands.front().CommandLine)
-    ArgStrs.push_back(S.c_str());
-
-  auto ArgP = &*ArgStrs.begin();
-  return std::unique_ptr<clang::ASTUnit>(ASTUnit::LoadFromCommandLine(
-      ArgP, ArgP + ArgStrs.size(), PCHs, Diags, ResourceDir,
-      /*OnlyLocalDecls=*/false, /*CaptureDiagnostics=*/true,
-      getRemappedFiles(Docs),
-      /*RemappedFilesKeepOriginalName=*/true,
-      /*PrecompilePreambleAfterNParses=*/1, /*TUKind=*/TU_Complete,
-      /*CacheCodeCompletionResults=*/true,
-      /*IncludeBriefCommentsInCodeCompletion=*/true,
-      /*AllowPCHWithCompilerErrors=*/true));
-}
-
-std::vector<clang::tooling::Replacement>
-ASTManager::getFixIts(StringRef File, const clangd::Diagnostic &D) {
-  // TODO(ibiryukov): the FixIts should be available immediately
-  // even when parsing is being run on a worker thread
-  std::lock_guard<std::mutex> Guard(ClangObjectLock);
-  return DocDatas[File].getFixIts(D);
-}
-
-namespace {
-class CompletionItemsCollector : public CodeCompleteConsumer {
-  std::vector<CompletionItem> *Items;
-  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
-  CodeCompletionTUInfo CCTUInfo;
-
-public:
-  CompletionItemsCollector(std::vector<CompletionItem> *Items,
-                           const CodeCompleteOptions &CodeCompleteOpts)
-      : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
-        Items(Items),
-        Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
-        CCTUInfo(Allocator) {}
-
-  void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
-                                  CodeCompletionResult *Results,
-                                  unsigned NumResults) override {
-    for (unsigned I = 0; I != NumResults; ++I) {
-      CodeCompletionResult &Result = Results[I];
-      CodeCompletionString *CCS = Result.CreateCodeCompletionString(
-          S, Context, *Allocator, CCTUInfo,
-          CodeCompleteOpts.IncludeBriefComments);
-      if (CCS) {
-        CompletionItem Item;
-        assert(CCS->getTypedText());
-        Item.label = CCS->getTypedText();
-        Item.kind = getKind(Result.CursorKind);
-        if (CCS->getBriefComment())
-          Item.documentation = CCS->getBriefComment();
-        Items->push_back(std::move(Item));
-      }
-    }
-  }
-
-  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
-
-  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
-};
-
-} // namespace
-
-std::vector<CompletionItem>
-ASTManager::codeComplete(StringRef File, unsigned Line, unsigned Column) {
-  CodeCompleteOptions CCO;
-  CCO.IncludeBriefComments = 1;
-  // This is where code completion stores dirty buffers. Need to free after
-  // completion.
-  SmallVector<const llvm::MemoryBuffer *, 4> OwnedBuffers;
-  SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
-  IntrusiveRefCntPtr<DiagnosticsEngine> DiagEngine(
-      new DiagnosticsEngine(new DiagnosticIDs, new DiagnosticOptions));
-  std::vector<CompletionItem> Items;
-  CompletionItemsCollector Collector(&Items, CCO);
-
-  std::lock_guard<std::mutex> Guard(ClangObjectLock);
-  auto &DocData = DocDatas[File];
-  auto Unit = DocData.getAST();
-  if (!Unit) {
-    auto newAST = createASTUnitForFile(File, this->Store);
-    Unit = newAST.get();
-    DocData.setAST(std::move(newAST));
-  }
-  if (!Unit)
-    return {};
-  IntrusiveRefCntPtr<SourceManager> SourceMgr(
-      new SourceManager(*DiagEngine, Unit->getFileManager()));
-  // CodeComplete seems to require fresh LangOptions.
-  LangOptions LangOpts = Unit->getLangOpts();
-  // The language server protocol uses zero-based line and column numbers.
-  // The clang code completion uses one-based numbers.
-  Unit->CodeComplete(File, Line + 1, Column + 1, getRemappedFiles(this->Store),
-                     CCO.IncludeMacros, CCO.IncludeCodePatterns,
-                     CCO.IncludeBriefComments, Collector, PCHs, *DiagEngine,
-                     LangOpts, *SourceMgr, Unit->getFileManager(),
-                     StoredDiagnostics, OwnedBuffers);
-  for (const llvm::MemoryBuffer *Buffer : OwnedBuffers)
-    delete Buffer;
-  return Items;
-}

Removed: clang-tools-extra/trunk/clangd/ASTManager.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ASTManager.h?rev=303150&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/ASTManager.h (original)
+++ clang-tools-extra/trunk/clangd/ASTManager.h (removed)
@@ -1,162 +0,0 @@
-//===--- ASTManager.h - Clang AST manager -----------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTMANAGER_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTMANAGER_H
-
-#include "DocumentStore.h"
-#include "JSONRPCDispatcher.h"
-#include "Protocol.h"
-#include "clang/Tooling/Core/Replacement.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include <condition_variable>
-#include <deque>
-#include <thread>
-
-namespace clang {
-class ASTUnit;
-class DiagnosticsEngine;
-class PCHContainerOperations;
-namespace tooling {
-class CompilationDatabase;
-} // namespace tooling
-
-namespace clangd {
-
-/// Using 'unsigned' here to avoid undefined behaviour on overflow.
-typedef unsigned DocVersion;
-
-/// Stores ASTUnit and FixIts map for an opened document.
-class DocData {
-public:
-  typedef std::map<clangd::Diagnostic, std::vector<clang::tooling::Replacement>>
-      DiagnosticToReplacementMap;
-
-public:
-  void setAST(std::unique_ptr<ASTUnit> AST);
-  ASTUnit *getAST() const;
-
-  void cacheFixIts(DiagnosticToReplacementMap FixIts);
-  std::vector<clang::tooling::Replacement>
-  getFixIts(const clangd::Diagnostic &D) const;
-
-private:
-  std::unique_ptr<ASTUnit> AST;
-  DiagnosticToReplacementMap FixIts;
-};
-
-enum class ASTManagerRequestType { ParseAndPublishDiagnostics, RemoveDocData };
-
-/// A request to the worker thread
-class ASTManagerRequest {
-public:
-  ASTManagerRequest() = default;
-  ASTManagerRequest(ASTManagerRequestType Type, std::string File,
-                    DocVersion Version);
-
-  ASTManagerRequestType Type;
-  std::string File;
-  DocVersion Version;
-};
-
-class ASTManager : public DocumentStoreListener {
-public:
-  ASTManager(JSONOutput &Output, DocumentStore &Store, bool RunSynchronously);
-  ~ASTManager() override;
-
-  void onDocumentAdd(StringRef File) override;
-  void onDocumentRemove(StringRef File) override;
-
-  /// Get code completions at a specified \p Line and \p Column in \p File.
-  ///
-  /// This function is thread-safe and returns completion items that own the
-  /// data they contain.
-  std::vector<CompletionItem> codeComplete(StringRef File, unsigned Line,
-                                           unsigned Column);
-
-  /// Get the fixes associated with a certain diagnostic in a specified file as
-  /// replacements.
-  ///
-  /// This function is thread-safe. It returns a copy to avoid handing out
-  /// references to unguarded data.
-  std::vector<clang::tooling::Replacement>
-  getFixIts(StringRef File, const clangd::Diagnostic &D);
-
-  DocumentStore &getStore() const { return Store; }
-
-private:
-  JSONOutput &Output;
-  DocumentStore &Store;
-
-  // Set to true if requests should block instead of being processed
-  // asynchronously.
-  bool RunSynchronously;
-
-  /// Loads a compilation database for File. May return nullptr if it fails. The
-  /// database is cached for subsequent accesses.
-  clang::tooling::CompilationDatabase *
-  getOrCreateCompilationDatabaseForFile(StringRef File);
-  // Creates a new ASTUnit for the document at File.
-  // FIXME: This calls chdir internally, which is thread unsafe.
-  std::unique_ptr<clang::ASTUnit>
-  createASTUnitForFile(StringRef File, const DocumentStore &Docs);
-
-  /// If RunSynchronously is false, queues the request to be run on the worker
-  /// thread.
-  /// If RunSynchronously is true, runs the request handler immediately on the
-  /// main thread.
-  void queueOrRun(ASTManagerRequestType RequestType, StringRef File);
-
-  void runWorker();
-  void handleRequest(ASTManagerRequestType RequestType, StringRef File);
-
-  /// Parses files and publishes diagnostics.
-  /// This function is called on the worker thread in asynchronous mode and
-  /// on the main thread in synchronous mode.
-  void parseFileAndPublishDiagnostics(StringRef File);
-
-  /// Caches compilation databases loaded from directories(keys are directories).
-  llvm::StringMap<std::unique_ptr<clang::tooling::CompilationDatabase>>
-      CompilationDatabases;
-
-  /// Clang objects.
-  /// A map from filenames to DocData structures that store ASTUnit and Fixits for
-  /// the files. The ASTUnits are used for generating diagnostics and fix-it-s
-  /// asynchronously by the worker thread and synchronously for code completion.
-  llvm::StringMap<DocData> DocDatas;
-  std::shared_ptr<clang::PCHContainerOperations> PCHs;
-  /// A lock for access to the DocDatas, CompilationDatabases and PCHs.
-  std::mutex ClangObjectLock;
-
-  /// Stores latest versions of the tracked documents to discard outdated requests.
-  /// Guarded by RequestLock.
-  /// TODO(ibiryukov): the entries are neved deleted from this map.
-  llvm::StringMap<DocVersion> DocVersions;
-
-  /// A LIFO queue of requests. Note that requests are discarded if the `version`
-  /// field is not equal to the one stored inside DocVersions.
-  /// TODO(krasimir): code completion should always have priority over parsing
-  /// for diagnostics.
-  std::deque<ASTManagerRequest> RequestQueue;
-  /// Setting Done to true will make the worker thread terminate.
-  bool Done = false;
-  /// Condition variable to wake up the worker thread.
-  std::condition_variable ClangRequestCV;
-  /// Lock for accesses to RequestQueue, DocVersions and Done.
-  std::mutex RequestLock;
-
-  /// We run parsing on a separate thread. This thread looks into RequestQueue to
-  /// find requests to handle and terminates when Done is set to true.
-  std::thread ClangWorker;
-};
-
-} // namespace clangd
-} // namespace clang
-
-#endif

Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=303151&r1=303150&r2=303151&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clangd/CMakeLists.txt Tue May 16 04:38:59 2017
@@ -1,6 +1,11 @@
 add_clang_executable(clangd
-  ASTManager.cpp
+  ClangdLSPServer.cpp
   ClangdMain.cpp
+  ClangdServer.cpp
+  ClangdUnit.cpp
+  ClangdUnitStore.cpp
+  DraftStore.cpp
+  GlobalCompilationDatabase.cpp
   JSONRPCDispatcher.cpp
   Protocol.cpp
   ProtocolHandlers.cpp

Copied: clang-tools-extra/trunk/clangd/ClangdLSPServer.h (from r303093, clang-tools-extra/trunk/clangd/ClangdLSPServer.h)
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.h?p2=clang-tools-extra/trunk/clangd/ClangdLSPServer.h&p1=clang-tools-extra/trunk/clangd/ClangdLSPServer.h&r1=303093&r2=303151&rev=303151&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.h Tue May 16 04:38:59 2017
@@ -64,13 +64,16 @@ private:
                           std::vector<DiagWithFixIts> Diagnostics);
 
   JSONOutput &Out;
-  ClangdServer Server;
 
   std::mutex FixItsMutex;
   typedef std::map<clangd::Diagnostic, std::vector<clang::tooling::Replacement>>
       DiagnosticToReplacementMap;
   /// Caches FixIts per file and diagnostics
   llvm::StringMap<DiagnosticToReplacementMap> FixItsMap;
+  // Server must be the last member of the class to allow its destructor to exit
+  // the worker thread that may otherwise run an async callback on partially
+  // destructed instance of ClangdLSPServer.
+  ClangdServer Server;
 };
 
 } // namespace clangd

Modified: clang-tools-extra/trunk/clangd/ClangdMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdMain.cpp?rev=303151&r1=303150&r2=303151&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdMain.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdMain.cpp Tue May 16 04:38:59 2017
@@ -7,15 +7,19 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ASTManager.h"
-#include "DocumentStore.h"
 #include "JSONRPCDispatcher.h"
+#include "ClangdLSPServer.h"
+#include "Protocol.h"
 #include "ProtocolHandlers.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Program.h"
+
 #include <iostream>
+#include <memory>
 #include <string>
+
+using namespace clang;
 using namespace clang::clangd;
 
 static llvm::cl::opt<bool>
@@ -34,9 +38,7 @@ int main(int argc, char *argv[]) {
 
   // Set up a document store and intialize all the method handlers for JSONRPC
   // dispatching.
-  DocumentStore Store;
-  ASTManager AST(Out, Store, RunSynchronously);
-  Store.addListener(&AST);
+  ClangdLSPServer LSPServer(Out, RunSynchronously);
   JSONRPCDispatcher Dispatcher(llvm::make_unique<Handler>(Out));
   Dispatcher.registerHandler("initialize",
                              llvm::make_unique<InitializeHandler>(Out));
@@ -45,26 +47,26 @@ int main(int argc, char *argv[]) {
   Dispatcher.registerHandler("shutdown", std::move(ShutdownPtr));
   Dispatcher.registerHandler(
       "textDocument/didOpen",
-      llvm::make_unique<TextDocumentDidOpenHandler>(Out, Store));
+      llvm::make_unique<TextDocumentDidOpenHandler>(Out, LSPServer));
   Dispatcher.registerHandler(
       "textDocument/didClose",
-      llvm::make_unique<TextDocumentDidCloseHandler>(Out, Store));
+      llvm::make_unique<TextDocumentDidCloseHandler>(Out, LSPServer));
   Dispatcher.registerHandler(
       "textDocument/didChange",
-      llvm::make_unique<TextDocumentDidChangeHandler>(Out, Store));
+      llvm::make_unique<TextDocumentDidChangeHandler>(Out, LSPServer));
   Dispatcher.registerHandler(
       "textDocument/rangeFormatting",
-      llvm::make_unique<TextDocumentRangeFormattingHandler>(Out, Store));
+      llvm::make_unique<TextDocumentRangeFormattingHandler>(Out, LSPServer));
   Dispatcher.registerHandler(
       "textDocument/onTypeFormatting",
-      llvm::make_unique<TextDocumentOnTypeFormattingHandler>(Out, Store));
+      llvm::make_unique<TextDocumentOnTypeFormattingHandler>(Out, LSPServer));
   Dispatcher.registerHandler(
       "textDocument/formatting",
-      llvm::make_unique<TextDocumentFormattingHandler>(Out, Store));
+      llvm::make_unique<TextDocumentFormattingHandler>(Out, LSPServer));
   Dispatcher.registerHandler("textDocument/codeAction",
-                             llvm::make_unique<CodeActionHandler>(Out, AST));
+                             llvm::make_unique<CodeActionHandler>(Out, LSPServer));
   Dispatcher.registerHandler("textDocument/completion",
-                             llvm::make_unique<CompletionHandler>(Out, AST));
+                             llvm::make_unique<CompletionHandler>(Out, LSPServer));
 
   while (std::cin.good()) {
     // A Language Server Protocol message starts with a HTTP header, delimited

Removed: clang-tools-extra/trunk/clangd/DocumentStore.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/DocumentStore.h?rev=303150&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/DocumentStore.h (original)
+++ clang-tools-extra/trunk/clangd/DocumentStore.h (removed)
@@ -1,86 +0,0 @@
-//===--- DocumentStore.h - File contents container --------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DOCUMENTSTORE_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DOCUMENTSTORE_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/StringMap.h"
-#include <mutex>
-#include <string>
-#include <vector>
-
-namespace clang {
-namespace clangd {
-class DocumentStore;
-
-struct DocumentStoreListener {
-  virtual ~DocumentStoreListener() = default;
-  virtual void onDocumentAdd(StringRef File) {}
-  virtual void onDocumentRemove(StringRef File) {}
-};
-
-/// A container for files opened in a workspace, addressed by File. The contents
-/// are owned by the DocumentStore.
-class DocumentStore {
-public:
-  /// Add a document to the store. Overwrites existing contents.
-  void addDocument(StringRef File, StringRef Text) {
-    {
-      std::lock_guard<std::mutex> Guard(DocsMutex);
-      Docs[File] = Text;
-    }
-    for (const auto &Listener : Listeners)
-      Listener->onDocumentAdd(File);
-  }
-  /// Delete a document from the store.
-  void removeDocument(StringRef File) {
-    {
-      std::lock_guard<std::mutex> Guard(DocsMutex);
-      Docs.erase(File);
-    }
-    for (const auto &Listener : Listeners)
-      Listener->onDocumentRemove(File);
-  }
-  /// Retrieve a document from the store. Empty string if it's unknown.
-  ///
-  /// This function is thread-safe. It returns a copy to avoid handing out
-  /// references to unguarded data.
-  std::string getDocument(StringRef File) const {
-    // FIXME: This could be a reader lock.
-    std::lock_guard<std::mutex> Guard(DocsMutex);
-    return Docs.lookup(File);
-  }
-
-  /// Add a listener. Does not take ownership.
-  void addListener(DocumentStoreListener *DSL) { Listeners.push_back(DSL); }
-
-  /// Get name and constents of all documents in this store.
-  ///
-  /// This function is thread-safe. It returns a copies to avoid handing out
-  /// references to unguarded data.
-  std::vector<std::pair<std::string, std::string>> getAllDocuments() const {
-    std::vector<std::pair<std::string, std::string>> AllDocs;
-    std::lock_guard<std::mutex> Guard(DocsMutex);
-    for (const auto &P : Docs)
-      AllDocs.emplace_back(P.first(), P.second);
-    return AllDocs;
-  }
-
-private:
-  llvm::StringMap<std::string> Docs;
-  std::vector<DocumentStoreListener *> Listeners;
-
-  mutable std::mutex DocsMutex;
-};
-
-} // namespace clangd
-} // namespace clang
-
-#endif

Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp?rev=303151&r1=303150&r2=303151&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp (original)
+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp Tue May 16 04:38:59 2017
@@ -8,9 +8,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "ProtocolHandlers.h"
-#include "ASTManager.h"
-#include "DocumentStore.h"
+#include "ClangdServer.h"
+#include "DraftStore.h"
 #include "clang/Format/Format.h"
+#include "ClangdLSPServer.h"
 using namespace clang;
 using namespace clangd;
 
@@ -21,7 +22,7 @@ void TextDocumentDidOpenHandler::handleN
     Output.log("Failed to decode DidOpenTextDocumentParams!\n");
     return;
   }
-  Store.addDocument(DOTDP->textDocument.uri.file, DOTDP->textDocument.text);
+  AST.openDocument(DOTDP->textDocument.uri.file, DOTDP->textDocument.text);
 }
 
 void TextDocumentDidCloseHandler::handleNotification(
@@ -32,7 +33,7 @@ void TextDocumentDidCloseHandler::handle
     return;
   }
 
-  Store.removeDocument(DCTDP->textDocument.uri.file);
+  AST.closeDocument(DCTDP->textDocument.uri.file);
 }
 
 void TextDocumentDidChangeHandler::handleNotification(
@@ -43,7 +44,7 @@ void TextDocumentDidChangeHandler::handl
     return;
   }
   // We only support full syncing right now.
-  Store.addDocument(DCTDP->textDocument.uri.file, DCTDP->contentChanges[0].text);
+  AST.openDocument(DCTDP->textDocument.uri.file, DCTDP->contentChanges[0].text);
 }
 
 /// Turn a [line, column] pair into an offset in Code.
@@ -110,7 +111,7 @@ void TextDocumentRangeFormattingHandler:
     return;
   }
 
-  std::string Code = Store.getDocument(DRFP->textDocument.uri.file);
+  std::string Code = AST.getDocument(DRFP->textDocument.uri.file);
 
   size_t Begin = positionToOffset(Code, DRFP->range.start);
   size_t Len = positionToOffset(Code, DRFP->range.end) - Begin;
@@ -129,7 +130,7 @@ void TextDocumentOnTypeFormattingHandler
 
   // Look for the previous opening brace from the character position and format
   // starting from there.
-  std::string Code = Store.getDocument(DOTFP->textDocument.uri.file);
+  std::string Code = AST.getDocument(DOTFP->textDocument.uri.file);
   size_t CursorPos = positionToOffset(Code, DOTFP->position);
   size_t PreviousLBracePos = StringRef(Code).find_last_of('{', CursorPos);
   if (PreviousLBracePos == StringRef::npos)
@@ -149,7 +150,7 @@ void TextDocumentFormattingHandler::hand
   }
 
   // Format everything.
-  std::string Code = Store.getDocument(DFP->textDocument.uri.file);
+  std::string Code = AST.getDocument(DFP->textDocument.uri.file);
   writeMessage(formatCode(Code, DFP->textDocument.uri.file,
                           {clang::tooling::Range(0, Code.size())}, ID));
 }
@@ -164,7 +165,7 @@ void CodeActionHandler::handleMethod(llv
 
   // We provide a code action for each diagnostic at the requested location
   // which has FixIts available.
-  std::string Code = AST.getStore().getDocument(CAP->textDocument.uri.file);
+  std::string Code = AST.getDocument(CAP->textDocument.uri.file);
   std::string Commands;
   for (Diagnostic &D : CAP->context.diagnostics) {
     std::vector<clang::tooling::Replacement> Fixes = AST.getFixIts(CAP->textDocument.uri.file, D);
@@ -195,8 +196,8 @@ void CompletionHandler::handleMethod(llv
     return;
   }
 
-  auto Items = AST.codeComplete(TDPP->textDocument.uri.file, TDPP->position.line,
-                                TDPP->position.character);
+  auto Items = AST.codeComplete(TDPP->textDocument.uri.file, Position{TDPP->position.line,
+          TDPP->position.character});
   std::string Completions;
   for (const auto &Item : Items) {
     Completions += CompletionItem::unparse(Item);

Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.h?rev=303151&r1=303150&r2=303151&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ProtocolHandlers.h (original)
+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.h Tue May 16 04:38:59 2017
@@ -22,8 +22,8 @@
 
 namespace clang {
 namespace clangd {
-class ASTManager;
-class DocumentStore;
+class ClangdLSPServer;
+class ClangdLSPServer;
 
 struct InitializeHandler : Handler {
   InitializeHandler(JSONOutput &Output) : Handler(Output) {}
@@ -56,83 +56,83 @@ private:
 };
 
 struct TextDocumentDidOpenHandler : Handler {
-  TextDocumentDidOpenHandler(JSONOutput &Output, DocumentStore &Store)
-      : Handler(Output), Store(Store) {}
+  TextDocumentDidOpenHandler(JSONOutput &Output, ClangdLSPServer &AST)
+      : Handler(Output), AST(AST) {}
 
   void handleNotification(llvm::yaml::MappingNode *Params) override;
 
 private:
-  DocumentStore &Store;
+  ClangdLSPServer &AST;
 };
 
 struct TextDocumentDidChangeHandler : Handler {
-  TextDocumentDidChangeHandler(JSONOutput &Output, DocumentStore &Store)
-      : Handler(Output), Store(Store) {}
+  TextDocumentDidChangeHandler(JSONOutput &Output, ClangdLSPServer &AST)
+      : Handler(Output), AST(AST) {}
 
   void handleNotification(llvm::yaml::MappingNode *Params) override;
 
 private:
-  DocumentStore &Store;
+  ClangdLSPServer &AST;
 };
 
 struct TextDocumentDidCloseHandler : Handler {
-  TextDocumentDidCloseHandler(JSONOutput &Output, DocumentStore &Store)
-      : Handler(Output), Store(Store) {}
+  TextDocumentDidCloseHandler(JSONOutput &Output, ClangdLSPServer &AST)
+      : Handler(Output), AST(AST) {}
 
   void handleNotification(llvm::yaml::MappingNode *Params) override;
 
 private:
-  DocumentStore &Store;
+  ClangdLSPServer &AST;
 };
 
 struct TextDocumentOnTypeFormattingHandler : Handler {
-  TextDocumentOnTypeFormattingHandler(JSONOutput &Output, DocumentStore &Store)
-      : Handler(Output), Store(Store) {}
+  TextDocumentOnTypeFormattingHandler(JSONOutput &Output, ClangdLSPServer &AST)
+      : Handler(Output), AST(AST) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;
 
 private:
-  DocumentStore &Store;
+  ClangdLSPServer &AST;
 };
 
 struct TextDocumentRangeFormattingHandler : Handler {
-  TextDocumentRangeFormattingHandler(JSONOutput &Output, DocumentStore &Store)
-      : Handler(Output), Store(Store) {}
+  TextDocumentRangeFormattingHandler(JSONOutput &Output, ClangdLSPServer &AST)
+      : Handler(Output), AST(AST) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;
 
 private:
-  DocumentStore &Store;
+  ClangdLSPServer &AST;
 };
 
 struct TextDocumentFormattingHandler : Handler {
-  TextDocumentFormattingHandler(JSONOutput &Output, DocumentStore &Store)
-      : Handler(Output), Store(Store) {}
+  TextDocumentFormattingHandler(JSONOutput &Output, ClangdLSPServer &AST)
+      : Handler(Output), AST(AST) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;
 
 private:
-  DocumentStore &Store;
+  ClangdLSPServer &AST;
 };
 
 struct CodeActionHandler : Handler {
-  CodeActionHandler(JSONOutput &Output, ASTManager &AST)
+  CodeActionHandler(JSONOutput &Output, ClangdLSPServer &AST)
       : Handler(Output), AST(AST) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;
 
 private:
-  ASTManager &AST;
+  ClangdLSPServer &AST;
 };
 
 struct CompletionHandler : Handler {
-  CompletionHandler(JSONOutput &Output, ASTManager &AST)
+  CompletionHandler(JSONOutput &Output, ClangdLSPServer &AST)
       : Handler(Output), AST(AST) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;
 
  private:
-  ASTManager &AST;
+  ClangdLSPServer &AST;
 };
 
 } // namespace clangd

Modified: clang-tools-extra/trunk/test/clangd/formatting.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/formatting.test?rev=303151&r1=303150&r2=303151&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clangd/formatting.test (original)
+++ clang-tools-extra/trunk/test/clangd/formatting.test Tue May 16 04:38:59 2017
@@ -1,4 +1,4 @@
-# RUN: clangd < %s | FileCheck %s
+# RUN: clangd -run-synchronously < %s | FileCheck %s
 # It is absolutely vital that this file has CRLF line endings.
 #
 Content-Length: 125




More information about the cfe-commits mailing list