Index: clangd/ClangdLSPServer.cpp =================================================================== --- clangd/ClangdLSPServer.cpp +++ clangd/ClangdLSPServer.cpp @@ -32,6 +32,12 @@ return Edits; } +Context destroyAndTakeContext(RequestContext Ctx) { + // FIXME(ibiryukov): We move the Context out of RequestContext. This works, + // but it's shaky. Maybe we should rather keep the RequestContext alive? + return std::move(Ctx.ctx()); +} + } // namespace void ClangdLSPServer::onInitialize(Ctx C, InitializeParams &Params) { @@ -82,7 +88,8 @@ if (Params.metadata && !Params.metadata->extraFlags.empty()) CDB.setExtraFlagsForFile(Params.textDocument.uri.file, std::move(Params.metadata->extraFlags)); - Server.addDocument(Params.textDocument.uri.file, Params.textDocument.text); + Server.addDocument(Params.textDocument.uri.file, Params.textDocument.text, + destroyAndTakeContext(std::move(C))); } void ClangdLSPServer::onDocumentDidChange(Ctx C, @@ -92,7 +99,8 @@ "can only apply one change at a time"); // We only support full syncing right now. Server.addDocument(Params.textDocument.uri.file, - Params.contentChanges[0].text); + Params.contentChanges[0].text, + destroyAndTakeContext(std::move(C))); } void ClangdLSPServer::onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) { @@ -145,7 +153,8 @@ void ClangdLSPServer::onDocumentDidClose(Ctx C, DidCloseTextDocumentParams &Params) { - Server.removeDocument(Params.textDocument.uri.file); + Server.removeDocument(Params.textDocument.uri.file, + destroyAndTakeContext(std::move(C))); } void ClangdLSPServer::onDocumentOnTypeFormatting( @@ -197,10 +206,9 @@ auto List = Server .codeComplete( Params.textDocument.uri.file, - Position{Params.position.line, Params.position.character}) - .get() // FIXME(ibiryukov): This could be made async if we - // had an API that would allow to attach callbacks to - // futures returned by ClangdServer. + Position{Params.position.line, Params.position.character}, + C.ctx()) + .get() // FIXME(ibiryukov): This could be made async. .Value; C.reply(List); } @@ -209,7 +217,7 @@ TextDocumentPositionParams &Params) { auto SignatureHelp = Server.signatureHelp( Params.textDocument.uri.file, - Position{Params.position.line, Params.position.character}); + Position{Params.position.line, Params.position.character}, C.ctx()); if (!SignatureHelp) return C.replyError(ErrorCode::InvalidParams, llvm::toString(SignatureHelp.takeError())); @@ -220,7 +228,7 @@ TextDocumentPositionParams &Params) { auto Items = Server.findDefinitions( Params.textDocument.uri.file, - Position{Params.position.line, Params.position.character}); + Position{Params.position.line, Params.position.character}, C.ctx()); if (!Items) return C.replyError(ErrorCode::InvalidParams, llvm::toString(Items.takeError())); @@ -239,10 +247,9 @@ const clangd::CodeCompleteOptions &CCOpts, llvm::Optional ResourceDir, llvm::Optional CompileCommandsDir) - : Out(Out), CDB(/*Logger=*/Out, std::move(CompileCommandsDir)), + : Out(Out), CDB(std::move(CompileCommandsDir)), Server(CDB, /*DiagConsumer=*/*this, FSProvider, AsyncThreadsCount, - StorePreamblesInMemory, CCOpts, - /*Logger=*/Out, ResourceDir) {} + StorePreamblesInMemory, CCOpts, ResourceDir) {} bool ClangdLSPServer::run(std::istream &In) { assert(!IsDone && "Run was called before"); Index: clangd/ClangdServer.h =================================================================== --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -36,8 +36,6 @@ namespace clangd { -class Logger; - /// Turn a [line, column] pair into an offset in Code. size_t positionToOffset(StringRef Code, Position P); @@ -204,14 +202,11 @@ /// /// \p StorePreamblesInMemory defines whether the Preambles generated by /// clangd are stored in-memory or on disk. - /// - /// Various messages are logged using \p Logger. ClangdServer(GlobalCompilationDatabase &CDB, DiagnosticsConsumer &DiagConsumer, FileSystemProvider &FSProvider, unsigned AsyncThreadsCount, bool StorePreamblesInMemory, const clangd::CodeCompleteOptions &CodeCompleteOpts, - clangd::Logger &Logger, llvm::Optional ResourceDir = llvm::None); /// Set the root path of the workspace. @@ -223,17 +218,17 @@ /// constructor will receive onDiagnosticsReady callback. /// \return A future that will become ready when the rebuild (including /// diagnostics) is finished. - std::future addDocument(PathRef File, StringRef Contents); + std::future addDocument(PathRef File, StringRef Contents, Context Ctx); /// Remove \p File from list of tracked files, schedule a request to free /// resources associated with it. /// \return A future that will become ready when the file is removed and all /// associated resources are freed. - std::future removeDocument(PathRef File); + std::future removeDocument(PathRef File, Context Ctx); /// Force \p File to be reparsed using the latest contents. /// Will also check if CompileCommand, provided by GlobalCompilationDatabase /// for \p File has changed. If it has, will remove currently stored Preamble /// and AST and rebuild them from scratch. - std::future forceReparse(PathRef File); + std::future forceReparse(PathRef File, Context Ctx); /// DEPRECATED. Please use a callback-based version, this API is deprecated /// and will soon be removed. @@ -252,15 +247,20 @@ /// This method should only be called for currently tracked files. However, it /// is safe to call removeDocument for \p File after this method returns, even /// while returned future is not yet ready. + /// + /// The callers are responsible for making sure \p Ctx stays alive until + /// std::future<> is ready (i.e. wait() or get() returns) std::future> - codeComplete(PathRef File, Position Pos, + codeComplete(PathRef File, Position Pos, Context &Ctx, llvm::Optional OverridenContents = llvm::None, IntrusiveRefCntPtr *UsedFS = nullptr); /// A version of `codeComplete` that runs \p Callback on the processing thread /// when codeComplete results become available. + /// The callers are responsible for making sure \p Ctx stays alive until \p + /// Callback is executed. void codeComplete(UniqueFunction)> Callback, - PathRef File, Position Pos, + PathRef File, Position Pos, Context &Ctx, llvm::Optional OverridenContents = llvm::None, IntrusiveRefCntPtr *UsedFS = nullptr); @@ -272,13 +272,13 @@ /// vfs::FileSystem used for signature help. This method should only be called /// for currently tracked files. llvm::Expected> - signatureHelp(PathRef File, Position Pos, + signatureHelp(PathRef File, Position Pos, Context &Ctx, llvm::Optional OverridenContents = llvm::None, IntrusiveRefCntPtr *UsedFS = nullptr); /// Get definition of symbol at a specified \p Line and \p Column in \p File. - llvm::Expected>> findDefinitions(PathRef File, - Position Pos); + llvm::Expected>> + findDefinitions(PathRef File, Position Pos, Context &Ctx); /// Helper function that returns a path to the corresponding source file when /// given a header file and vice versa. @@ -309,14 +309,13 @@ void onFileEvent(const DidChangeWatchedFilesParams &Params); private: - std::future - scheduleReparseAndDiags(PathRef File, VersionedDraft Contents, - std::shared_ptr Resources, - Tagged> TaggedFS); + std::future scheduleReparseAndDiags( + PathRef File, VersionedDraft Contents, std::shared_ptr Resources, + Tagged> TaggedFS, Context Ctx); - std::future scheduleCancelRebuild(std::shared_ptr Resources); + std::future scheduleCancelRebuild(std::shared_ptr Resources, + Context Ctx); - clangd::Logger &Logger; GlobalCompilationDatabase &CDB; DiagnosticsConsumer &DiagConsumer; FileSystemProvider &FSProvider; Index: clangd/ClangdServer.cpp =================================================================== --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -175,10 +175,8 @@ unsigned AsyncThreadsCount, bool StorePreamblesInMemory, const clangd::CodeCompleteOptions &CodeCompleteOpts, - clangd::Logger &Logger, llvm::Optional ResourceDir) - : Logger(Logger), CDB(CDB), DiagConsumer(DiagConsumer), - FSProvider(FSProvider), + : CDB(CDB), DiagConsumer(DiagConsumer), FSProvider(FSProvider), ResourceDir(ResourceDir ? ResourceDir->str() : getStandardResourceDir()), PCHs(std::make_shared()), StorePreamblesInMemory(StorePreamblesInMemory), @@ -191,41 +189,45 @@ this->RootPath = NewRootPath; } -std::future ClangdServer::addDocument(PathRef File, StringRef Contents) { +std::future ClangdServer::addDocument(PathRef File, StringRef Contents, + Context Ctx) { DocVersion Version = DraftMgr.updateDraft(File, Contents); auto TaggedFS = FSProvider.getTaggedFileSystem(File); std::shared_ptr Resources = Units.getOrCreateFile( - File, ResourceDir, CDB, StorePreamblesInMemory, PCHs, Logger); + File, ResourceDir, CDB, StorePreamblesInMemory, PCHs); return scheduleReparseAndDiags(File, VersionedDraft{Version, Contents.str()}, - std::move(Resources), std::move(TaggedFS)); + std::move(Resources), std::move(TaggedFS), + std::move(Ctx)); } -std::future ClangdServer::removeDocument(PathRef File) { +std::future ClangdServer::removeDocument(PathRef File, Context Ctx) { DraftMgr.removeDraft(File); std::shared_ptr Resources = Units.removeIfPresent(File); - return scheduleCancelRebuild(std::move(Resources)); + return scheduleCancelRebuild(std::move(Resources), std::move(Ctx)); } -std::future ClangdServer::forceReparse(PathRef File) { +std::future ClangdServer::forceReparse(PathRef File, Context Ctx) { auto FileContents = DraftMgr.getDraft(File); assert(FileContents.Draft && "forceReparse() was called for non-added document"); auto TaggedFS = FSProvider.getTaggedFileSystem(File); auto Recreated = Units.recreateFileIfCompileCommandChanged( - File, ResourceDir, CDB, StorePreamblesInMemory, PCHs, Logger); + File, ResourceDir, CDB, StorePreamblesInMemory, PCHs); - // Note that std::future from this cleanup action is ignored. - scheduleCancelRebuild(std::move(Recreated.RemovedFile)); + // Note that std::future from this cleanup action. + // FIXME(ibiryukov): We use a global context here, should not fork the action + // instead. + scheduleCancelRebuild(std::move(Recreated.RemovedFile), buildCtx()); // Schedule a reparse. return scheduleReparseAndDiags(File, std::move(FileContents), std::move(Recreated.FileInCollection), - std::move(TaggedFS)); + std::move(TaggedFS), std::move(Ctx)); } std::future> -ClangdServer::codeComplete(PathRef File, Position Pos, +ClangdServer::codeComplete(PathRef File, Position Pos, Context &Ctx, llvm::Optional OverridenContents, IntrusiveRefCntPtr *UsedFS) { using ResultType = Tagged; @@ -239,13 +241,13 @@ std::future ResultFuture = ResultPromise.get_future(); codeComplete(BindWithForward(Callback, std::move(ResultPromise)), File, Pos, - OverridenContents, UsedFS); + Ctx, OverridenContents, UsedFS); return ResultFuture; } void ClangdServer::codeComplete( UniqueFunction)> Callback, PathRef File, - Position Pos, llvm::Optional OverridenContents, + Position Pos, Context &Ctx, llvm::Optional OverridenContents, IntrusiveRefCntPtr *UsedFS) { using CallbackType = UniqueFunction)>; @@ -276,7 +278,7 @@ // A task that will be run asynchronously. auto Task = // 'mutable' to reassign Preamble variable. - [=](CallbackType Callback) mutable { + [=, &Ctx](CallbackType Callback) mutable { if (!Preamble) { // Maybe we built some preamble before processing this request. Preamble = Resources->getPossiblyStalePreamble(); @@ -287,7 +289,7 @@ CompletionList Result = clangd::codeComplete( File, Resources->getCompileCommand(), Preamble ? &Preamble->Preamble : nullptr, Contents, Pos, - TaggedFS.Value, PCHs, CodeCompleteOpts, Logger); + TaggedFS.Value, PCHs, CodeCompleteOpts, Ctx); Callback(make_tagged(std::move(Result), std::move(TaggedFS.Tag))); }; @@ -296,7 +298,7 @@ } llvm::Expected> -ClangdServer::signatureHelp(PathRef File, Position Pos, +ClangdServer::signatureHelp(PathRef File, Position Pos, Context &Ctx, llvm::Optional OverridenContents, IntrusiveRefCntPtr *UsedFS) { std::string DraftStorage; @@ -322,10 +324,10 @@ llvm::errc::invalid_argument); auto Preamble = Resources->getPossiblyStalePreamble(); - auto Result = clangd::signatureHelp(File, Resources->getCompileCommand(), - Preamble ? &Preamble->Preamble : nullptr, - *OverridenContents, Pos, TaggedFS.Value, - PCHs, Logger); + auto Result = + clangd::signatureHelp(File, Resources->getCompileCommand(), + Preamble ? &Preamble->Preamble : nullptr, + *OverridenContents, Pos, TaggedFS.Value, PCHs, Ctx); return make_tagged(std::move(Result), TaggedFS.Tag); } @@ -430,7 +432,7 @@ } llvm::Expected>> -ClangdServer::findDefinitions(PathRef File, Position Pos) { +ClangdServer::findDefinitions(PathRef File, Position Pos, Context &Ctx) { auto TaggedFS = FSProvider.getTaggedFileSystem(File); std::shared_ptr Resources = Units.getFile(File); @@ -440,10 +442,10 @@ llvm::errc::invalid_argument); std::vector Result; - Resources->getAST().get()->runUnderLock([Pos, &Result, this](ParsedAST *AST) { + Resources->getAST().get()->runUnderLock([Pos, &Result, &Ctx](ParsedAST *AST) { if (!AST) return; - Result = clangd::findDefinitions(*AST, Pos, Logger); + Result = clangd::findDefinitions(*AST, Pos, Ctx); }); return make_tagged(std::move(Result), TaggedFS.Tag); } @@ -509,10 +511,10 @@ std::future ClangdServer::scheduleReparseAndDiags( PathRef File, VersionedDraft Contents, std::shared_ptr Resources, - Tagged> TaggedFS) { + Tagged> TaggedFS, Context Ctx) { assert(Contents.Draft && "Draft must have contents"); - UniqueFunction>()> + UniqueFunction>(Context &)> DeferredRebuild = Resources->deferRebuild(*Contents.Draft, TaggedFS.Value); std::promise DonePromise; @@ -522,17 +524,17 @@ Path FileStr = File; VFSTag Tag = TaggedFS.Tag; auto ReparseAndPublishDiags = - [this, FileStr, Version, - Tag](UniqueFunction>()> - DeferredRebuild, - std::promise DonePromise) -> void { + [this, FileStr, Version, Tag]( + UniqueFunction>(Context &)> + DeferredRebuild, + std::promise DonePromise, Context Ctx) -> void { FulfillPromiseGuard Guard(DonePromise); auto CurrentVersion = DraftMgr.getVersion(FileStr); if (CurrentVersion != Version) return; // This request is outdated - auto Diags = DeferredRebuild(); + auto Diags = DeferredRebuild(Ctx); if (!Diags) return; // A new reparse was requested before this one completed. @@ -553,12 +555,14 @@ }; WorkScheduler.addToFront(std::move(ReparseAndPublishDiags), - std::move(DeferredRebuild), std::move(DonePromise)); + std::move(DeferredRebuild), std::move(DonePromise), + std::move(Ctx)); return DoneFuture; } std::future -ClangdServer::scheduleCancelRebuild(std::shared_ptr Resources) { +ClangdServer::scheduleCancelRebuild(std::shared_ptr Resources, + Context Ctx) { std::promise DonePromise; std::future DoneFuture = DonePromise.get_future(); if (!Resources) { @@ -569,12 +573,13 @@ UniqueFunction DeferredCancel = Resources->deferCancelRebuild(); auto CancelReparses = [Resources](std::promise DonePromise, - UniqueFunction DeferredCancel) { + UniqueFunction DeferredCancel, + Context Ctx) { FulfillPromiseGuard Guard(DonePromise); DeferredCancel(); }; WorkScheduler.addToFront(std::move(CancelReparses), std::move(DonePromise), - std::move(DeferredCancel)); + std::move(DeferredCancel), std::move(Ctx)); return DoneFuture; } Index: clangd/ClangdUnit.h =================================================================== --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H +#include "Context.h" #include "Function.h" #include "Path.h" #include "Protocol.h" @@ -40,8 +41,6 @@ namespace clangd { -class Logger; - /// A diagnostic with its FixIts. struct DiagWithFixIts { clangd::Diagnostic Diag; @@ -69,7 +68,7 @@ std::shared_ptr Preamble, std::unique_ptr Buffer, std::shared_ptr PCHs, - IntrusiveRefCntPtr VFS, clangd::Logger &Logger); + IntrusiveRefCntPtr VFS, Context &Ctx); ParsedAST(ParsedAST &&Other); ParsedAST &operator=(ParsedAST &&Other); @@ -146,12 +145,12 @@ static std::shared_ptr Create(PathRef FileName, tooling::CompileCommand Command, bool StorePreamblesInMemory, - std::shared_ptr PCHs, clangd::Logger &Logger); + std::shared_ptr PCHs); private: CppFile(PathRef FileName, tooling::CompileCommand Command, bool StorePreamblesInMemory, - std::shared_ptr PCHs, clangd::Logger &Logger); + std::shared_ptr PCHs); public: CppFile(CppFile const &) = delete; @@ -173,7 +172,8 @@ /// requested in parallel (effectively cancelling this rebuild) before /// diagnostics were produced. llvm::Optional> - rebuild(StringRef NewContents, IntrusiveRefCntPtr VFS); + rebuild(StringRef NewContents, IntrusiveRefCntPtr VFS, + Context &Ctx); /// Schedule a rebuild and return a deferred computation that will finish the /// rebuild, that can be called on a different thread. @@ -189,7 +189,7 @@ /// The future to finish rebuild returns a list of diagnostics built during /// reparse, or None, if another deferRebuild was called before this /// rebuild was finished. - UniqueFunction>()> + UniqueFunction>(Context &)> deferRebuild(StringRef NewContents, IntrusiveRefCntPtr VFS); /// Returns a future to get the most fresh PreambleData for a file. The @@ -252,8 +252,6 @@ std::shared_ptr LatestAvailablePreamble; /// Utility class, required by clang. std::shared_ptr PCHs; - /// Used for logging various messages. - clangd::Logger &Logger; }; struct CodeCompleteOptions { @@ -291,21 +289,20 @@ }; /// Get code completions at a specified \p Pos in \p FileName. -CompletionList -codeComplete(PathRef FileName, const tooling::CompileCommand &Command, - PrecompiledPreamble const *Preamble, StringRef Contents, - Position Pos, IntrusiveRefCntPtr VFS, - std::shared_ptr PCHs, - clangd::CodeCompleteOptions Opts, clangd::Logger &Logger); - -/// Get signature help at a specified \p Pos in \p FileName. -SignatureHelp signatureHelp(PathRef FileName, +CompletionList codeComplete(PathRef FileName, const tooling::CompileCommand &Command, PrecompiledPreamble const *Preamble, StringRef Contents, Position Pos, IntrusiveRefCntPtr VFS, std::shared_ptr PCHs, - clangd::Logger &Logger); + clangd::CodeCompleteOptions Opts, Context &Ctx); + +/// Get signature help at a specified \p Pos in \p FileName. +SignatureHelp +signatureHelp(PathRef FileName, const tooling::CompileCommand &Command, + PrecompiledPreamble const *Preamble, StringRef Contents, + Position Pos, IntrusiveRefCntPtr VFS, + std::shared_ptr PCHs, Context &Ctx); /// Get the beginning SourceLocation at a specified \p Pos. SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos, @@ -313,7 +310,7 @@ /// Get definition of symbol at a specified \p Pos. std::vector findDefinitions(ParsedAST &AST, Position Pos, - clangd::Logger &Logger); + Context &Ctx); /// For testing/debugging purposes. Note that this method deserializes all /// unserialized Decls, so use with care. Index: clangd/ClangdUnit.cpp =================================================================== --- clangd/ClangdUnit.cpp +++ clangd/ClangdUnit.cpp @@ -762,7 +762,7 @@ PrecompiledPreamble const *Preamble, StringRef Contents, Position Pos, IntrusiveRefCntPtr VFS, std::shared_ptr PCHs, - clangd::Logger &Logger) { + Context &Ctx) { std::vector ArgStrs; for (const auto &S : Command.CommandLine) ArgStrs.push_back(S.c_str()); @@ -807,12 +807,12 @@ SyntaxOnlyAction Action; if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) { - Logger.log("BeginSourceFile() failed when running codeComplete for " + - FileName); + log(Ctx, + "BeginSourceFile() failed when running codeComplete for " + FileName); return false; } if (!Action.Execute()) { - Logger.log("Execute() failed when running codeComplete for " + FileName); + log(Ctx, "Execute() failed when running codeComplete for " + FileName); return false; } @@ -839,7 +839,7 @@ PrecompiledPreamble const *Preamble, StringRef Contents, Position Pos, IntrusiveRefCntPtr VFS, std::shared_ptr PCHs, - clangd::CodeCompleteOptions Opts, clangd::Logger &Logger) { + clangd::CodeCompleteOptions Opts, Context &Ctx) { CompletionList Results; std::unique_ptr Consumer; if (Opts.EnableSnippets) { @@ -851,7 +851,7 @@ } invokeCodeComplete(std::move(Consumer), Opts.getClangCompleteOpts(), FileName, Command, Preamble, Contents, Pos, std::move(VFS), - std::move(PCHs), Logger); + std::move(PCHs), Ctx); return Results; } @@ -860,7 +860,7 @@ PrecompiledPreamble const *Preamble, StringRef Contents, Position Pos, IntrusiveRefCntPtr VFS, std::shared_ptr PCHs, - clangd::Logger &Logger) { + Context &Ctx) { SignatureHelp Result; clang::CodeCompleteOptions Options; Options.IncludeGlobals = false; @@ -869,7 +869,7 @@ Options.IncludeBriefComments = true; invokeCodeComplete(llvm::make_unique(Options, Result), Options, FileName, Command, Preamble, Contents, Pos, - std::move(VFS), std::move(PCHs), Logger); + std::move(VFS), std::move(PCHs), Ctx); return Result; } @@ -882,8 +882,7 @@ std::shared_ptr Preamble, std::unique_ptr Buffer, std::shared_ptr PCHs, - IntrusiveRefCntPtr VFS, - clangd::Logger &Logger) { + IntrusiveRefCntPtr VFS, Context &Ctx) { std::vector ASTDiags; StoreDiagsConsumer UnitDiagsConsumer(/*ref*/ ASTDiags); @@ -901,12 +900,12 @@ auto Action = llvm::make_unique(); const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0]; if (!Action->BeginSourceFile(*Clang, MainInput)) { - Logger.log("BeginSourceFile() failed when building AST for " + - MainInput.getFile()); + log(Ctx, "BeginSourceFile() failed when building AST for " + + MainInput.getFile()); return llvm::None; } if (!Action->Execute()) - Logger.log("Execute() failed when building AST for " + MainInput.getFile()); + log(Ctx, "Execute() failed when building AST for " + MainInput.getFile()); // UnitDiagsConsumer is local, we can not store it in CompilerInstance that // has a longer lifetime. @@ -1032,7 +1031,7 @@ } // namespace std::vector clangd::findDefinitions(ParsedAST &AST, Position Pos, - clangd::Logger &Logger) { + Context &Ctx) { const SourceManager &SourceMgr = AST.getASTContext().getSourceManager(); const FileEntry *FE = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); if (!FE) @@ -1135,20 +1134,17 @@ std::shared_ptr CppFile::Create(PathRef FileName, tooling::CompileCommand Command, bool StorePreamblesInMemory, - std::shared_ptr PCHs, - clangd::Logger &Logger) { - return std::shared_ptr(new CppFile(FileName, std::move(Command), - StorePreamblesInMemory, - std::move(PCHs), Logger)); + std::shared_ptr PCHs) { + return std::shared_ptr(new CppFile( + FileName, std::move(Command), StorePreamblesInMemory, std::move(PCHs))); } CppFile::CppFile(PathRef FileName, tooling::CompileCommand Command, bool StorePreamblesInMemory, - std::shared_ptr PCHs, - clangd::Logger &Logger) + std::shared_ptr PCHs) : FileName(FileName), Command(std::move(Command)), StorePreamblesInMemory(StorePreamblesInMemory), RebuildCounter(0), - RebuildInProgress(false), PCHs(std::move(PCHs)), Logger(Logger) { + RebuildInProgress(false), PCHs(std::move(PCHs)) { std::lock_guard Lock(Mutex); LatestAvailablePreamble = nullptr; @@ -1200,12 +1196,12 @@ } llvm::Optional> -CppFile::rebuild(StringRef NewContents, - IntrusiveRefCntPtr VFS) { - return deferRebuild(NewContents, std::move(VFS))(); +CppFile::rebuild(StringRef NewContents, IntrusiveRefCntPtr VFS, + Context &Ctx) { + return deferRebuild(NewContents, std::move(VFS))(Ctx); } -UniqueFunction>()> +UniqueFunction>(Context &)> CppFile::deferRebuild(StringRef NewContents, IntrusiveRefCntPtr VFS) { std::shared_ptr OldPreamble; @@ -1242,9 +1238,10 @@ // Don't let this CppFile die before rebuild is finished. std::shared_ptr That = shared_from_this(); auto FinishRebuild = [OldPreamble, VFS, RequestRebuildCounter, PCHs, - That](std::string NewContents) mutable // 'mutable' to - // allow changing - // OldPreamble. + That](std::string NewContents, + Context &Ctx) mutable // 'mutable' to + // allow changing + // OldPreamble. -> llvm::Optional> { // Only one execution of this method is possible at a time. // RebuildGuard will wait for any ongoing rebuilds to finish and will put us @@ -1337,9 +1334,8 @@ { trace::Span Tracer("Build"); SPAN_ATTACH(Tracer, "File", That->FileName); - NewAST = - ParsedAST::Build(std::move(CI), std::move(NewPreamble), - std::move(ContentsBuffer), PCHs, VFS, That->Logger); + NewAST = ParsedAST::Build(std::move(CI), std::move(NewPreamble), + std::move(ContentsBuffer), PCHs, VFS, Ctx); } if (NewAST) { Index: clangd/ClangdUnitStore.h =================================================================== --- clangd/ClangdUnitStore.h +++ clangd/ClangdUnitStore.h @@ -14,6 +14,7 @@ #include "ClangdUnit.h" #include "GlobalCompilationDatabase.h" +#include "Logger.h" #include "Path.h" #include "clang/Tooling/CompilationDatabase.h" @@ -28,8 +29,7 @@ std::shared_ptr getOrCreateFile(PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB, bool StorePreamblesInMemory, - std::shared_ptr PCHs, - clangd::Logger &Logger) { + std::shared_ptr PCHs) { std::lock_guard Lock(Mutex); auto It = OpenedFiles.find(File); @@ -39,7 +39,7 @@ It = OpenedFiles .try_emplace(File, CppFile::Create(File, std::move(Command), StorePreamblesInMemory, - std::move(PCHs), Logger)) + std::move(PCHs))) .first; } return It->second; @@ -61,8 +61,8 @@ /// will be returned in RecreateResult.RemovedFile. RecreateResult recreateFileIfCompileCommandChanged( PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB, - bool StorePreamblesInMemory, std::shared_ptr PCHs, - clangd::Logger &Logger); + bool StorePreamblesInMemory, + std::shared_ptr PCHs); std::shared_ptr getFile(PathRef File) { std::lock_guard Lock(Mutex); Index: clangd/ClangdUnitStore.cpp =================================================================== --- clangd/ClangdUnitStore.cpp +++ clangd/ClangdUnitStore.cpp @@ -29,8 +29,7 @@ CppFileCollection::RecreateResult CppFileCollection::recreateFileIfCompileCommandChanged( PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB, - bool StorePreamblesInMemory, std::shared_ptr PCHs, - clangd::Logger &Logger) { + bool StorePreamblesInMemory, std::shared_ptr PCHs) { auto NewCommand = getCompileCommand(CDB, File, ResourceDir); std::lock_guard Lock(Mutex); @@ -42,14 +41,13 @@ It = OpenedFiles .try_emplace(File, CppFile::Create(File, std::move(NewCommand), StorePreamblesInMemory, - std::move(PCHs), Logger)) + std::move(PCHs))) .first; } else if (!compileCommandsAreEqual(It->second->getCompileCommand(), NewCommand)) { Result.RemovedFile = std::move(It->second); - It->second = - CppFile::Create(File, std::move(NewCommand), StorePreamblesInMemory, - std::move(PCHs), Logger); + It->second = CppFile::Create(File, std::move(NewCommand), + StorePreamblesInMemory, std::move(PCHs)); } Result.FileInCollection = It->second; return Result; Index: clangd/GlobalCompilationDatabase.h =================================================================== --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -48,7 +48,7 @@ : public GlobalCompilationDatabase { public: DirectoryBasedGlobalCompilationDatabase( - clangd::Logger &Logger, llvm::Optional CompileCommandsDir); + llvm::Optional CompileCommandsDir); std::vector getCompileCommands(PathRef File) override; @@ -67,8 +67,6 @@ /// Stores extra flags per file. llvm::StringMap> ExtraFlagsForFile; - /// Used for logging. - clangd::Logger &Logger; /// Used for command argument pointing to folder where compile_commands.json /// is located. llvm::Optional CompileCommandsDir; Index: clangd/GlobalCompilationDatabase.cpp =================================================================== --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -39,8 +39,8 @@ DirectoryBasedGlobalCompilationDatabase:: DirectoryBasedGlobalCompilationDatabase( - clangd::Logger &Logger, llvm::Optional CompileCommandsDir) - : Logger(Logger), CompileCommandsDir(std::move(CompileCommandsDir)) {} + llvm::Optional CompileCommandsDir) + : CompileCommandsDir(std::move(CompileCommandsDir)) {} std::vector DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) { @@ -99,9 +99,9 @@ tooling::CompilationDatabase *ReturnValue = tryLoadDatabaseFromPath(CompileCommandsDir.getValue()); if (ReturnValue == nullptr) - Logger.log("Failed to find compilation database for " + Twine(File) + - "in overriden directory " + CompileCommandsDir.getValue() + - "\n"); + log(globalCtx(), "Failed to find compilation database for " + + Twine(File) + "in overriden directory " + + CompileCommandsDir.getValue() + "\n"); return ReturnValue; } @@ -114,7 +114,8 @@ return CDB; } - Logger.log("Failed to find compilation database for " + Twine(File) + "\n"); + log(globalCtx(), + "Failed to find compilation database for " + Twine(File) + "\n"); return nullptr; } Index: clangd/JSONRPCDispatcher.h =================================================================== --- clangd/JSONRPCDispatcher.h +++ clangd/JSONRPCDispatcher.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H +#include "Context.h" #include "JSONExpr.h" #include "Logger.h" #include "Protocol.h" @@ -37,7 +38,7 @@ /// Write to the logging stream. /// No newline is implicitly added. (TODO: we should fix this!) - void log(const Twine &Message) override; + void logImpl(Context &Ctx, const Twine &Message) override; /// Mirror \p Message into InputMirror stream. Does nothing if InputMirror is /// null. @@ -56,9 +57,9 @@ /// Context object passed to handlers to allow replies. class RequestContext { public: - RequestContext(JSONOutput &Out, StringRef Method, + RequestContext(Context Ctx, JSONOutput &Out, StringRef Method, llvm::Optional ID) - : Out(Out), ID(std::move(ID)), + : Ctx(std::move(Ctx)), Out(Out), ID(std::move(ID)), Tracer(llvm::make_unique(Method)) { if (this->ID) SPAN_ATTACH(tracer(), "ID", *this->ID); @@ -72,8 +73,10 @@ void call(llvm::StringRef Method, json::Expr &&Params); trace::Span &tracer() { return *Tracer; } + Context &ctx() { return Ctx; } private: + Context Ctx; JSONOutput &Out; llvm::Optional ID; std::unique_ptr Tracer; Index: clangd/JSONRPCDispatcher.cpp =================================================================== --- clangd/JSONRPCDispatcher.cpp +++ clangd/JSONRPCDispatcher.cpp @@ -39,7 +39,8 @@ Outs.flush(); } -void JSONOutput::log(const Twine &Message) { +void JSONOutput::logImpl(Context &Ctx, const Twine &Message) { + // FIXME(ibiryukov): get rid of trace::log here. trace::log(Message); std::lock_guard Guard(StreamMutex); Logs << Message; @@ -56,7 +57,7 @@ void RequestContext::reply(json::Expr &&Result) { if (!ID) { - Out.log("Attempted to reply to a notification!\n"); + log(Ctx, "Attempted to reply to a notification!\n"); return; } SPAN_ATTACH(tracer(), "Reply", Result); @@ -69,7 +70,7 @@ void RequestContext::replyError(ErrorCode code, const llvm::StringRef &Message) { - Out.log("Error " + Twine(static_cast(code)) + ": " + Message + "\n"); + log(Ctx, "Error " + Twine(static_cast(code)) + ": " + Message + "\n"); SPAN_ATTACH(tracer(), "Error", (json::obj{{"code", static_cast(code)}, {"message", Message.str()}})); @@ -110,7 +111,9 @@ llvm::StringRef MethodStr = Method->getValue(MethodStorage); auto I = Handlers.find(MethodStr); auto &Handler = I != Handlers.end() ? I->second : UnknownHandler; - Handler(RequestContext(Out, MethodStr, std::move(ID)), Params); + Handler( + RequestContext(buildCtx(), Out, MethodStr, std::move(ID)), + Params); } bool JSONRPCDispatcher::call(StringRef Content, JSONOutput &Out) const { @@ -224,9 +227,10 @@ // The end of headers is signified by an empty line. if (LineRef.consume_front("Content-Length: ")) { if (ContentLength != 0) { - Out.log("Warning: Duplicate Content-Length header received. " - "The previous value for this message (" + - std::to_string(ContentLength) + ") was ignored.\n"); + log(globalCtx(), "Warning: Duplicate Content-Length header received. " + "The previous value for this message (" + + std::to_string(ContentLength) + + ") was ignored.\n"); } llvm::getAsUnsignedInteger(LineRef.trim(), 0, ContentLength); @@ -245,8 +249,8 @@ // and we don't want to crash downstream because of it. if (ContentLength > 1 << 30) { // 1024M In.ignore(ContentLength); - Out.log("Skipped overly large message of " + Twine(ContentLength) + - " bytes.\n"); + log(globalCtx(), "Skipped overly large message of " + + Twine(ContentLength) + " bytes.\n"); continue; } @@ -262,9 +266,10 @@ // If the stream is aborted before we read ContentLength bytes, In // will have eofbit and failbit set. if (!In) { - Out.log("Input was aborted. Read only " + - std::to_string(In.gcount()) + " bytes of expected " + - std::to_string(ContentLength) + ".\n"); + log(globalCtx(), "Input was aborted. Read only " + + std::to_string(In.gcount()) + + " bytes of expected " + + std::to_string(ContentLength) + ".\n"); break; } @@ -272,18 +277,19 @@ } // Log the message. - Out.log("<-- " + JSONRef + "\n"); + log(globalCtx(), "<-- " + JSONRef + "\n"); // Finally, execute the action for this JSON message. if (!Dispatcher.call(JSONRef, Out)) - Out.log("JSON dispatch failed!\n"); + log(globalCtx(), "JSON dispatch failed!\n"); // If we're done, exit the loop. if (IsDone) break; } else { - Out.log("Warning: Missing Content-Length header, or message has zero " - "length.\n"); + log(globalCtx(), + "Warning: Missing Content-Length header, or message has zero " + "length.\n"); } } } Index: clangd/Logger.h =================================================================== --- clangd/Logger.h +++ clangd/Logger.h @@ -10,29 +10,24 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H +#include "Context.h" #include "llvm/ADT/Twine.h" namespace clang { namespace clangd { +/// Main logging function. Logs messages to a Logger inside \p Ctx. +void log(Context &Ctx, const llvm::Twine &Message); + /// Interface to allow custom logging in clangd. class Logger { public: + static PtrKey CtxKey; + virtual ~Logger() = default; /// Implementations of this method must be thread-safe. - virtual void log(const llvm::Twine &Message) = 0; -}; - -/// Logger implementation that ignores all messages. -class EmptyLogger : public Logger { -public: - static EmptyLogger &getInstance(); - - void log(const llvm::Twine &Message) override; - -private: - EmptyLogger() = default; + virtual void logImpl(Context &Ctx, const llvm::Twine &Message) = 0; }; } // namespace clangd Index: clangd/Logger.cpp =================================================================== --- clangd/Logger.cpp +++ clangd/Logger.cpp @@ -9,11 +9,17 @@ #include "Logger.h" -using namespace clang::clangd; +namespace clang { +namespace clangd { -EmptyLogger &EmptyLogger::getInstance() { - static EmptyLogger Logger; - return Logger; +PtrKey Logger::CtxKey; + +void log(Context &Ctx, const llvm::Twine &Message) { + Logger *Logger = Ctx.get(Logger::CtxKey); + if (!Logger) + return; + Logger->logImpl(Ctx, Message); } -void EmptyLogger::log(const llvm::Twine &Message) {} +} // namespace clangd +} // namespace clang Index: clangd/Protocol.h =================================================================== --- clangd/Protocol.h +++ clangd/Protocol.h @@ -21,6 +21,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H +#include "Context.h" #include "JSONExpr.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/YAMLParser.h" @@ -75,7 +76,7 @@ URI uri; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct Position { @@ -95,7 +96,7 @@ } static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); static json::Expr unparse(const Position &P); }; @@ -114,7 +115,7 @@ } static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); static json::Expr unparse(const Range &P); }; @@ -142,7 +143,7 @@ std::vector extraFlags; static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); }; struct TextEdit { @@ -155,7 +156,7 @@ std::string newText; static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); static json::Expr unparse(const TextEdit &P); }; @@ -173,7 +174,7 @@ std::string text; static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); }; enum class TraceLevel { @@ -184,7 +185,7 @@ struct NoParams { static llvm::Optional parse(llvm::yaml::MappingNode *Params, - Logger &Logger) { + Context &Ctx) { return NoParams{}; } }; @@ -219,7 +220,7 @@ /// The initial trace setting. If omitted trace is disabled ('off'). llvm::Optional trace; static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); }; struct DidOpenTextDocumentParams { @@ -230,7 +231,7 @@ llvm::Optional metadata; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct DidCloseTextDocumentParams { @@ -238,7 +239,7 @@ TextDocumentIdentifier textDocument; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct TextDocumentContentChangeEvent { @@ -246,7 +247,7 @@ std::string text; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct DidChangeTextDocumentParams { @@ -259,7 +260,7 @@ std::vector contentChanges; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; enum class FileChangeType { @@ -278,7 +279,7 @@ FileChangeType type; static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); }; struct DidChangeWatchedFilesParams { @@ -286,7 +287,7 @@ std::vector changes; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct FormattingOptions { @@ -297,7 +298,7 @@ bool insertSpaces; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); static json::Expr unparse(const FormattingOptions &P); }; @@ -312,7 +313,7 @@ FormattingOptions options; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct DocumentOnTypeFormattingParams { @@ -329,7 +330,7 @@ FormattingOptions options; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct DocumentFormattingParams { @@ -340,7 +341,7 @@ FormattingOptions options; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct Diagnostic { @@ -373,7 +374,7 @@ } static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); }; struct CodeActionContext { @@ -381,7 +382,7 @@ std::vector diagnostics; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct CodeActionParams { @@ -395,7 +396,7 @@ CodeActionContext context; static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); }; struct WorkspaceEdit { @@ -406,7 +407,7 @@ /// no support for versioned edits. static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); static json::Expr unparse(const WorkspaceEdit &WE); }; @@ -430,7 +431,7 @@ llvm::Optional workspaceEdit; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; struct ApplyWorkspaceEditParams { @@ -446,7 +447,7 @@ Position position; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + parse(llvm::yaml::MappingNode *Params, Context &Ctx); }; /// The kind of a completion entry. @@ -612,7 +613,7 @@ std::string newName; static llvm::Optional parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger); + Context &Ctx); }; } // namespace clangd Index: clangd/Protocol.cpp =================================================================== --- clangd/Protocol.cpp +++ clangd/Protocol.cpp @@ -26,8 +26,8 @@ using namespace clang::clangd; namespace { -void logIgnoredField(llvm::StringRef KeyValue, clangd::Logger &Logger) { - Logger.log(llvm::formatv("Ignored unknown field \"{0}\"\n", KeyValue)); +void logIgnoredField(llvm::StringRef KeyValue, Context &Ctx) { + log(Ctx, llvm::formatv("Ignored unknown field \"{0}\"\n", KeyValue)); } } // namespace @@ -66,8 +66,7 @@ json::Expr URI::unparse(const URI &U) { return U.uri; } llvm::Optional -TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { +TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { TextDocumentIdentifier Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -86,14 +85,14 @@ } else if (KeyValue == "version") { // FIXME: parse version, but only for VersionedTextDocumentIdentifiers. } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional Position::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { Position Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -119,7 +118,7 @@ return llvm::None; Result.character = Val; } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -133,7 +132,7 @@ } llvm::Optional Range::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { Range Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -149,17 +148,17 @@ llvm::SmallString<10> Storage; if (KeyValue == "start") { - auto Parsed = Position::parse(Value, Logger); + auto Parsed = Position::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.start = std::move(*Parsed); } else if (KeyValue == "end") { - auto Parsed = Position::parse(Value, Logger); + auto Parsed = Position::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.end = std::move(*Parsed); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -180,8 +179,7 @@ } llvm::Optional -TextDocumentItem::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { +TextDocumentItem::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { TextDocumentItem Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -208,14 +206,14 @@ } else if (KeyValue == "text") { Result.text = Value->getValue(Storage); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional Metadata::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { Metadata Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -238,14 +236,14 @@ Result.extraFlags.push_back(Node->getValue(Storage)); } } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional TextEdit::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { TextEdit Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -261,7 +259,7 @@ auto *Map = dyn_cast(Value); if (!Map) return llvm::None; - auto Parsed = Range::parse(Map, Logger); + auto Parsed = Range::parse(Map, Ctx); if (!Parsed) return llvm::None; Result.range = std::move(*Parsed); @@ -271,7 +269,7 @@ return llvm::None; Result.newText = Node->getValue(Storage); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -285,8 +283,7 @@ } namespace { -TraceLevel getTraceLevel(llvm::StringRef TraceLevelStr, - clangd::Logger &Logger) { +TraceLevel getTraceLevel(llvm::StringRef TraceLevelStr, Context &Ctx) { if (TraceLevelStr == "off") return TraceLevel::Off; else if (TraceLevelStr == "messages") @@ -294,17 +291,16 @@ else if (TraceLevelStr == "verbose") return TraceLevel::Verbose; - Logger.log(llvm::formatv("Unknown trace level \"{0}\"\n", TraceLevelStr)); + log(Ctx, llvm::formatv("Unknown trace level \"{0}\"\n", TraceLevelStr)); return TraceLevel::Off; } } // namespace llvm::Optional -InitializeParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { +InitializeParams::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { // If we don't understand the params, proceed with default parameters. auto ParseFailure = [&] { - Logger.log("Failed to decode InitializeParams\n"); + log(Ctx, "Failed to decode InitializeParams\n"); return InitializeParams(); }; InitializeParams Result; @@ -338,9 +334,9 @@ } else if (KeyValue == "capabilities") { // Not used } else if (KeyValue == "trace") { - Result.trace = getTraceLevel(Value->getValue(KeyStorage), Logger); + Result.trace = getTraceLevel(Value->getValue(KeyStorage), Ctx); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -348,7 +344,7 @@ llvm::Optional DidOpenTextDocumentParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { DidOpenTextDocumentParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -364,17 +360,17 @@ llvm::SmallString<10> Storage; if (KeyValue == "textDocument") { - auto Parsed = TextDocumentItem::parse(Value, Logger); + auto Parsed = TextDocumentItem::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.textDocument = std::move(*Parsed); } else if (KeyValue == "metadata") { - auto Parsed = Metadata::parse(Value, Logger); + auto Parsed = Metadata::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.metadata = std::move(*Parsed); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -382,7 +378,7 @@ llvm::Optional DidCloseTextDocumentParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { DidCloseTextDocumentParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -397,12 +393,12 @@ auto *Map = dyn_cast(Value); if (!Map) return llvm::None; - auto Parsed = TextDocumentIdentifier::parse(Map, Logger); + auto Parsed = TextDocumentIdentifier::parse(Map, Ctx); if (!Parsed) return llvm::None; Result.textDocument = std::move(*Parsed); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -410,7 +406,7 @@ llvm::Optional DidChangeTextDocumentParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { DidChangeTextDocumentParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -426,7 +422,7 @@ auto *Map = dyn_cast(Value); if (!Map) return llvm::None; - auto Parsed = TextDocumentIdentifier::parse(Map, Logger); + auto Parsed = TextDocumentIdentifier::parse(Map, Ctx); if (!Parsed) return llvm::None; Result.textDocument = std::move(*Parsed); @@ -438,20 +434,20 @@ auto *I = dyn_cast(&Item); if (!I) return llvm::None; - auto Parsed = TextDocumentContentChangeEvent::parse(I, Logger); + auto Parsed = TextDocumentContentChangeEvent::parse(I, Ctx); if (!Parsed) return llvm::None; Result.contentChanges.push_back(std::move(*Parsed)); } } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional FileEvent::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { llvm::Optional Result = FileEvent(); for (auto &NextKeyValue : *Params) { // We have to consume the whole MappingNode because it doesn't support @@ -487,7 +483,7 @@ Result->type > FileChangeType::Deleted) Result.reset(); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -495,7 +491,7 @@ llvm::Optional DidChangeWatchedFilesParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { DidChangeWatchedFilesParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -515,14 +511,14 @@ auto *I = dyn_cast(&Item); if (!I) return llvm::None; - auto Parsed = FileEvent::parse(I, Logger); + auto Parsed = FileEvent::parse(I, Ctx); if (Parsed) Result.changes.push_back(std::move(*Parsed)); else - Logger.log("Failed to decode a FileEvent.\n"); + log(Ctx, "Failed to decode a FileEvent.\n"); } } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -530,7 +526,7 @@ llvm::Optional TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { TextDocumentContentChangeEvent Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -548,15 +544,14 @@ if (KeyValue == "text") { Result.text = Value->getValue(Storage); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional -FormattingOptions::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { +FormattingOptions::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { FormattingOptions Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -589,7 +584,7 @@ } Result.insertSpaces = Val; } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -604,7 +599,7 @@ llvm::Optional DocumentRangeFormattingParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { DocumentRangeFormattingParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -620,22 +615,22 @@ llvm::SmallString<10> Storage; if (KeyValue == "textDocument") { - auto Parsed = TextDocumentIdentifier::parse(Value, Logger); + auto Parsed = TextDocumentIdentifier::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.textDocument = std::move(*Parsed); } else if (KeyValue == "range") { - auto Parsed = Range::parse(Value, Logger); + auto Parsed = Range::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.range = std::move(*Parsed); } else if (KeyValue == "options") { - auto Parsed = FormattingOptions::parse(Value, Logger); + auto Parsed = FormattingOptions::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.options = std::move(*Parsed); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -643,7 +638,7 @@ llvm::Optional DocumentOnTypeFormattingParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { DocumentOnTypeFormattingParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -668,30 +663,29 @@ if (!Value) return llvm::None; if (KeyValue == "textDocument") { - auto Parsed = TextDocumentIdentifier::parse(Value, Logger); + auto Parsed = TextDocumentIdentifier::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.textDocument = std::move(*Parsed); } else if (KeyValue == "position") { - auto Parsed = Position::parse(Value, Logger); + auto Parsed = Position::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.position = std::move(*Parsed); } else if (KeyValue == "options") { - auto Parsed = FormattingOptions::parse(Value, Logger); + auto Parsed = FormattingOptions::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.options = std::move(*Parsed); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional -DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { +DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { DocumentFormattingParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -707,24 +701,24 @@ llvm::SmallString<10> Storage; if (KeyValue == "textDocument") { - auto Parsed = TextDocumentIdentifier::parse(Value, Logger); + auto Parsed = TextDocumentIdentifier::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.textDocument = std::move(*Parsed); } else if (KeyValue == "options") { - auto Parsed = FormattingOptions::parse(Value, Logger); + auto Parsed = FormattingOptions::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.options = std::move(*Parsed); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional Diagnostic::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { Diagnostic Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -740,7 +734,7 @@ dyn_cast_or_null(NextKeyValue.getValue()); if (!Value) return llvm::None; - auto Parsed = Range::parse(Value, Logger); + auto Parsed = Range::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.range = std::move(*Parsed); @@ -764,15 +758,14 @@ return llvm::None; Result.message = Value->getValue(Storage); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional -CodeActionContext::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { +CodeActionContext::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { CodeActionContext Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -792,21 +785,20 @@ auto *I = dyn_cast(&Item); if (!I) return llvm::None; - auto Parsed = Diagnostic::parse(I, Logger); + auto Parsed = Diagnostic::parse(I, Ctx); if (!Parsed) return llvm::None; Result.diagnostics.push_back(std::move(*Parsed)); } } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional -CodeActionParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { +CodeActionParams::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { CodeActionParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -822,30 +814,29 @@ llvm::SmallString<10> Storage; if (KeyValue == "textDocument") { - auto Parsed = TextDocumentIdentifier::parse(Value, Logger); + auto Parsed = TextDocumentIdentifier::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.textDocument = std::move(*Parsed); } else if (KeyValue == "range") { - auto Parsed = Range::parse(Value, Logger); + auto Parsed = Range::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.range = std::move(*Parsed); } else if (KeyValue == "context") { - auto Parsed = CodeActionContext::parse(Value, Logger); + auto Parsed = CodeActionContext::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.context = std::move(*Parsed); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; } llvm::Optional>> -parseWorkspaceEditChange(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { +parseWorkspaceEditChange(llvm::yaml::MappingNode *Params, Context &Ctx) { std::map> Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -855,7 +846,7 @@ llvm::SmallString<10> KeyStorage; StringRef KeyValue = KeyString->getValue(KeyStorage); if (Result.count(KeyValue)) { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); continue; } @@ -867,7 +858,7 @@ auto *ItemValue = dyn_cast_or_null(&Item); if (!ItemValue) return llvm::None; - auto Parsed = TextEdit::parse(ItemValue, Logger); + auto Parsed = TextEdit::parse(ItemValue, Ctx); if (!Parsed) return llvm::None; @@ -879,7 +870,7 @@ } llvm::Optional -WorkspaceEdit::parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger) { +WorkspaceEdit::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { WorkspaceEdit Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -895,12 +886,12 @@ dyn_cast_or_null(NextKeyValue.getValue()); if (!Value) return llvm::None; - auto Parsed = parseWorkspaceEditChange(Value, Logger); + auto Parsed = parseWorkspaceEditChange(Value, Ctx); if (!Parsed) return llvm::None; Result.changes = std::move(*Parsed); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -910,8 +901,7 @@ "clangd.applyFix"; llvm::Optional -ExecuteCommandParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { +ExecuteCommandParams::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { ExecuteCommandParams Result; // Depending on which "command" we parse, we will use this function to parse // the command "arguments". @@ -935,8 +925,8 @@ llvm::SmallString<10> Storage; Result.command = ScalarValue->getValue(Storage); if (Result.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND) { - ArgParser = [&Result, &Logger](llvm::yaml::MappingNode *Params) { - auto WE = WorkspaceEdit::parse(Params, Logger); + ArgParser = [&Result, &Ctx](llvm::yaml::MappingNode *Params) { + auto WE = WorkspaceEdit::parse(Params, Ctx); if (WE) Result.workspaceEdit = WE; return WE.hasValue(); @@ -957,7 +947,7 @@ return llvm::None; } } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } if (Result.command.empty()) @@ -982,7 +972,7 @@ llvm::Optional TextDocumentPositionParams::parse(llvm::yaml::MappingNode *Params, - clangd::Logger &Logger) { + Context &Ctx) { TextDocumentPositionParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -998,17 +988,17 @@ llvm::SmallString<10> Storage; if (KeyValue == "textDocument") { - auto Parsed = TextDocumentIdentifier::parse(Value, Logger); + auto Parsed = TextDocumentIdentifier::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.textDocument = std::move(*Parsed); } else if (KeyValue == "position") { - auto Parsed = Position::parse(Value, Logger); + auto Parsed = Position::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.position = std::move(*Parsed); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; @@ -1082,7 +1072,7 @@ } llvm::Optional -RenameParams::parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger) { +RenameParams::parse(llvm::yaml::MappingNode *Params, Context &Ctx) { RenameParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -1100,7 +1090,7 @@ auto *Map = dyn_cast(Value); if (!Map) return llvm::None; - auto Parsed = TextDocumentIdentifier::parse(Map, Logger); + auto Parsed = TextDocumentIdentifier::parse(Map, Ctx); if (!Parsed) return llvm::None; Result.textDocument = std::move(*Parsed); @@ -1109,7 +1099,7 @@ dyn_cast_or_null(NextKeyValue.getValue()); if (!Value) continue; - auto Parsed = Position::parse(Value, Logger); + auto Parsed = Position::parse(Value, Ctx); if (!Parsed) return llvm::None; Result.position = std::move(*Parsed); @@ -1123,7 +1113,7 @@ llvm::SmallString<10> Storage; Result.newName = Node->getValue(Storage); } else { - logIgnoredField(KeyValue, Logger); + logIgnoredField(KeyValue, Ctx); } } return Result; Index: clangd/ProtocolHandlers.cpp =================================================================== --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -27,17 +27,16 @@ void operator()(StringRef Method, void (ProtocolCallbacks::*Handler)(RequestContext, Param)) { // Capture pointers by value, as the lambda will outlive this object. - auto *Out = this->Out; auto *Callbacks = this->Callbacks; Dispatcher.registerHandler( Method, [=](RequestContext C, llvm::yaml::MappingNode *RawParams) { if (auto P = [&] { trace::Span Tracer("Parse"); - return std::decay::type::parse(RawParams, *Out); + return std::decay::type::parse(RawParams, C.ctx()); }()) { (Callbacks->*Handler)(std::move(C), *P); } else { - Out->log("Failed to decode " + Method + " request.\n"); + log(C.ctx(), "Failed to decode " + Method + " request.\n"); } }); } Index: clangd/tool/ClangdMain.cpp =================================================================== --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -134,6 +134,8 @@ InputMirrorStream ? InputMirrorStream.getPointer() : nullptr, PrettyPrint); + GlobalSession Session(buildCtx().add(Logger::CtxKey, &Out)); + // If --compile-commands-dir arg was invoked, check value and override default // path. llvm::Optional CompileCommandsDirPath; @@ -172,8 +174,7 @@ CCOpts.IncludeIneligibleResults = IncludeIneligibleResults; // Initialize and run ClangdLSPServer. ClangdLSPServer LSPServer(Out, WorkerThreadsCount, StorePreamblesInMemory, - CCOpts, ResourceDirRef, - CompileCommandsDirPath); + CCOpts, ResourceDirRef, CompileCommandsDirPath); constexpr int NoShutdownRequestErrorCode = 1; llvm::set_thread_name("clangd.main"); return LSPServer.run(std::cin) ? 0 : NoShutdownRequestErrorCode; Index: unittests/clangd/ClangdTests.cpp =================================================================== --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -9,7 +9,7 @@ #include "ClangdLSPServer.h" #include "ClangdServer.h" -#include "Logger.h" +#include "Context.h" #include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" #include "llvm/ADT/SmallVector.h" @@ -133,8 +133,11 @@ } // namespace vfs namespace clangd { + namespace { +Context emptyCtx() { return buildCtx(); } + struct StringWithPos { std::string Text; clangd::Position MarkerPos; @@ -333,8 +336,7 @@ MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); + clangd::CodeCompleteOptions()); for (const auto &FileWithContents : ExtraFiles) FS.Files[getVirtualTestFilePath(FileWithContents.first)] = FileWithContents.second; @@ -345,7 +347,8 @@ // Have to sync reparses because requests are processed on the calling // thread. - auto AddDocFuture = Server.addDocument(SourceFilename, SourceContents); + auto AddDocFuture = + Server.addDocument(SourceFilename, SourceContents, emptyCtx()); auto Result = dumpASTWithoutMemoryLocs(Server, SourceFilename); @@ -398,8 +401,7 @@ MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); + clangd::CodeCompleteOptions()); const auto SourceContents = R"cpp( #include "foo.h" @@ -416,19 +418,19 @@ // To sync reparses before checking for errors. std::future ParseFuture; - ParseFuture = Server.addDocument(FooCpp, SourceContents); + ParseFuture = Server.addDocument(FooCpp, SourceContents, emptyCtx()); auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp); ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout), std::future_status::ready); EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags()); - ParseFuture = Server.addDocument(FooCpp, ""); + ParseFuture = Server.addDocument(FooCpp, "", emptyCtx()); auto DumpParseEmpty = dumpASTWithoutMemoryLocs(Server, FooCpp); ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout), std::future_status::ready); EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags()); - ParseFuture = Server.addDocument(FooCpp, SourceContents); + ParseFuture = Server.addDocument(FooCpp, SourceContents, emptyCtx()); auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp); ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout), std::future_status::ready); @@ -445,8 +447,7 @@ ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); + clangd::CodeCompleteOptions()); const auto SourceContents = R"cpp( #include "foo.h" @@ -463,21 +464,21 @@ // To sync reparses before checking for errors. std::future ParseFuture; - ParseFuture = Server.addDocument(FooCpp, SourceContents); + ParseFuture = Server.addDocument(FooCpp, SourceContents, emptyCtx()); auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp); ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout), std::future_status::ready); EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags()); FS.Files[FooH] = ""; - ParseFuture = Server.forceReparse(FooCpp); + ParseFuture = Server.forceReparse(FooCpp, emptyCtx()); auto DumpParseDifferent = dumpASTWithoutMemoryLocs(Server, FooCpp); ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout), std::future_status::ready); EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags()); FS.Files[FooH] = "int a;"; - ParseFuture = Server.forceReparse(FooCpp); + ParseFuture = Server.forceReparse(FooCpp, emptyCtx()); auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp); EXPECT_EQ(ParseFuture.wait_for(DefaultFutureTimeout), std::future_status::ready); @@ -495,8 +496,7 @@ ClangdServer Server(CDB, DiagConsumer, FS, /*AsyncThreadsCount=*/0, /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); + clangd::CodeCompleteOptions()); auto FooCpp = getVirtualTestFilePath("foo.cpp"); const auto SourceContents = "int a;"; @@ -506,14 +506,16 @@ // No need to sync reparses, because requests are processed on the calling // thread. FS.Tag = "123"; - Server.addDocument(FooCpp, SourceContents); - EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}).get().Tag, FS.Tag); + Server.addDocument(FooCpp, SourceContents, emptyCtx()); + EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}, globalCtx()).get().Tag, + FS.Tag); EXPECT_EQ(DiagConsumer.lastVFSTag(), FS.Tag); FS.Tag = "321"; - Server.addDocument(FooCpp, SourceContents); + Server.addDocument(FooCpp, SourceContents, emptyCtx()); EXPECT_EQ(DiagConsumer.lastVFSTag(), FS.Tag); - EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}).get().Tag, FS.Tag); + EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}, globalCtx()).get().Tag, + FS.Tag); } // Only enable this test on Unix @@ -531,8 +533,7 @@ ClangdServer Server(CDB, DiagConsumer, FS, /*AsyncThreadsCount=*/0, /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); + clangd::CodeCompleteOptions()); // Just a random gcc version string SmallString<8> Version("4.9.3"); @@ -563,14 +564,14 @@ // No need to sync reparses, because requests are processed on the calling // thread. - Server.addDocument(FooCpp, SourceContents); + Server.addDocument(FooCpp, SourceContents, emptyCtx()); EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags()); const auto SourceContentsWithError = R"cpp( #include std::string x; )cpp"; - Server.addDocument(FooCpp, SourceContentsWithError); + Server.addDocument(FooCpp, SourceContentsWithError, emptyCtx()); EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags()); } #endif // LLVM_ON_UNIX @@ -582,8 +583,7 @@ ClangdServer Server(CDB, DiagConsumer, FS, /*AsyncThreadsCount=*/0, /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); + clangd::CodeCompleteOptions()); // No need to sync reparses, because reparses are performed on the calling // thread to true. @@ -602,26 +602,26 @@ // First parse files in C mode and check they produce errors. CDB.ExtraClangFlags = {"-xc"}; - Server.addDocument(FooCpp, SourceContents1); + Server.addDocument(FooCpp, SourceContents1, emptyCtx()); EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags()); - Server.addDocument(FooCpp, SourceContents2); + Server.addDocument(FooCpp, SourceContents2, emptyCtx()); EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags()); // Now switch to C++ mode. CDB.ExtraClangFlags = {"-xc++"}; // Currently, addDocument never checks if CompileCommand has changed, so we // expect to see the errors. - Server.addDocument(FooCpp, SourceContents1); + Server.addDocument(FooCpp, SourceContents1, emptyCtx()); EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags()); - Server.addDocument(FooCpp, SourceContents2); + Server.addDocument(FooCpp, SourceContents2, emptyCtx()); EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags()); // But forceReparse should reparse the file with proper flags. - Server.forceReparse(FooCpp); + Server.forceReparse(FooCpp, emptyCtx()); EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags()); // Subsequent addDocument calls should finish without errors too. - Server.addDocument(FooCpp, SourceContents1); + Server.addDocument(FooCpp, SourceContents1, emptyCtx()); EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags()); - Server.addDocument(FooCpp, SourceContents2); + Server.addDocument(FooCpp, SourceContents2, emptyCtx()); EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags()); } @@ -651,8 +651,7 @@ ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); + clangd::CodeCompleteOptions()); auto FooCpp = getVirtualTestFilePath("foo.cpp"); const auto SourceContents = R"cpp( @@ -675,11 +674,11 @@ // No need to sync reparses here as there are no asserts on diagnostics (or // other async operations). - Server.addDocument(FooCpp, SourceContents); + Server.addDocument(FooCpp, SourceContents, emptyCtx()); { auto CodeCompletionResults1 = - Server.codeComplete(FooCpp, CompletePos, None).get().Value; + Server.codeComplete(FooCpp, CompletePos, globalCtx(), None).get().Value; EXPECT_TRUE(ContainsItem(CodeCompletionResults1, "aba")); EXPECT_FALSE(ContainsItem(CodeCompletionResults1, "cbc")); } @@ -687,7 +686,7 @@ { auto CodeCompletionResultsOverriden = Server - .codeComplete(FooCpp, CompletePos, + .codeComplete(FooCpp, CompletePos, globalCtx(), StringRef(OverridenSourceContents)) .get() .Value; @@ -697,7 +696,7 @@ { auto CodeCompletionResults2 = - Server.codeComplete(FooCpp, CompletePos, None).get().Value; + Server.codeComplete(FooCpp, CompletePos, globalCtx(), None).get().Value; EXPECT_TRUE(ContainsItem(CodeCompletionResults2, "aba")); EXPECT_FALSE(ContainsItem(CodeCompletionResults2, "cbc")); } @@ -711,8 +710,7 @@ clangd::CodeCompleteOptions Opts; Opts.Limit = 2; ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), - /*StorePreamblesInMemory=*/true, Opts, - EmptyLogger::getInstance()); + /*StorePreamblesInMemory=*/true, Opts); auto FooCpp = getVirtualTestFilePath("foo.cpp"); FS.Files[FooCpp] = ""; @@ -726,11 +724,11 @@ int main() { ClassWithMembers().{complete} } )cpp", "complete"); - Server.addDocument(FooCpp, Completion.Text); + Server.addDocument(FooCpp, Completion.Text, emptyCtx()); /// For after-dot completion we must always get consistent results. auto Results = Server - .codeComplete(FooCpp, Completion.MarkerPos, + .codeComplete(FooCpp, Completion.MarkerPos, globalCtx(), StringRef(Completion.Text)) .get() .Value; @@ -809,11 +807,10 @@ auto TestWithOpts = [&](clangd::CodeCompleteOptions Opts) { ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), - /*StorePreamblesInMemory=*/true, Opts, - EmptyLogger::getInstance()); + /*StorePreamblesInMemory=*/true, Opts); // No need to sync reparses here as there are no asserts on diagnostics (or // other async operations). - Server.addDocument(FooCpp, GlobalCompletion.Text); + Server.addDocument(FooCpp, GlobalCompletion.Text, emptyCtx()); StringRef MethodItemText = Opts.EnableSnippets ? "method()" : "method"; StringRef GlobalFuncItemText = @@ -821,11 +818,12 @@ /// For after-dot completion we must always get consistent results. { - auto Results = Server - .codeComplete(FooCpp, MemberCompletion.MarkerPos, - StringRef(MemberCompletion.Text)) - .get() - .Value; + auto Results = + Server + .codeComplete(FooCpp, MemberCompletion.MarkerPos, globalCtx(), + StringRef(MemberCompletion.Text)) + .get() + .Value; // Class members. The only items that must be present in after-dor // completion. @@ -857,11 +855,12 @@ } // Global completion differs based on the Opts that were passed. { - auto Results = Server - .codeComplete(FooCpp, GlobalCompletion.MarkerPos, - StringRef(GlobalCompletion.Text)) - .get() - .Value; + auto Results = + Server + .codeComplete(FooCpp, GlobalCompletion.MarkerPos, globalCtx(), + StringRef(GlobalCompletion.Text)) + .get() + .Value; // Class members. Should never be present in global completions. EXPECT_FALSE(ContainsItem(Results, MethodItemText)); @@ -895,13 +894,13 @@ }; clangd::CodeCompleteOptions CCOpts; - for (bool IncludeMacros : {true, false}){ + for (bool IncludeMacros : {true, false}) { CCOpts.IncludeMacros = IncludeMacros; - for (bool IncludeGlobals : {true, false}){ + for (bool IncludeGlobals : {true, false}) { CCOpts.IncludeGlobals = IncludeGlobals; - for (bool IncludeBriefComments : {true, false}){ + for (bool IncludeBriefComments : {true, false}) { CCOpts.IncludeBriefComments = IncludeBriefComments; - for (bool EnableSnippets : {true, false}){ + for (bool EnableSnippets : {true, false}) { CCOpts.EnableSnippets = EnableSnippets; for (bool IncludeCodePatterns : {true, false}) { CCOpts.IncludeCodePatterns = IncludeCodePatterns; @@ -1015,8 +1014,7 @@ MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); + clangd::CodeCompleteOptions()); // Prepare some random distributions for the test. std::random_device RandGen; @@ -1064,9 +1062,11 @@ auto AddDocument = [&](unsigned FileIndex) { bool ShouldHaveErrors = ShouldHaveErrorsDist(RandGen); - auto Future = Server.addDocument( - FilePaths[FileIndex], ShouldHaveErrors ? SourceContentsWithErrors - : SourceContentsWithoutErrors); + auto Future = + Server.addDocument(FilePaths[FileIndex], + ShouldHaveErrors ? SourceContentsWithErrors + : SourceContentsWithoutErrors, + emptyCtx()); UpdateStatsOnAddDocument(FileIndex, ShouldHaveErrors, std::move(Future)); }; @@ -1082,7 +1082,7 @@ if (ReqStats[FileIndex].FileIsRemoved) AddDocument(FileIndex); - auto Future = Server.forceReparse(FilePaths[FileIndex]); + auto Future = Server.forceReparse(FilePaths[FileIndex], emptyCtx()); UpdateStatsOnForceReparse(FileIndex, std::move(Future)); }; @@ -1092,7 +1092,7 @@ if (ReqStats[FileIndex].FileIsRemoved) AddDocument(FileIndex); - auto Future = Server.removeDocument(FilePaths[FileIndex]); + auto Future = Server.removeDocument(FilePaths[FileIndex], emptyCtx()); UpdateStatsOnRemoveDocument(FileIndex, std::move(Future)); }; @@ -1109,7 +1109,7 @@ // requests as opposed to AddDocument/RemoveDocument, which are implicitly // cancelled by any subsequent AddDocument/RemoveDocument request to the // same file. - Server.codeComplete(FilePaths[FileIndex], Pos).wait(); + Server.codeComplete(FilePaths[FileIndex], Pos, globalCtx()).wait(); }; auto FindDefinitionsRequest = [&]() { @@ -1119,7 +1119,8 @@ AddDocument(FileIndex); Position Pos{LineDist(RandGen), ColumnDist(RandGen)}; - ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos)); + ASSERT_TRUE( + !!Server.findDefinitions(FilePaths[FileIndex], Pos, globalCtx())); }; std::vector> AsyncRequests = { @@ -1176,8 +1177,7 @@ ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); + clangd::CodeCompleteOptions()); auto SourceContents = R"cpp( #include "foo.h" @@ -1303,12 +1303,12 @@ MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); ClangdServer Server(CDB, DiagConsumer, FS, 4, /*StorePreamblesInMemory=*/true, - clangd::CodeCompleteOptions(), - EmptyLogger::getInstance()); - Server.addDocument(FooCpp, SourceContentsWithErrors); + clangd::CodeCompleteOptions()); + Server.addDocument(FooCpp, SourceContentsWithErrors, emptyCtx()); StartSecondReparse.wait(); - auto Future = Server.addDocument(FooCpp, SourceContentsWithoutErrors); + auto Future = + Server.addDocument(FooCpp, SourceContentsWithoutErrors, emptyCtx()); Future.wait(); }