Index: clangd/CMakeLists.txt =================================================================== --- clangd/CMakeLists.txt +++ clangd/CMakeLists.txt @@ -9,8 +9,9 @@ ClangdUnitStore.cpp CodeComplete.cpp CodeCompletionStrings.cpp - Context.cpp + CompileArgsCache.cpp Compiler.cpp + Context.cpp DraftStore.cpp FuzzyMatch.cpp GlobalCompilationDatabase.cpp Index: clangd/ClangdServer.h =================================================================== --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -13,6 +13,7 @@ #include "ClangdUnit.h" #include "ClangdUnitStore.h" #include "CodeComplete.h" +#include "CompileArgsCache.h" #include "DraftStore.h" #include "Function.h" #include "GlobalCompilationDatabase.h" @@ -331,13 +332,12 @@ std::future scheduleReparseAndDiags(Context Ctx, PathRef File, VersionedDraft Contents, std::shared_ptr Resources, - Tagged> TaggedFS, - bool AllowCachedCompileFlags); + Tagged> TaggedFS); std::future scheduleCancelRebuild(Context Ctx, std::shared_ptr Resources); - GlobalCompilationDatabase &CDB; + CompileArgsCache CompileArgs; DiagnosticsConsumer &DiagConsumer; FileSystemProvider &FSProvider; DraftStore DraftMgr; @@ -352,7 +352,6 @@ // If present, a merged view of FileIdx and an external index. Read via Index. std::unique_ptr MergedIndex; CppFileCollection Units; - std::string ResourceDir; // If set, this represents the workspace path. llvm::Optional RootPath; std::shared_ptr PCHs; Index: clangd/ClangdServer.cpp =================================================================== --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -32,18 +32,6 @@ namespace { -tooling::CompileCommand getCompileCommand(GlobalCompilationDatabase &CDB, - PathRef File, PathRef ResourceDir) { - llvm::Optional C = CDB.getCompileCommand(File); - if (!C) // FIXME: Suppress diagnostics? Let the user know? - C = CDB.getFallbackCommand(File); - - // Inject the resource dir. - // FIXME: Don't overwrite it if it's already there. - C->CommandLine.push_back("-resource-dir=" + ResourceDir.str()); - return std::move(*C); -} - std::string getStandardResourceDir() { static int Dummy; // Just an address in this process. return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy); @@ -149,7 +137,9 @@ bool StorePreamblesInMemory, bool BuildDynamicSymbolIndex, SymbolIndex *StaticIdx, llvm::Optional ResourceDir) - : CDB(CDB), DiagConsumer(DiagConsumer), FSProvider(FSProvider), + : CompileArgs(CDB, + ResourceDir ? ResourceDir->str() : getStandardResourceDir()), + DiagConsumer(DiagConsumer), FSProvider(FSProvider), FileIdx(BuildDynamicSymbolIndex ? new FileIndex() : nullptr), // Pass a callback into `Units` to extract symbols from a newly parsed // file and rebuild the file index synchronously each time an AST is @@ -160,7 +150,6 @@ ? [this](const Context &Ctx, PathRef Path, ParsedAST *AST) { FileIdx->update(Ctx, Path, AST); } : ASTParsedCallback()), - ResourceDir(ResourceDir ? ResourceDir->str() : getStandardResourceDir()), PCHs(std::make_shared()), StorePreamblesInMemory(StorePreamblesInMemory), WorkScheduler(AsyncThreadsCount) { @@ -188,15 +177,16 @@ auto TaggedFS = FSProvider.getTaggedFileSystem(File); std::shared_ptr Resources = - Units.getOrCreateFile(File, ResourceDir, StorePreamblesInMemory, PCHs); + Units.getOrCreateFile(File, StorePreamblesInMemory, PCHs); return scheduleReparseAndDiags(std::move(Ctx), File, VersionedDraft{Version, Contents.str()}, - std::move(Resources), std::move(TaggedFS), - /*AllowCachedCompileFlags=*/true); + std::move(Resources), std::move(TaggedFS)); } std::future ClangdServer::removeDocument(Context Ctx, PathRef File) { DraftMgr.removeDraft(File); + CompileArgs.invalidate(File); + std::shared_ptr Resources = Units.removeIfPresent(File); return scheduleCancelRebuild(std::move(Ctx), std::move(Resources)); } @@ -206,12 +196,15 @@ assert(FileContents.Draft && "forceReparse() was called for non-added document"); + // forceReparse promises to request new compilation flags from CDB, so we + // remove any cahced flags. + CompileArgs.invalidate(File); + auto TaggedFS = FSProvider.getTaggedFileSystem(File); std::shared_ptr Resources = - Units.getOrCreateFile(File, ResourceDir, StorePreamblesInMemory, PCHs); + Units.getOrCreateFile(File, StorePreamblesInMemory, PCHs); return scheduleReparseAndDiags(std::move(Ctx), File, FileContents, - std::move(Resources), std::move(TaggedFS), - /*AllowCachedCompileFlags=*/false); + std::move(Resources), std::move(TaggedFS)); } std::future>> @@ -277,11 +270,7 @@ Path FileStr = File; // Copy PCHs to avoid accessing this->PCHs concurrently std::shared_ptr PCHs = this->PCHs; - - assert(Resources->getLastCommand() && - "CppFile is in inconsistent state, missing CompileCommand"); - tooling::CompileCommand CompileCommand = *Resources->getLastCommand(); - + tooling::CompileCommand CompileCommand = CompileArgs.getCompileCommand(File); // A task that will be run asynchronously. auto Task = // 'mutable' to reassign Preamble variable. @@ -332,12 +321,9 @@ "signatureHelp is called for non-added document", llvm::errc::invalid_argument); - assert(Resources->getLastCommand() && - "CppFile is in inconsistent state, missing CompileCommand"); - auto Preamble = Resources->getPossiblyStalePreamble(); auto Result = - clangd::signatureHelp(Ctx, File, *Resources->getLastCommand(), + clangd::signatureHelp(Ctx, File, CompileArgs.getCompileCommand(File), Preamble ? &Preamble->Preamble : nullptr, *OverridenContents, Pos, TaggedFS.Value, PCHs); return make_tagged(std::move(Result), TaggedFS.Tag); @@ -571,18 +557,11 @@ std::future ClangdServer::scheduleReparseAndDiags( Context Ctx, PathRef File, VersionedDraft Contents, std::shared_ptr Resources, - Tagged> TaggedFS, - bool AllowCachedCompileFlags) { - llvm::Optional ReusedCommand; - if (AllowCachedCompileFlags) - ReusedCommand = Resources->getLastCommand(); - tooling::CompileCommand Command = - ReusedCommand ? std::move(*ReusedCommand) - : getCompileCommand(CDB, File, ResourceDir); - - ParseInputs Inputs = {std::move(Command), std::move(TaggedFS.Value), - *std::move(Contents.Draft)}; + Tagged> TaggedFS) { assert(Contents.Draft && "Draft must have contents"); + ParseInputs Inputs = {CompileArgs.getCompileCommand(File), + std::move(TaggedFS.Value), *std::move(Contents.Draft)}; + UniqueFunction>(const Context &)> DeferredRebuild = Resources->deferRebuild(std::move(Inputs)); std::promise DonePromise; Index: clangd/ClangdUnit.h =================================================================== --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -216,14 +216,6 @@ /// always be non-null. std::shared_future> getAST() const; - /// Get the latest CompileCommand used to build this CppFile. Returns - /// llvm::None before first call to rebuild() or after calls to - /// cancelRebuild(). - // In practice we always call rebuild() when adding a CppFile to the - // CppFileCollection, and only `cancelRebuild()` after removing it. This means - // files in the CppFileCollection always have a compile command available. - llvm::Optional getLastCommand() const; - private: /// A helper guard that manages the state of CppFile during rebuild. class RebuildGuard { @@ -251,7 +243,6 @@ bool RebuildInProgress; /// Condition variable to indicate changes to RebuildInProgress. std::condition_variable RebuildCond; - llvm::Optional LastCommand; /// Promise and future for the latests AST. Fulfilled during rebuild. /// We use std::shared_ptr here because MVSC fails to compile non-copyable Index: clangd/ClangdUnit.cpp =================================================================== --- clangd/ClangdUnit.cpp +++ clangd/ClangdUnit.cpp @@ -455,7 +455,6 @@ this->ASTPromise = std::promise>(); this->ASTFuture = this->ASTPromise.get_future(); } - this->LastCommand = Inputs.CompileCommand; } // unlock Mutex. // Notify about changes to RebuildCounter. RebuildCond.notify_all(); @@ -636,11 +635,6 @@ return ASTFuture; } -llvm::Optional CppFile::getLastCommand() const { - std::lock_guard Lock(Mutex); - return LastCommand; -} - CppFile::RebuildGuard::RebuildGuard(CppFile &File, unsigned RequestRebuildCounter) : File(File), RequestRebuildCounter(RequestRebuildCounter) { Index: clangd/ClangdUnitStore.h =================================================================== --- clangd/ClangdUnitStore.h +++ clangd/ClangdUnitStore.h @@ -31,8 +31,7 @@ : ASTCallback(std::move(ASTCallback)) {} std::shared_ptr - getOrCreateFile(PathRef File, PathRef ResourceDir, - bool StorePreamblesInMemory, + getOrCreateFile(PathRef File, bool StorePreamblesInMemory, std::shared_ptr PCHs) { std::lock_guard Lock(Mutex); auto It = OpenedFiles.find(File);