[clang-tools-extra] r323872 - [clangd] Pass Context implicitly using TLS.

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 31 08:59:51 PST 2018


This uses thread_local and broke at least bots whose runtimes don't support
it.

https://reviews.llvm.org/D42742 should fix this by using pthread where
possible, which should cover the affected platforms.

(Would like to avoid a revert because this patch touches/conflicts with
everything in clangd, and we also have out-of-tree dependencies...)

On Wed, Jan 31, 2018 at 2:40 PM, Sam McCall via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: sammccall
> Date: Wed Jan 31 05:40:48 2018
> New Revision: 323872
>
> URL: http://llvm.org/viewvc/llvm-project?rev=323872&view=rev
> Log:
> [clangd] Pass Context implicitly using TLS.
>
> Summary:
> Instead of passing Context explicitly around, we now have a thread-local
> Context object `Context::current()` which is an implicit argument to
> every function.
> Most manipulation of this should use the WithContextValue helper, which
> augments the current Context to add a single KV pair, and restores the
> old context on destruction.
>
> Advantages are:
> - less boilerplate in functions that just propagate contexts
> - reading most code doesn't require understanding context at all, and
>   using context as values in fewer places still
> - fewer options to pass the "wrong" context when it changes within a
>   scope (e.g. when using Span)
> - contexts pass through interfaces we can't modify, such as VFS
> - propagating contexts across threads was slightly tricky (e.g.
>   copy vs move, no move-init in lambdas), and is now encapsulated in
>   the threadpool
>
> Disadvantages are all the usual TLS stuff - hidden magic, and
> potential for higher memory usage on threads that don't use the
> context. (In practice, it's just one pointer)
>
> Reviewers: ilya-biryukov
>
> Subscribers: klimek, jkorous-apple, ioeric, cfe-commits
>
> Differential Revision: https://reviews.llvm.org/D42517
>
> Modified:
>     clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
>     clang-tools-extra/trunk/clangd/ClangdLSPServer.h
>     clang-tools-extra/trunk/clangd/ClangdServer.cpp
>     clang-tools-extra/trunk/clangd/ClangdServer.h
>     clang-tools-extra/trunk/clangd/ClangdUnit.cpp
>     clang-tools-extra/trunk/clangd/ClangdUnit.h
>     clang-tools-extra/trunk/clangd/CodeComplete.cpp
>     clang-tools-extra/trunk/clangd/CodeComplete.h
>     clang-tools-extra/trunk/clangd/Context.cpp
>     clang-tools-extra/trunk/clangd/Context.h
>     clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp
>     clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
>     clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
>     clang-tools-extra/trunk/clangd/Logger.cpp
>     clang-tools-extra/trunk/clangd/Logger.h
>     clang-tools-extra/trunk/clangd/Protocol.cpp
>     clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
>     clang-tools-extra/trunk/clangd/ProtocolHandlers.h
>     clang-tools-extra/trunk/clangd/TUScheduler.cpp
>     clang-tools-extra/trunk/clangd/TUScheduler.h
>     clang-tools-extra/trunk/clangd/Threading.cpp
>     clang-tools-extra/trunk/clangd/Threading.h
>     clang-tools-extra/trunk/clangd/Trace.cpp
>     clang-tools-extra/trunk/clangd/Trace.h
>     clang-tools-extra/trunk/clangd/XRefs.cpp
>     clang-tools-extra/trunk/clangd/XRefs.h
>     clang-tools-extra/trunk/clangd/index/FileIndex.cpp
>     clang-tools-extra/trunk/clangd/index/FileIndex.h
>     clang-tools-extra/trunk/clangd/index/Index.h
>     clang-tools-extra/trunk/clangd/index/MemIndex.cpp
>     clang-tools-extra/trunk/clangd/index/MemIndex.h
>     clang-tools-extra/trunk/clangd/index/Merge.cpp
>     clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
>     clang-tools-extra/trunk/unittests/clangd/ClangdUnitTests.cpp
>     clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
>     clang-tools-extra/trunk/unittests/clangd/FileIndexTests.cpp
>     clang-tools-extra/trunk/unittests/clangd/IndexTests.cpp
>     clang-tools-extra/trunk/unittests/clangd/TUSchedulerTests.cpp
>     clang-tools-extra/trunk/unittests/clangd/TraceTests.cpp
>     clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp
>
> Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ClangdLSPServer.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
> +++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Wed Jan 31
> 05:40:48 2018
> @@ -46,8 +46,8 @@ std::vector<TextEdit> replacementsToEdit
>
>  } // namespace
>
> -void ClangdLSPServer::onInitialize(Ctx C, InitializeParams &Params) {
> -  reply(C, json::obj{
> +void ClangdLSPServer::onInitialize(InitializeParams &Params) {
> +  reply(json::obj{
>        {{"capabilities",
>          json::obj{
>              {"textDocumentSync", 1},
> @@ -82,38 +82,35 @@ void ClangdLSPServer::onInitialize(Ctx C
>      Server.setRootPath(*Params.rootPath);
>  }
>
> -void ClangdLSPServer::onShutdown(Ctx C, ShutdownParams &Params) {
> +void ClangdLSPServer::onShutdown(ShutdownParams &Params) {
>    // Do essentially nothing, just say we're ready to exit.
>    ShutdownRequestReceived = true;
> -  reply(C, nullptr);
> +  reply(nullptr);
>  }
>
> -void ClangdLSPServer::onExit(Ctx C, ExitParams &Params) { IsDone = true; }
> +void ClangdLSPServer::onExit(ExitParams &Params) { IsDone = true; }
>
> -void ClangdLSPServer::onDocumentDidOpen(Ctx C,
> -                                        DidOpenTextDocumentParams
> &Params) {
> +void ClangdLSPServer::onDocumentDidOpen(DidOpenTextDocumentParams
> &Params) {
>    if (Params.metadata && !Params.metadata->extraFlags.empty())
>      CDB.setExtraFlagsForFile(Params.textDocument.uri.file,
>                               std::move(Params.metadata->extraFlags));
> -  Server.addDocument(std::move(C), Params.textDocument.uri.file,
> -                     Params.textDocument.text);
> +  Server.addDocument(Params.textDocument.uri.file,
> Params.textDocument.text);
>  }
>
> -void ClangdLSPServer::onDocumentDidChange(Ctx C,
> -                                          DidChangeTextDocumentParams
> &Params) {
> +void ClangdLSPServer::onDocumentDidChange(DidChangeTextDocumentParams
> &Params) {
>    if (Params.contentChanges.size() != 1)
> -    return replyError(C, ErrorCode::InvalidParams,
> +    return replyError(ErrorCode::InvalidParams,
>                        "can only apply one change at a time");
>    // We only support full syncing right now.
> -  Server.addDocument(std::move(C), Params.textDocument.uri.file,
> +  Server.addDocument(Params.textDocument.uri.file,
>                       Params.contentChanges[0].text);
>  }
>
> -void ClangdLSPServer::onFileEvent(Ctx C, DidChangeWatchedFilesParams
> &Params) {
> +void ClangdLSPServer::onFileEvent(DidChangeWatchedFilesParams &Params) {
>    Server.onFileEvent(Params);
>  }
>
> -void ClangdLSPServer::onCommand(Ctx C, ExecuteCommandParams &Params) {
> +void ClangdLSPServer::onCommand(ExecuteCommandParams &Params) {
>    if (Params.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND &&
>        Params.workspaceEdit) {
>      // The flow for "apply-fix" :
> @@ -127,31 +124,31 @@ void ClangdLSPServer::onCommand(Ctx C, E
>
>      ApplyWorkspaceEditParams ApplyEdit;
>      ApplyEdit.edit = *Params.workspaceEdit;
> -    reply(C, "Fix applied.");
> +    reply("Fix applied.");
>      // We don't need the response so id == 1 is OK.
>      // Ideally, we would wait for the response and if there is no error,
> we
>      // would reply success/failure to the original RPC.
> -    call(C, "workspace/applyEdit", ApplyEdit);
> +    call("workspace/applyEdit", ApplyEdit);
>    } else {
>      // We should not get here because ExecuteCommandParams would not have
>      // parsed in the first place and this handler should not be called.
> But if
>      // more commands are added, this will be here has a safe guard.
>      replyError(
> -        C, ErrorCode::InvalidParams,
> +        ErrorCode::InvalidParams,
>          llvm::formatv("Unsupported command \"{0}\".",
> Params.command).str());
>    }
>  }
>
> -void ClangdLSPServer::onRename(Ctx C, RenameParams &Params) {
> +void ClangdLSPServer::onRename(RenameParams &Params) {
>    auto File = Params.textDocument.uri.file;
>    auto Code = Server.getDocument(File);
>    if (!Code)
> -    return replyError(C, ErrorCode::InvalidParams,
> +    return replyError(ErrorCode::InvalidParams,
>                        "onRename called for non-added file");
>
> -  auto Replacements = Server.rename(C, File, Params.position,
> Params.newName);
> +  auto Replacements = Server.rename(File, Params.position,
> Params.newName);
>    if (!Replacements) {
> -    replyError(C, ErrorCode::InternalError,
> +    replyError(ErrorCode::InternalError,
>                 llvm::toString(Replacements.takeError()));
>      return;
>    }
> @@ -159,68 +156,66 @@ void ClangdLSPServer::onRename(Ctx C, Re
>    std::vector<TextEdit> Edits = replacementsToEdits(*Code, *Replacements);
>    WorkspaceEdit WE;
>    WE.changes = {{Params.textDocument.uri.uri(), Edits}};
> -  reply(C, WE);
> +  reply(WE);
>  }
>
> -void ClangdLSPServer::onDocumentDidClose(Ctx C,
> -                                         DidCloseTextDocumentParams
> &Params) {
> -  Server.removeDocument(std::move(C), Params.textDocument.uri.file);
> +void ClangdLSPServer::onDocumentDidClose(DidCloseTextDocumentParams
> &Params) {
> +  Server.removeDocument(Params.textDocument.uri.file);
>  }
>
>  void ClangdLSPServer::onDocumentOnTypeFormatting(
> -    Ctx C, DocumentOnTypeFormattingParams &Params) {
> +    DocumentOnTypeFormattingParams &Params) {
>    auto File = Params.textDocument.uri.file;
>    auto Code = Server.getDocument(File);
>    if (!Code)
> -    return replyError(C, ErrorCode::InvalidParams,
> +    return replyError(ErrorCode::InvalidParams,
>                        "onDocumentOnTypeFormatting called for non-added
> file");
>
>    auto ReplacementsOrError = Server.formatOnType(*Code, File,
> Params.position);
>    if (ReplacementsOrError)
> -    reply(C, json::ary(replacementsToEdits(*Code,
> ReplacementsOrError.get())));
> +    reply(json::ary(replacementsToEdits(*Code,
> ReplacementsOrError.get())));
>    else
> -    replyError(C, ErrorCode::UnknownErrorCode,
> +    replyError(ErrorCode::UnknownErrorCode,
>                 llvm::toString(ReplacementsOrError.takeError()));
>  }
>
>  void ClangdLSPServer::onDocumentRangeFormatting(
> -    Ctx C, DocumentRangeFormattingParams &Params) {
> +    DocumentRangeFormattingParams &Params) {
>    auto File = Params.textDocument.uri.file;
>    auto Code = Server.getDocument(File);
>    if (!Code)
> -    return replyError(C, ErrorCode::InvalidParams,
> +    return replyError(ErrorCode::InvalidParams,
>                        "onDocumentRangeFormatting called for non-added
> file");
>
>    auto ReplacementsOrError = Server.formatRange(*Code, File,
> Params.range);
>    if (ReplacementsOrError)
> -    reply(C, json::ary(replacementsToEdits(*Code,
> ReplacementsOrError.get())));
> +    reply(json::ary(replacementsToEdits(*Code,
> ReplacementsOrError.get())));
>    else
> -    replyError(C, ErrorCode::UnknownErrorCode,
> +    replyError(ErrorCode::UnknownErrorCode,
>                 llvm::toString(ReplacementsOrError.takeError()));
>  }
>
> -void ClangdLSPServer::onDocumentFormatting(Ctx C,
> -                                           DocumentFormattingParams
> &Params) {
> +void ClangdLSPServer::onDocumentFormatting(DocumentFormattingParams
> &Params) {
>    auto File = Params.textDocument.uri.file;
>    auto Code = Server.getDocument(File);
>    if (!Code)
> -    return replyError(C, ErrorCode::InvalidParams,
> +    return replyError(ErrorCode::InvalidParams,
>                        "onDocumentFormatting called for non-added file");
>
>    auto ReplacementsOrError = Server.formatFile(*Code, File);
>    if (ReplacementsOrError)
> -    reply(C, json::ary(replacementsToEdits(*Code,
> ReplacementsOrError.get())));
> +    reply(json::ary(replacementsToEdits(*Code,
> ReplacementsOrError.get())));
>    else
> -    replyError(C, ErrorCode::UnknownErrorCode,
> +    replyError(ErrorCode::UnknownErrorCode,
>                 llvm::toString(ReplacementsOrError.takeError()));
>  }
>
> -void ClangdLSPServer::onCodeAction(Ctx C, CodeActionParams &Params) {
> +void ClangdLSPServer::onCodeAction(CodeActionParams &Params) {
>    // We provide a code action for each diagnostic at the requested
> location
>    // which has FixIts available.
>    auto Code = Server.getDocument(Params.textDocument.uri.file);
>    if (!Code)
> -    return replyError(C, ErrorCode::InvalidParams,
> +    return replyError(ErrorCode::InvalidParams,
>                        "onCodeAction called for non-added file");
>
>    json::ary Commands;
> @@ -236,67 +231,53 @@ void ClangdLSPServer::onCodeAction(Ctx C
>        });
>      }
>    }
> -  reply(C, std::move(Commands));
> +  reply(std::move(Commands));
>  }
>
> -void ClangdLSPServer::onCompletion(Ctx C, TextDocumentPositionParams
> &Params) {
> -  auto Reply = Server
> -                   .codeComplete(std::move(C),
> Params.textDocument.uri.file,
> -                                 Position{Params.position.line,
> -                                          Params.position.character},
> -                                 CCOpts)
> -                   .get(); // FIXME(ibiryukov): This could be made async
> if we
> -                           // had an API that would allow to attach
> callbacks to
> -                           // futures returned by ClangdServer.
> -
> -  // We have std::move'd from C, now restore it from response of
> codeComplete.
> -  C = std::move(Reply.first);
> -  auto List = std::move(Reply.second.Value);
> -  reply(C, List);
> +void ClangdLSPServer::onCompletion(TextDocumentPositionParams &Params) {
> +  Server.codeComplete(Params.textDocument.uri.file,
> +                      Position{Params.position.line,
> Params.position.character},
> +                      CCOpts,
> +                      [](Tagged<CompletionList> List) {
> reply(List.Value); });
>  }
>
> -void ClangdLSPServer::onSignatureHelp(Ctx C,
> -                                      TextDocumentPositionParams &Params)
> {
> +void ClangdLSPServer::onSignatureHelp(TextDocumentPositionParams
> &Params) {
>    auto SignatureHelp = Server.signatureHelp(
> -      C, Params.textDocument.uri.file,
> +      Params.textDocument.uri.file,
>        Position{Params.position.line, Params.position.character});
>    if (!SignatureHelp)
> -    return replyError(C, ErrorCode::InvalidParams,
> +    return replyError(ErrorCode::InvalidParams,
>                        llvm::toString(SignatureHelp.takeError()));
> -  reply(C, SignatureHelp->Value);
> +  reply(SignatureHelp->Value);
>  }
>
> -void ClangdLSPServer::onGoToDefinition(Ctx C,
> -                                       TextDocumentPositionParams
> &Params) {
> +void ClangdLSPServer::onGoToDefinition(TextDocumentPositionParams
> &Params) {
>    auto Items = Server.findDefinitions(
> -      C, Params.textDocument.uri.file,
> +      Params.textDocument.uri.file,
>        Position{Params.position.line, Params.position.character});
>    if (!Items)
> -    return replyError(C, ErrorCode::InvalidParams,
> +    return replyError(ErrorCode::InvalidParams,
>                        llvm::toString(Items.takeError()));
> -  reply(C, json::ary(Items->Value));
> +  reply(json::ary(Items->Value));
>  }
>
> -void ClangdLSPServer::onSwitchSourceHeader(Ctx C,
> -                                           TextDocumentIdentifier
> &Params) {
> +void ClangdLSPServer::onSwitchSourceHeader(TextDocumentIdentifier
> &Params) {
>    llvm::Optional<Path> Result = Server.switchSourceHeader(
> Params.uri.file);
> -  reply(C, Result ? URI::createFile(*Result).toString() : "");
> +  reply(Result ? URI::createFile(*Result).toString() : "");
>  }
>
> -void ClangdLSPServer::onDocumentHighlight(Ctx C,
> -                                          TextDocumentPositionParams
> &Params) {
> -
> +void ClangdLSPServer::onDocumentHighlight(TextDocumentPositionParams
> &Params) {
>    auto Highlights = Server.findDocumentHighlights(
> -      C, Params.textDocument.uri.file,
> +      Params.textDocument.uri.file,
>        Position{Params.position.line, Params.position.character});
>
>    if (!Highlights) {
> -    replyError(C, ErrorCode::InternalError,
> +    replyError(ErrorCode::InternalError,
>                 llvm::toString(Highlights.takeError()));
>      return;
>    }
>
> -  reply(C, json::ary(Highlights->Value));
> +  reply(json::ary(Highlights->Value));
>  }
>
>  ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned
> AsyncThreadsCount,
> @@ -315,8 +296,8 @@ bool ClangdLSPServer::run(std::istream &
>    assert(!IsDone && "Run was called before");
>
>    // Set up JSONRPCDispatcher.
> -  JSONRPCDispatcher Dispatcher([](Context Ctx, const json::Expr &Params) {
> -    replyError(Ctx, ErrorCode::MethodNotFound, "method not found");
> +  JSONRPCDispatcher Dispatcher([](const json::Expr &Params) {
> +    replyError(ErrorCode::MethodNotFound, "method not found");
>    });
>    registerCallbackHandlers(Dispatcher, Out, /*Callbacks=*/*this);
>
> @@ -346,8 +327,7 @@ std::vector<TextEdit> ClangdLSPServer::g
>  }
>
>  void ClangdLSPServer::onDiagnosticsReady(
> -    const Context &Ctx, PathRef File,
> -    Tagged<std::vector<DiagWithFixIts>> Diagnostics) {
> +    PathRef File, Tagged<std::vector<DiagWithFixIts>> Diagnostics) {
>    json::ary DiagnosticsJSON;
>
>    DiagnosticToReplacementMap LocalFixIts; // Temporary storage
>
> Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ClangdLSPServer.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ClangdLSPServer.h (original)
> +++ clang-tools-extra/trunk/clangd/ClangdLSPServer.h Wed Jan 31 05:40:48
> 2018
> @@ -50,32 +50,30 @@ public:
>  private:
>    // Implement DiagnosticsConsumer.
>    virtual void
> -  onDiagnosticsReady(const Context &Ctx, PathRef File,
> +  onDiagnosticsReady(PathRef File,
>                       Tagged<std::vector<DiagWithFixIts>> Diagnostics)
> override;
>
>    // Implement ProtocolCallbacks.
> -  void onInitialize(Ctx C, InitializeParams &Params) override;
> -  void onShutdown(Ctx C, ShutdownParams &Params) override;
> -  void onExit(Ctx C, ExitParams &Params) override;
> -  void onDocumentDidOpen(Ctx C, DidOpenTextDocumentParams &Params)
> override;
> -  void onDocumentDidChange(Ctx C, DidChangeTextDocumentParams &Params)
> override;
> -  void onDocumentDidClose(Ctx C, DidCloseTextDocumentParams &Params)
> override;
> +  void onInitialize(InitializeParams &Params) override;
> +  void onShutdown(ShutdownParams &Params) override;
> +  void onExit(ExitParams &Params) override;
> +  void onDocumentDidOpen(DidOpenTextDocumentParams &Params) override;
> +  void onDocumentDidChange(DidChangeTextDocumentParams &Params) override;
> +  void onDocumentDidClose(DidCloseTextDocumentParams &Params) override;
>    void
> -  onDocumentOnTypeFormatting(Ctx C,
> -                             DocumentOnTypeFormattingParams &Params)
> override;
> +  onDocumentOnTypeFormatting(DocumentOnTypeFormattingParams &Params)
> override;
>    void
> -  onDocumentRangeFormatting(Ctx C,
> -                            DocumentRangeFormattingParams &Params)
> override;
> -  void onDocumentFormatting(Ctx C, DocumentFormattingParams &Params)
> override;
> -  void onCodeAction(Ctx C, CodeActionParams &Params) override;
> -  void onCompletion(Ctx C, TextDocumentPositionParams &Params) override;
> -  void onSignatureHelp(Ctx C, TextDocumentPositionParams &Params)
> override;
> -  void onGoToDefinition(Ctx C, TextDocumentPositionParams &Params)
> override;
> -  void onSwitchSourceHeader(Ctx C, TextDocumentIdentifier &Params)
> override;
> -  void onDocumentHighlight(Ctx C, TextDocumentPositionParams &Params)
> override;
> -  void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) override;
> -  void onCommand(Ctx C, ExecuteCommandParams &Params) override;
> -  void onRename(Ctx C, RenameParams &Parames) override;
> +  onDocumentRangeFormatting(DocumentRangeFormattingParams &Params)
> override;
> +  void onDocumentFormatting(DocumentFormattingParams &Params) override;
> +  void onCodeAction(CodeActionParams &Params) override;
> +  void onCompletion(TextDocumentPositionParams &Params) override;
> +  void onSignatureHelp(TextDocumentPositionParams &Params) override;
> +  void onGoToDefinition(TextDocumentPositionParams &Params) override;
> +  void onSwitchSourceHeader(TextDocumentIdentifier &Params) override;
> +  void onDocumentHighlight(TextDocumentPositionParams &Params) override;
> +  void onFileEvent(DidChangeWatchedFilesParams &Params) override;
> +  void onCommand(ExecuteCommandParams &Params) override;
> +  void onRename(RenameParams &Parames) override;
>
>    std::vector<TextEdit> getFixIts(StringRef File, const
> clangd::Diagnostic &D);
>
>
> Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ClangdServer.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)
> +++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Wed Jan 31 05:40:48
> 2018
> @@ -116,11 +116,11 @@ ClangdServer::ClangdServer(GlobalCompila
>        // is parsed.
>        // FIXME(ioeric): this can be slow and we may be able to index on
> less
>        // critical paths.
> -      WorkScheduler(
> -          AsyncThreadsCount, StorePreamblesInMemory,
> -          FileIdx ? [this](const Context &Ctx, PathRef Path,
> -                           ParsedAST *AST) { FileIdx->update(Ctx, Path,
> AST); }
> -                  : ASTParsedCallback()) {
> +      WorkScheduler(AsyncThreadsCount, StorePreamblesInMemory,
> +                    FileIdx
> +                        ? [this](PathRef Path,
> +                                 ParsedAST *AST) { FileIdx->update(Path,
> AST); }
> +                        : ASTParsedCallback()) {
>    if (FileIdx && StaticIdx) {
>      MergedIndex = mergeIndex(FileIdx.get(), StaticIdx);
>      Index = MergedIndex.get();
> @@ -139,35 +139,33 @@ void ClangdServer::setRootPath(PathRef R
>      this->RootPath = NewRootPath;
>  }
>
> -std::future<Context> ClangdServer::addDocument(Context Ctx, PathRef File,
> -                                               StringRef Contents) {
> +std::future<void> ClangdServer::addDocument(PathRef File, StringRef
> Contents) {
>    DocVersion Version = DraftMgr.updateDraft(File, Contents);
>    auto TaggedFS = FSProvider.getTaggedFileSystem(File);
> -  return scheduleReparseAndDiags(std::move(Ctx), File,
> -                                 VersionedDraft{Version, Contents.str()},
> +  return scheduleReparseAndDiags(File, VersionedDraft{Version,
> Contents.str()},
>                                   std::move(TaggedFS));
>  }
>
> -std::future<Context> ClangdServer::removeDocument(Context Ctx, PathRef
> File) {
> +std::future<void> ClangdServer::removeDocument(PathRef File) {
>    DraftMgr.removeDraft(File);
>    CompileArgs.invalidate(File);
>
> -  std::promise<Context> DonePromise;
> -  std::future<Context> DoneFuture = DonePromise.get_future();
> +  std::promise<void> DonePromise;
> +  std::future<void> DoneFuture = DonePromise.get_future();
>
>    auto Callback = BindWithForward(
> -      [](Context Ctx, std::promise<Context> DonePromise, llvm::Error Err)
> {
> +      [](std::promise<void> DonePromise, llvm::Error Err) {
>          if (Err)
>            ignoreError(std::move(Err));
> -        DonePromise.set_value(std::move(Ctx));
> +        DonePromise.set_value();
>        },
> -      std::move(Ctx), std::move(DonePromise));
> +      std::move(DonePromise));
>
>    WorkScheduler.remove(File, std::move(Callback));
>    return DoneFuture;
>  }
>
> -std::future<Context> ClangdServer::forceReparse(Context Ctx, PathRef
> File) {
> +std::future<void> ClangdServer::forceReparse(PathRef File) {
>    auto FileContents = DraftMgr.getDraft(File);
>    assert(FileContents.Draft &&
>           "forceReparse() was called for non-added document");
> @@ -177,38 +175,34 @@ std::future<Context> ClangdServer::force
>    CompileArgs.invalidate(File);
>
>    auto TaggedFS = FSProvider.getTaggedFileSystem(File);
> -  return scheduleReparseAndDiags(std::move(Ctx), File,
> std::move(FileContents),
> +  return scheduleReparseAndDiags(File, std::move(FileContents),
>                                   std::move(TaggedFS));
>  }
>
> -std::future<std::pair<Context, Tagged<CompletionList>>>
> -ClangdServer::codeComplete(Context Ctx, PathRef File, Position Pos,
> +std::future<Tagged<CompletionList>>
> +ClangdServer::codeComplete(PathRef File, Position Pos,
>                             const clangd::CodeCompleteOptions &Opts,
>                             llvm::Optional<StringRef> OverridenContents,
>                             IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
> -  using ResultType = std::pair<Context, Tagged<CompletionList>>;
> -
> -  std::promise<ResultType> ResultPromise;
> -
> -  auto Callback = [](std::promise<ResultType> ResultPromise, Context Ctx,
> +  std::promise<Tagged<CompletionList>> ResultPromise;
> +  auto Callback = [](std::promise<Tagged<CompletionList>> ResultPromise,
>                       Tagged<CompletionList> Result) -> void {
> -    ResultPromise.set_value({std::move(Ctx), std::move(Result)});
> +    ResultPromise.set_value(std::move(Result));
>    };
>
> -  std::future<ResultType> ResultFuture = ResultPromise.get_future();
> -  codeComplete(std::move(Ctx), File, Pos, Opts,
> +  auto ResultFuture = ResultPromise.get_future();
> +  codeComplete(File, Pos, Opts,
>                 BindWithForward(Callback, std::move(ResultPromise)),
>                 OverridenContents, UsedFS);
>    return ResultFuture;
>  }
>
>  void ClangdServer::codeComplete(
> -    Context Ctx, PathRef File, Position Pos,
> -    const clangd::CodeCompleteOptions &Opts,
> -    UniqueFunction<void(Context, Tagged<CompletionList>)> Callback,
> +    PathRef File, Position Pos, const clangd::CodeCompleteOptions &Opts,
> +    UniqueFunction<void(Tagged<CompletionList>)> Callback,
>      llvm::Optional<StringRef> OverridenContents,
>      IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
> -  using CallbackType = UniqueFunction<void(Context,
> Tagged<CompletionList>)>;
> +  using CallbackType = UniqueFunction<void(Tagged<CompletionList>)>;
>
>    auto TaggedFS = FSProvider.getTaggedFileSystem(File);
>    if (UsedFS)
> @@ -231,8 +225,8 @@ void ClangdServer::codeComplete(
>    // Copy PCHs to avoid accessing this->PCHs concurrently
>    std::shared_ptr<PCHContainerOperations> PCHs = this->PCHs;
>    auto Task = [PCHs, Pos, TaggedFS, CodeCompleteOpts](
> -                  Context Ctx, std::string Contents, Path File,
> -                  CallbackType Callback, llvm::Expected<InputsAndPreamble>
> IP) {
> +                  std::string Contents, Path File, CallbackType Callback,
> +                  llvm::Expected<InputsAndPreamble> IP) {
>      assert(IP && "error when trying to read preamble for codeComplete");
>      auto PreambleData = IP->Preamble;
>      auto &Command = IP->Inputs.CompileCommand;
> @@ -240,20 +234,19 @@ void ClangdServer::codeComplete(
>      // FIXME(ibiryukov): even if Preamble is non-null, we may want to
> check
>      // both the old and the new version in case only one of them matches.
>      CompletionList Result = clangd::codeComplete(
> -        Ctx, File, Command, PreambleData ? &PreambleData->Preamble :
> nullptr,
> +        File, Command, PreambleData ? &PreambleData->Preamble : nullptr,
>          Contents, Pos, TaggedFS.Value, PCHs, CodeCompleteOpts);
>
> -    Callback(std::move(Ctx),
> -             make_tagged(std::move(Result), std::move(TaggedFS.Tag)));
> +    Callback(make_tagged(std::move(Result), std::move(TaggedFS.Tag)));
>    };
>
> -  WorkScheduler.runWithPreamble(
> -      File, BindWithForward(Task, std::move(Ctx), std::move(Contents),
> -                            File.str(), std::move(Callback)));
> +  WorkScheduler.runWithPreamble(File, BindWithForward(Task,
> std::move(Contents),
> +                                                      File.str(),
> +
> std::move(Callback)));
>  }
>
>  llvm::Expected<Tagged<SignatureHelp>>
> -ClangdServer::signatureHelp(const Context &Ctx, PathRef File, Position
> Pos,
> +ClangdServer::signatureHelp(PathRef File, Position Pos,
>                              llvm::Optional<StringRef> OverridenContents,
>                              IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS)
> {
>    auto TaggedFS = FSProvider.getTaggedFileSystem(File);
> @@ -272,7 +265,7 @@ ClangdServer::signatureHelp(const Contex
>      Contents = std::move(*Latest.Draft);
>    }
>
> -  auto Action = [=, &Ctx](llvm::Expected<InputsAndPreamble> IP)
> +  auto Action = [=](llvm::Expected<InputsAndPreamble> IP)
>        -> Expected<Tagged<SignatureHelp>> {
>      if (!IP)
>        return IP.takeError();
> @@ -280,7 +273,7 @@ ClangdServer::signatureHelp(const Contex
>      auto &Command = IP->Inputs.CompileCommand;
>
>      return make_tagged(
> -        clangd::signatureHelp(Ctx, File, Command,
> +        clangd::signatureHelp(File, Command,
>                                PreambleData ? &PreambleData->Preamble :
> nullptr,
>                                Contents, Pos, TaggedFS.Value, PCHs),
>          TaggedFS.Tag);
> @@ -316,8 +309,7 @@ ClangdServer::formatOnType(StringRef Cod
>  }
>
>  Expected<std::vector<tooling::Replacement>>
> -ClangdServer::rename(const Context &Ctx, PathRef File, Position Pos,
> -                     llvm::StringRef NewName) {
> +ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName)
> {
>    using RetType = Expected<std::vector<tooling::Replacement>>;
>    auto Action = [=](Expected<InputsAndAST> InpAST) -> RetType {
>      if (!InpAST)
> @@ -396,14 +388,14 @@ std::string ClangdServer::dumpAST(PathRe
>  }
>
>  llvm::Expected<Tagged<std::vector<Location>>>
> -ClangdServer::findDefinitions(const Context &Ctx, PathRef File, Position
> Pos) {
> +ClangdServer::findDefinitions(PathRef File, Position Pos) {
>    auto TaggedFS = FSProvider.getTaggedFileSystem(File);
>
>    using RetType = llvm::Expected<Tagged<std::vector<Location>>>;
> -  auto Action = [=, &Ctx](llvm::Expected<InputsAndAST> InpAST) ->
> RetType {
> +  auto Action = [=](llvm::Expected<InputsAndAST> InpAST) -> RetType {
>      if (!InpAST)
>        return InpAST.takeError();
> -    auto Result = clangd::findDefinitions(Ctx, InpAST->AST, Pos);
> +    auto Result = clangd::findDefinitions(InpAST->AST, Pos);
>      return make_tagged(std::move(Result), TaggedFS.Tag);
>    };
>    return blockingRunWithAST<RetType>(WorkScheduler, File, Action);
> @@ -483,8 +475,7 @@ ClangdServer::formatCode(llvm::StringRef
>  }
>
>  llvm::Expected<Tagged<std::vector<DocumentHighlight>>>
> -ClangdServer::findDocumentHighlights(const Context &Ctx, PathRef File,
> -                                     Position Pos) {
> +ClangdServer::findDocumentHighlights(PathRef File, Position Pos) {
>    auto FileContents = DraftMgr.getDraft(File);
>    if (!FileContents.Draft)
>      return llvm::make_error<llvm::StringError>(
> @@ -494,17 +485,17 @@ ClangdServer::findDocumentHighlights(con
>    auto TaggedFS = FSProvider.getTaggedFileSystem(File);
>
>    using RetType = llvm::Expected<Tagged<std::vector<DocumentHighlight>>>;
> -  auto Action = [=, &Ctx](llvm::Expected<InputsAndAST> InpAST) ->
> RetType {
> +  auto Action = [=](llvm::Expected<InputsAndAST> InpAST) -> RetType {
>      if (!InpAST)
>        return InpAST.takeError();
> -    auto Result = clangd::findDocumentHighlights(Ctx, InpAST->AST, Pos);
> +    auto Result = clangd::findDocumentHighlights(InpAST->AST, Pos);
>      return make_tagged(std::move(Result), TaggedFS.Tag);
>    };
>    return blockingRunWithAST<RetType>(WorkScheduler, File, Action);
>  }
>
> -std::future<Context> ClangdServer::scheduleReparseAndDiags(
> -    Context Ctx, PathRef File, VersionedDraft Contents,
> +std::future<void> ClangdServer::scheduleReparseAndDiags(
> +    PathRef File, VersionedDraft Contents,
>      Tagged<IntrusiveRefCntPtr<vfs::FileSystem>> TaggedFS) {
>    tooling::CompileCommand Command = CompileArgs.getCompileCommand(File);
>
> @@ -514,14 +505,12 @@ std::future<Context> ClangdServer::sched
>    Path FileStr = File.str();
>    VFSTag Tag = std::move(TaggedFS.Tag);
>
> -  std::promise<Context> DonePromise;
> -  std::future<Context> DoneFuture = DonePromise.get_future();
> +  std::promise<void> DonePromise;
> +  std::future<void> DoneFuture = DonePromise.get_future();
>
> -  auto Callback = [this, Version, FileStr,
> -                   Tag](std::promise<Context> DonePromise, Context Ctx,
> -                        OptDiags Diags) {
> -    auto Guard =
> -        llvm::make_scope_exit([&]() { DonePromise.set_value(std::move(Ctx));
> });
> +  auto Callback = [this, Version, FileStr, Tag](std::promise<void>
> DonePromise,
> +                                                OptDiags Diags) {
> +    auto Guard = llvm::make_scope_exit([&]() { DonePromise.set_value();
> });
>      if (!Diags)
>        return; // A new reparse was requested before this one completed.
>
> @@ -538,10 +527,10 @@ std::future<Context> ClangdServer::sched
>      LastReportedDiagsVersion = Version;
>
>      DiagConsumer.onDiagnosticsReady(
> -        Ctx, FileStr, make_tagged(std::move(*Diags), std::move(Tag)));
> +        FileStr, make_tagged(std::move(*Diags), std::move(Tag)));
>    };
>
> -  WorkScheduler.update(std::move(Ctx), File,
> +  WorkScheduler.update(File,
>                         ParseInputs{std::move(Command),
>                                     std::move(TaggedFS.Value),
>                                     std::move(*Contents.Draft)},
>
> Modified: clang-tools-extra/trunk/clangd/ClangdServer.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ClangdServer.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ClangdServer.h (original)
> +++ clang-tools-extra/trunk/clangd/ClangdServer.h Wed Jan 31 05:40:48 2018
> @@ -71,7 +71,7 @@ public:
>
>    /// Called by ClangdServer when \p Diagnostics for \p File are ready.
>    virtual void
> -  onDiagnosticsReady(const Context &Ctx, PathRef File,
> +  onDiagnosticsReady(PathRef File,
>                       Tagged<std::vector<DiagWithFixIts>> Diagnostics) =
> 0;
>  };
>
> @@ -95,8 +95,6 @@ public:
>    getTaggedFileSystem(PathRef File) override;
>  };
>
> -class ClangdServer;
> -
>  /// Provides API to manage ASTs for a collection of C++ files and request
>  /// various language features.
>  /// Currently supports async diagnostics, code completion, formatting and
> goto
> @@ -156,30 +154,26 @@ public:
>    /// diagnostics) is finished.
>    /// FIXME: don't return futures here, LSP does not require a response
> for this
>    /// request.
> -  std::future<Context> addDocument(Context Ctx, PathRef File,
> -                                   StringRef Contents);
> +  std::future<void> addDocument(PathRef File, StringRef Contents);
> +
>    /// 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.
>    /// FIXME: don't return futures here, LSP does not require a response
> for this
>    /// request.
> -  std::future<Context> removeDocument(Context Ctx, PathRef File);
> +  std::future<void> removeDocument(PathRef File);
> +
>    /// 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.
>    /// FIXME: don't return futures here, LSP does not require a response
> for this
>    /// request.
> -  std::future<Context> forceReparse(Context Ctx, PathRef File);
> +  std::future<void> forceReparse(PathRef File);
>
> -  /// DEPRECATED. Please use a callback-based version, this API is
> deprecated
> -  /// and will soon be removed.
> -  ///
>    /// Run code completion for \p File at \p Pos.
> -  ///
> -  /// Request is processed asynchronously. You can use the returned
> future to
> -  /// wait for the results of the async request.
> +  /// Request is processed asynchronously.
>    ///
>    /// If \p OverridenContents is not None, they will used only for code
>    /// completion, i.e. no diagnostics update will be scheduled and a
> draft for
> @@ -190,18 +184,18 @@ public:
>    /// 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.
> -  std::future<std::pair<Context, Tagged<CompletionList>>>
> -  codeComplete(Context Ctx, PathRef File, Position Pos,
> -               const clangd::CodeCompleteOptions &Opts,
> -               llvm::Optional<StringRef> OverridenContents = llvm::None,
> -               IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
> -
>    /// A version of `codeComplete` that runs \p Callback on the processing
> thread
>    /// when codeComplete results become available.
> -  void
> -  codeComplete(Context Ctx, PathRef File, Position Pos,
> +  void codeComplete(PathRef File, Position Pos,
> +                    const clangd::CodeCompleteOptions &Opts,
> +                    UniqueFunction<void(Tagged<CompletionList>)>
> Callback,
> +                    llvm::Optional<StringRef> OverridenContents =
> llvm::None,
> +                    IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS =
> nullptr);
> +
> +  /// DEPRECATED: Please use the callback-based version of codeComplete.
> +  std::future<Tagged<CompletionList>>
> +  codeComplete(PathRef File, Position Pos,
>                 const clangd::CodeCompleteOptions &Opts,
> -               UniqueFunction<void(Context, Tagged<CompletionList>)>
> Callback,
>                 llvm::Optional<StringRef> OverridenContents = llvm::None,
>                 IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
>
> @@ -213,13 +207,13 @@ public:
>    /// vfs::FileSystem used for signature help. This method should only be
> called
>    /// for currently tracked files.
>    llvm::Expected<Tagged<SignatureHelp>>
> -  signatureHelp(const Context &Ctx, PathRef File, Position Pos,
> +  signatureHelp(PathRef File, Position Pos,
>                  llvm::Optional<StringRef> OverridenContents = llvm::None,
>                  IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
>
>    /// Get definition of symbol at a specified \p Line and \p Column in \p
> File.
> -  llvm::Expected<Tagged<std::vector<Location>>>
> -  findDefinitions(const Context &Ctx, PathRef File, Position Pos);
> +  llvm::Expected<Tagged<std::vector<Location>>> findDefinitions(PathRef
> File,
> +                                                                Position
> Pos);
>
>    /// Helper function that returns a path to the corresponding source
> file when
>    /// given a header file and vice versa.
> @@ -227,7 +221,7 @@ public:
>
>    /// Get document highlights for a given position.
>    llvm::Expected<Tagged<std::vector<DocumentHighlight>>>
> -  findDocumentHighlights(const Context &Ctx, PathRef File, Position Pos);
> +  findDocumentHighlights(PathRef File, Position Pos);
>
>    /// Run formatting for \p Rng inside \p File with content \p Code.
>    llvm::Expected<tooling::Replacements> formatRange(StringRef Code,
> @@ -244,8 +238,7 @@ public:
>
>    /// Rename all occurrences of the symbol at the \p Pos in \p File to
>    /// \p NewName.
> -  Expected<std::vector<tooling::Replacement>> rename(const Context &Ctx,
> -                                                     PathRef File,
> Position Pos,
> +  Expected<std::vector<tooling::Replacement>> rename(PathRef File,
> Position Pos,
>                                                       llvm::StringRef
> NewName);
>
>    /// Gets current document contents for \p File. Returns None if \p File
> is not
> @@ -277,8 +270,8 @@ private:
>    formatCode(llvm::StringRef Code, PathRef File,
>               ArrayRef<tooling::Range> Ranges);
>
> -  std::future<Context>
> -  scheduleReparseAndDiags(Context Ctx, PathRef File, VersionedDraft
> Contents,
> +  std::future<void>
> +  scheduleReparseAndDiags(PathRef File, VersionedDraft Contents,
>                            Tagged<IntrusiveRefCntPtr<vfs::FileSystem>>
> TaggedFS);
>
>    CompileArgsCache CompileArgs;
>
> Modified: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ClangdUnit.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (original)
> +++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp Wed Jan 31 05:40:48 2018
> @@ -229,8 +229,7 @@ void clangd::dumpAST(ParsedAST &AST, llv
>  }
>
>  llvm::Optional<ParsedAST>
> -ParsedAST::Build(const Context &Ctx,
> -                 std::unique_ptr<clang::CompilerInvocation> CI,
> +ParsedAST::Build(std::unique_ptr<clang::CompilerInvocation> CI,
>                   std::shared_ptr<const PreambleData> Preamble,
>                   std::unique_ptr<llvm::MemoryBuffer> Buffer,
>                   std::shared_ptr<PCHContainerOperations> PCHs,
> @@ -254,12 +253,12 @@ ParsedAST::Build(const Context &Ctx,
>    auto Action = llvm::make_unique<ClangdFrontendAction>();
>    const FrontendInputFile &MainInput = Clang->getFrontendOpts().
> Inputs[0];
>    if (!Action->BeginSourceFile(*Clang, MainInput)) {
> -    log(Ctx, "BeginSourceFile() failed when building AST for " +
> -                 MainInput.getFile());
> +    log("BeginSourceFile() failed when building AST for " +
> +        MainInput.getFile());
>      return llvm::None;
>    }
>    if (!Action->Execute())
> -    log(Ctx, "Execute() failed when building AST for " +
> MainInput.getFile());
> +    log("Execute() failed when building AST for " + MainInput.getFile());
>
>    // UnitDiagsConsumer is local, we can not store it in CompilerInstance
> that
>    // has a longer lifetime.
> @@ -387,8 +386,7 @@ CppFile::CppFile(PathRef FileName, bool
>        RebuildCounter(0), RebuildInProgress(false), ASTMemUsage(0),
>        PreambleMemUsage(0), PCHs(std::move(PCHs)),
>        ASTCallback(std::move(ASTCallback)) {
> -  // FIXME(ibiryukov): we should pass a proper Context here.
> -  log(Context::empty(), "Created CppFile for " + FileName);
> +  log("Created CppFile for " + FileName);
>
>    std::lock_guard<std::mutex> Lock(Mutex);
>    LatestAvailablePreamble = nullptr;
> @@ -442,11 +440,11 @@ UniqueFunction<void()> CppFile::deferCan
>  }
>
>  llvm::Optional<std::vector<DiagWithFixIts>>
> -CppFile::rebuild(const Context &Ctx, ParseInputs &&Inputs) {
> -  return deferRebuild(std::move(Inputs))(Ctx);
> +CppFile::rebuild(ParseInputs &&Inputs) {
> +  return deferRebuild(std::move(Inputs))();
>  }
>
> -UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>(const Context
> &)>
> +UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
>  CppFile::deferRebuild(ParseInputs &&Inputs) {
>    std::shared_ptr<const PreambleData> OldPreamble;
>    std::shared_ptr<PCHContainerOperations> PCHs;
> @@ -483,13 +481,11 @@ CppFile::deferRebuild(ParseInputs &&Inpu
>    std::shared_ptr<CppFile> That = shared_from_this();
>    auto FinishRebuild =
>        [OldPreamble, RequestRebuildCounter, PCHs,
> -       That](ParseInputs Inputs,
> -             const Context &Ctx) mutable /* to allow changing
> OldPreamble. */
> +       That](ParseInputs Inputs) mutable /* to allow changing
> OldPreamble. */
>        -> llvm::Optional<std::vector<DiagWithFixIts>> {
> -    log(Context::empty(),
> -        "Rebuilding file " + That->FileName + " with command [" +
> -            Inputs.CompileCommand.Directory + "] " +
> -            llvm::join(Inputs.CompileCommand.CommandLine, " "));
> +    log("Rebuilding file " + That->FileName + " with command [" +
> +        Inputs.CompileCommand.Directory + "] " +
> +        llvm::join(Inputs.CompileCommand.CommandLine, " "));
>
>      // Only one execution of this method is possible at a time.
>      // RebuildGuard will wait for any ongoing rebuilds to finish and will
> put us
> @@ -532,16 +528,16 @@ CppFile::deferRebuild(ParseInputs &&Inpu
>        if (OldPreamble &&
>            OldPreamble->Preamble.CanReuse(*CI, ContentsBuffer.get(),
> Bounds,
>                                           Inputs.FS.get())) {
> -        log(Ctx, "Reusing preamble for file " + Twine(That->FileName));
> +        log("Reusing preamble for file " + Twine(That->FileName));
>          return OldPreamble;
>        }
> -      log(Ctx, "Premble for file " + Twine(That->FileName) +
> -                   " cannot be reused. Attempting to rebuild it.");
> +      log("Premble for file " + Twine(That->FileName) +
> +          " cannot be reused. Attempting to rebuild it.");
>        // We won't need the OldPreamble anymore, release it so it can be
>        // deleted (if there are no other references to it).
>        OldPreamble.reset();
>
> -      trace::Span Tracer(Ctx, "Preamble");
> +      trace::Span Tracer("Preamble");
>        SPAN_ATTACH(Tracer, "File", That->FileName);
>        std::vector<DiagWithFixIts> PreambleDiags;
>        StoreDiagsConsumer PreambleDiagnosticsConsumer(/*ref*/
> PreambleDiags);
> @@ -566,17 +562,15 @@ CppFile::deferRebuild(ParseInputs &&Inpu
>        CI->getFrontendOpts().SkipFunctionBodies = false;
>
>        if (BuiltPreamble) {
> -        log(Tracer.Ctx, "Built preamble of size " +
> -                            Twine(BuiltPreamble->getSize()) + " for file
> " +
> -                            Twine(That->FileName));
> +        log("Built preamble of size " + Twine(BuiltPreamble->getSize()) +
> +            " for file " + Twine(That->FileName));
>
>          return std::make_shared<PreambleData>(
>              std::move(*BuiltPreamble),
>              SerializedDeclsCollector.takeTopLevelDeclIDs(),
>              std::move(PreambleDiags));
>        } else {
> -        log(Tracer.Ctx,
> -            "Could not build a preamble for file " +
> Twine(That->FileName));
> +        log("Could not build a preamble for file " +
> Twine(That->FileName));
>          return nullptr;
>        }
>      };
> @@ -606,18 +600,17 @@ CppFile::deferRebuild(ParseInputs &&Inpu
>      // Compute updated AST.
>      llvm::Optional<ParsedAST> NewAST;
>      {
> -      trace::Span Tracer(Ctx, "Build");
> +      trace::Span Tracer("Build");
>        SPAN_ATTACH(Tracer, "File", That->FileName);
> -      NewAST =
> -          ParsedAST::Build(Tracer.Ctx, std::move(CI),
> std::move(NewPreamble),
> -                           std::move(ContentsBuffer), PCHs, Inputs.FS);
> +      NewAST = ParsedAST::Build(std::move(CI), std::move(NewPreamble),
> +                                std::move(ContentsBuffer), PCHs,
> Inputs.FS);
>      }
>
>      if (NewAST) {
>        Diagnostics.insert(Diagnostics.end(), NewAST->getDiagnostics().
> begin(),
>                           NewAST->getDiagnostics().end());
>        if (That->ASTCallback)
> -        That->ASTCallback(Ctx, That->FileName, NewAST.getPointer());
> +        That->ASTCallback(That->FileName, NewAST.getPointer());
>      } else {
>        // Don't report even Preamble diagnostics if we coulnd't build AST.
>        Diagnostics.clear();
>
> Modified: clang-tools-extra/trunk/clangd/ClangdUnit.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ClangdUnit.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ClangdUnit.h (original)
> +++ clang-tools-extra/trunk/clangd/ClangdUnit.h Wed Jan 31 05:40:48 2018
> @@ -10,7 +10,6 @@
>  #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"
> @@ -71,7 +70,7 @@ public:
>    /// Attempts to run Clang and store parsed AST. If \p Preamble is
> non-null
>    /// it is reused during parsing.
>    static llvm::Optional<ParsedAST>
> -  Build(const Context &Ctx, std::unique_ptr<clang::CompilerInvocation>
> CI,
> +  Build(std::unique_ptr<clang::CompilerInvocation> CI,
>          std::shared_ptr<const PreambleData> Preamble,
>          std::unique_ptr<llvm::MemoryBuffer> Buffer,
>          std::shared_ptr<PCHContainerOperations> PCHs,
> @@ -148,8 +147,7 @@ private:
>    mutable llvm::Optional<ParsedAST> AST;
>  };
>
> -using ASTParsedCallback =
> -    std::function<void(const Context &Ctx, PathRef Path, ParsedAST *)>;
> +using ASTParsedCallback = std::function<void(PathRef Path, ParsedAST *)>;
>
>  /// Manages resources, required by clangd. Allows to rebuild file with new
>  /// contents, and provides AST and Preamble for it.
> @@ -186,8 +184,7 @@ public:
>    /// Returns a list of diagnostics or a llvm::None, if another rebuild
> was
>    /// requested in parallel (effectively cancelling this rebuild) before
>    /// diagnostics were produced.
> -  llvm::Optional<std::vector<DiagWithFixIts>> rebuild(const Context &Ctx,
> -                                                      ParseInputs
> &&Inputs);
> +  llvm::Optional<std::vector<DiagWithFixIts>> rebuild(ParseInputs
> &&Inputs);
>
>    /// Schedule a rebuild and return a deferred computation that will
> finish the
>    /// rebuild, that can be called on a different thread.
> @@ -203,7 +200,7 @@ public:
>    /// 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<llvm::Optional<std::vector<DiagWithFixIts>>(const
> Context &)>
> +  UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
>    deferRebuild(ParseInputs &&Inputs);
>
>    /// Returns a future to get the most fresh PreambleData for a file. The
>
> Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/CodeComplete.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original)
> +++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Wed Jan 31 05:40:48
> 2018
> @@ -633,12 +633,11 @@ struct SemaCompleteInput {
>
>  // Invokes Sema code completion on a file.
>  // Callback will be invoked once completion is done, but before cleaning
> up.
> -bool semaCodeComplete(const Context &Ctx,
> -                      std::unique_ptr<CodeCompleteConsumer> Consumer,
> +bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
>                        const clang::CodeCompleteOptions &Options,
>                        const SemaCompleteInput &Input,
>                        llvm::function_ref<void()> Callback = nullptr) {
> -  auto Tracer = llvm::make_unique<trace::Span>(Ctx, "Sema completion");
> +  auto Tracer = llvm::make_unique<trace::Span>("Sema completion");
>    std::vector<const char *> ArgStrs;
>    for (const auto &S : Input.Command.CommandLine)
>      ArgStrs.push_back(S.c_str());
> @@ -690,13 +689,12 @@ bool semaCodeComplete(const Context &Ctx
>
>    SyntaxOnlyAction Action;
>    if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
> {
> -    log(Ctx, "BeginSourceFile() failed when running codeComplete for " +
> -                 Input.FileName);
> +    log("BeginSourceFile() failed when running codeComplete for " +
> +        Input.FileName);
>      return false;
>    }
>    if (!Action.Execute()) {
> -    log(Ctx,
> -        "Execute() failed when running codeComplete for " +
> Input.FileName);
> +    log("Execute() failed when running codeComplete for " +
> Input.FileName);
>      return false;
>    }
>    Tracer.reset();
> @@ -704,7 +702,7 @@ bool semaCodeComplete(const Context &Ctx
>    if (Callback)
>      Callback();
>
> -  Tracer = llvm::make_unique<trace::Span>(Ctx, "Sema completion
> cleanup");
> +  Tracer = llvm::make_unique<trace::Span>("Sema completion cleanup");
>    Action.EndSourceFile();
>
>    return true;
> @@ -801,8 +799,6 @@ clang::CodeCompleteOptions CodeCompleteO
>  //     This score is combined with the result quality score for the final
> score.
>  //   - TopN determines the results with the best score.
>  class CodeCompleteFlow {
> -  trace::Span Tracer;
> -  const Context &Ctx;
>    const CodeCompleteOptions &Opts;
>    // Sema takes ownership of Recorder. Recorder is valid until Sema
> cleanup.
>    std::unique_ptr<CompletionRecorder> RecorderOwner;
> @@ -813,21 +809,22 @@ class CodeCompleteFlow {
>
>  public:
>    // A CodeCompleteFlow object is only useful for calling run() exactly
> once.
> -  CodeCompleteFlow(const Context &Ctx, const CodeCompleteOptions &Opts)
> -      : Tracer(Ctx, "CodeCompleteFlow"), Ctx(Tracer.Ctx), Opts(Opts),
> -        RecorderOwner(new CompletionRecorder(Opts)),
> Recorder(*RecorderOwner) {}
> +  CodeCompleteFlow(const CodeCompleteOptions &Opts)
> +      : Opts(Opts), RecorderOwner(new CompletionRecorder(Opts)),
> +        Recorder(*RecorderOwner) {}
>
>    CompletionList run(const SemaCompleteInput &SemaCCInput) && {
> +    trace::Span Tracer("CodeCompleteFlow");
>      // We run Sema code completion first. It builds an AST and calculates:
>      //   - completion results based on the AST. These are saved for
> merging.
>      //   - partial identifier and context. We need these for the index
> query.
>      CompletionList Output;
> -    semaCodeComplete(Ctx, std::move(RecorderOwner),
> Opts.getClangCompleteOpts(),
> +    semaCodeComplete(std::move(RecorderOwner),
> Opts.getClangCompleteOpts(),
>                       SemaCCInput, [&] {
>                         if (Recorder.CCSema)
>                           Output = runWithSema();
>                         else
> -                         log(Ctx, "Code complete: no Sema callback, 0
> results");
> +                         log("Code complete: no Sema callback, 0
> results");
>                       });
>
>      SPAN_ATTACH(Tracer, "sema_results", NSema);
> @@ -835,8 +832,7 @@ public:
>      SPAN_ATTACH(Tracer, "merged_results", NBoth);
>      SPAN_ATTACH(Tracer, "returned_results", Output.items.size());
>      SPAN_ATTACH(Tracer, "incomplete", Output.isIncomplete);
> -    log(Ctx,
> -        llvm::formatv("Code complete: {0} results from Sema, {1} from
> Index, "
> +    log(llvm::formatv("Code complete: {0} results from Sema, {1} from
> Index, "
>                        "{2} matched, {3} returned{4}.",
>                        NSema, NIndex, NBoth, Output.items.size(),
>                        Output.isIncomplete ? " (incomplete)" : ""));
> @@ -871,7 +867,7 @@ private:
>    SymbolSlab queryIndex() {
>      if (!Opts.Index || !allowIndex(Recorder.CCContext.getKind()))
>        return SymbolSlab();
> -    trace::Span Tracer(Ctx, "Query index");
> +    trace::Span Tracer("Query index");
>      SPAN_ATTACH(Tracer, "limit", Opts.Limit);
>
>      SymbolSlab::Builder ResultsBuilder;
> @@ -882,15 +878,12 @@ private:
>      Req.Query = Filter->pattern();
>      Req.Scopes =
>          getQueryScopes(Recorder.CCContext, Recorder.CCSema->
> getSourceManager());
> -    log(Tracer.Ctx,
> -        llvm::formatv("Code complete: fuzzyFind(\"{0}\", Scopes: [{1}]",
> +    log(llvm::formatv("Code complete: fuzzyFind(\"{0}\", scopes=[{1}])",
>                        Req.Query,
>                        llvm::join(Req.Scopes.begin(), Req.Scopes.end(),
> ",")));
>      // Run the query against the index.
> -    Incomplete |=
> -        !Opts.Index->fuzzyFind(Tracer.Ctx, Req, [&](const Symbol &Sym) {
> -          ResultsBuilder.insert(Sym);
> -        });
> +    Incomplete |= !Opts.Index->fuzzyFind(
> +        Req, [&](const Symbol &Sym) { ResultsBuilder.insert(Sym); });
>      return std::move(ResultsBuilder).build();
>    }
>
> @@ -899,7 +892,7 @@ private:
>    std::vector<std::pair<CompletionCandidate, CompletionItemScores>>
>    mergeResults(const std::vector<CodeCompletionResult> &SemaResults,
>                 const SymbolSlab &IndexResults) {
> -    trace::Span Tracer(Ctx, "Merge and score results");
> +    trace::Span Tracer("Merge and score results");
>      // We only keep the best N results at any time, in "native" format.
>      TopN Top(Opts.Limit == 0 ? TopN::Unbounded : Opts.Limit);
>      llvm::DenseSet<const Symbol *> UsedIndexResults;
> @@ -960,18 +953,18 @@ private:
>    }
>  };
>
> -CompletionList codeComplete(const Context &Ctx, PathRef FileName,
> +CompletionList codeComplete(PathRef FileName,
>                              const tooling::CompileCommand &Command,
>                              PrecompiledPreamble const *Preamble,
>                              StringRef Contents, Position Pos,
>                              IntrusiveRefCntPtr<vfs::FileSystem> VFS,
>                              std::shared_ptr<PCHContainerOperations> PCHs,
>                              CodeCompleteOptions Opts) {
> -  return CodeCompleteFlow(Ctx, Opts).run(
> +  return CodeCompleteFlow(Opts).run(
>        {FileName, Command, Preamble, Contents, Pos, VFS, PCHs});
>  }
>
> -SignatureHelp signatureHelp(const Context &Ctx, PathRef FileName,
> +SignatureHelp signatureHelp(PathRef FileName,
>                              const tooling::CompileCommand &Command,
>                              PrecompiledPreamble const *Preamble,
>                              StringRef Contents, Position Pos,
> @@ -983,10 +976,10 @@ SignatureHelp signatureHelp(const Contex
>    Options.IncludeMacros = false;
>    Options.IncludeCodePatterns = false;
>    Options.IncludeBriefComments = true;
> -  semaCodeComplete(
> -      Ctx, llvm::make_unique<SignatureHelpCollector>(Options, Result),
> Options,
> -      {FileName, Command, Preamble, Contents, Pos, std::move(VFS),
> -       std::move(PCHs)});
> +  semaCodeComplete(llvm::make_unique<SignatureHelpCollector>(Options,
> Result),
> +                   Options,
> +                   {FileName, Command, Preamble, Contents, Pos,
> std::move(VFS),
> +                    std::move(PCHs)});
>    return Result;
>  }
>
>
> Modified: clang-tools-extra/trunk/clangd/CodeComplete.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/CodeComplete.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/CodeComplete.h (original)
> +++ clang-tools-extra/trunk/clangd/CodeComplete.h Wed Jan 31 05:40:48 2018
> @@ -15,7 +15,6 @@
>  #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
>  #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
>
> -#include "Context.h"
>  #include "Logger.h"
>  #include "Path.h"
>  #include "Protocol.h"
> @@ -67,7 +66,7 @@ struct CodeCompleteOptions {
>  };
>
>  /// Get code completions at a specified \p Pos in \p FileName.
> -CompletionList codeComplete(const Context &Ctx, PathRef FileName,
> +CompletionList codeComplete(PathRef FileName,
>                              const tooling::CompileCommand &Command,
>                              PrecompiledPreamble const *Preamble,
>                              StringRef Contents, Position Pos,
> @@ -76,7 +75,7 @@ CompletionList codeComplete(const Contex
>                              CodeCompleteOptions Opts);
>
>  /// Get signature help at a specified \p Pos in \p FileName.
> -SignatureHelp signatureHelp(const Context &Ctx, PathRef FileName,
> +SignatureHelp signatureHelp(PathRef FileName,
>                              const tooling::CompileCommand &Command,
>                              PrecompiledPreamble const *Preamble,
>                              StringRef Contents, Position Pos,
>
> Modified: clang-tools-extra/trunk/clangd/Context.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Context.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Context.cpp (original)
> +++ clang-tools-extra/trunk/clangd/Context.cpp Wed Jan 31 05:40:48 2018
> @@ -20,5 +20,19 @@ Context::Context(std::shared_ptr<const D
>
>  Context Context::clone() const { return Context(DataPtr); }
>
> +// The thread-local Context is scoped in a function to avoid
> +// initialization-order issues. It's created when first needed.
> +static Context &currentContext() {
> +  static thread_local Context C = Context::empty();
> +  return C;
> +}
> +
> +const Context &Context::current() { return currentContext(); }
> +
> +Context Context::swapCurrent(Context Replacement) {
> +  std::swap(Replacement, currentContext());
> +  return Replacement;
> +}
> +
>  } // namespace clangd
>  } // namespace clang
>
> Modified: clang-tools-extra/trunk/clangd/Context.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Context.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Context.h (original)
> +++ clang-tools-extra/trunk/clangd/Context.h Wed Jan 31 05:40:48 2018
> @@ -16,15 +16,28 @@
>  #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONTEXT_H_
>
>  #include "llvm/ADT/STLExtras.h"
> +#include "llvm/Support/Compiler.h"
>  #include <memory>
>  #include <type_traits>
>
>  namespace clang {
>  namespace clangd {
>
> -/// A key for a value of type \p Type, stored inside a context. Keys are
> -/// non-movable and non-copyable. See documentation of the Context class
> for
> -/// more details and usage examples.
> +/// Values in a Context are indexed by typed keys.
> +/// Key<T> serves two purposes:
> +///   - it provides a lookup key for the context (each Key is unique),
> +///   - it makes lookup type-safe: a Key<T> can only map to a T (or
> nothing).
> +///
> +/// Example:
> +///    Key<int> RequestID;
> +///    Key<int> Version;
> +///
> +///    Context Ctx = Context::empty().derive(RequestID,
> 10).derive(Version, 3);
> +///    assert(*Ctx.get(RequestID) == 10);
> +///    assert(*Ctx.get(Version) == 3);
> +///
> +/// Keys are typically used across multiple functions, so most of the
> time you
> +/// would want to make them static class members or global variables.
>  template <class Type> class Key {
>  public:
>    static_assert(!std::is_reference<Type>::value,
> @@ -45,53 +58,24 @@ public:
>  /// Conceptually, a context is a heterogeneous map<Key<T>, T>. Each key
> has
>  /// an associated value type, which allows the map to be typesafe.
>  ///
> +/// There is an "ambient" context for each thread, Context::current().
> +/// Most functions should read from this, and use WithContextValue or
> +/// WithContext to extend or replace the context within a block scope.
> +/// Only code dealing with threads and extension points should need to use
> +/// other Context objects.
> +///
>  /// You can't add data to an existing context, instead you create a new
>  /// immutable context derived from it with extra data added. When you
> retrieve
>  /// data, the context will walk up the parent chain until the key is
> found.
> -///
> -/// Contexts should be:
> -///  - passed by reference when calling synchronous functions
> -///  - passed by value (move) when calling asynchronous functions. The
> result
> -///    callback of async operations will receive the context again.
> -///  - cloned only when 'forking' an asynchronous computation that we
> don't wait
> -///    for.
> -///
> -/// Copy operations for this class are deleted, use an explicit clone()
> method
> -/// when you need a copy of the context instead.
> -///
> -/// To derive a child context use derive() function, e.g.
> -///     Context ChildCtx = ParentCtx.derive(RequestIdKey, 123);
> -///
> -/// To create a new root context, derive() from empty Context.
> -/// e.g.:
> -///     Context Ctx = Context::empty().derive(RequestIdKey, 123);
> -///
> -/// Values in the context are indexed by typed keys (instances of Key<T>
> class).
> -/// Key<T> serves two purposes:
> -///   - it provides a lookup key for the context (each instance of a key
> is
> -///   unique),
> -///   - it keeps the type information about the value stored in the
> context map
> -///   in the template arguments.
> -/// This provides a type-safe interface to store and access values of
> multiple
> -/// types inside a single context.
> -/// For example,
> -///    Key<int> RequestID;
> -///    Key<int> Version;
> -///
> -///    Context Ctx = Context::empty().derive(RequestID,
> 10).derive(Version, 3);
> -///    assert(*Ctx.get(RequestID) == 10);
> -///    assert(*Ctx.get(Version) == 3);
> -///
> -/// Keys are typically used across multiple functions, so most of the
> time you
> -/// would want to make them static class members or global variables.
> -///
> -/// FIXME: Rather than manual plumbing, pass Context using thread-local
> storage
> -/// by default, and make thread boundaries deal with propagation
> explicitly.
>  class Context {
>  public:
> -  /// Returns an empty context that contains no data. Useful for calling
> -  /// functions that require a context when no explicit context is
> available.
> +  /// Returns an empty root context that contains no data.
>    static Context empty();
> +  /// Returns the context for the current thread, creating it if needed.
> +  static const Context &current();
> +  // Sets the current() context to Replacement, and returns the old
> context.
> +  // Prefer to use WithContext or WithContextValue to do this safely.
> +  static Context swapCurrent(Context Replacement);
>
>  private:
>    struct Data;
> @@ -103,7 +87,8 @@ public:
>    /// (arguments of std::future<> must be default-construcitble in MSVC).
>    Context() = default;
>
> -  /// Move-only.
> +  /// Copy operations for this class are deleted, use an explicit clone()
> method
> +  /// when you need a copy of the context instead.
>    Context(Context const &) = delete;
>    Context &operator=(const Context &) = delete;
>
> @@ -131,9 +116,8 @@ public:
>    }
>
>    /// Derives a child context
> -  /// It is safe to move or destroy a parent context after calling
> derive() from
> -  /// it. The child context will continue to have access to the data
> stored in
> -  /// the parent context.
> +  /// It is safe to move or destroy a parent context after calling
> derive().
> +  /// The child will keep its parent alive, and its data remains
> accessible.
>    template <class Type>
>    Context derive(const Key<Type> &Key,
>                   typename std::decay<Type>::type Value) const & {
> @@ -198,7 +182,40 @@ private:
>    };
>
>    std::shared_ptr<const Data> DataPtr;
> -}; // namespace clangd
> +};
> +
> +/// WithContext replaces Context::current() with a provided scope.
> +/// When the WithContext is destroyed, the original scope is restored.
> +/// For extending the current context with new value, prefer
> WithContextValue.
> +class LLVM_NODISCARD WithContext {
> +public:
> +  WithContext(Context C) : Restore(Context::swapCurrent(std::move(C))) {}
> +  ~WithContext() { Context::swapCurrent(std::move(Restore)); }
> +  WithContext(const WithContext &) = delete;
> +  WithContext &operator=(const WithContext &) = delete;
> +  WithContext(WithContext &&) = delete;
> +  WithContext &operator=(WithContext &&) = delete;
> +
> +private:
> +  Context Restore;
> +};
> +
> +/// WithContextValue extends Context::current() with a single value.
> +/// When the WithContextValue is destroyed, the original scope is
> restored.
> +class LLVM_NODISCARD WithContextValue {
> +public:
> +  template <typename T>
> +  WithContextValue(const Key<T> &K, typename std::decay<T>::type V)
> +      : Restore(Context::current().derive(K, std::move(V))) {}
> +
> +  // Anonymous values can be used for the destructor side-effect.
> +  template <typename T>
> +  WithContextValue(T &&V)
> +      : Restore(Context::current().derive(std::forward<T>(V))) {}
> +
> +private:
> +  WithContext Restore;
> +};
>
>  } // namespace clangd
>  } // namespace clang
>
> Modified: clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/
> GlobalCompilationDatabase.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp
> (original)
> +++ clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp Wed Jan
> 31 05:40:48 2018
> @@ -38,8 +38,7 @@ DirectoryBasedGlobalCompilationDatabase:
>        return std::move(Candidates.front());
>      }
>    } else {
> -    log(Context::empty(), // FIXME(ibiryukov): pass a proper Context here.
> -        "Failed to find compilation database for " + Twine(File));
> +    log("Failed to find compilation database for " + Twine(File));
>    }
>    return llvm::None;
>  }
>
> Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/
> JSONRPCDispatcher.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp (original)
> +++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp Wed Jan 31
> 05:40:48 2018
> @@ -34,14 +34,14 @@ class RequestSpan {
>  public:
>    // Return a context that's aware of the enclosing request, identified
> by Span.
>    static Context stash(const trace::Span &Span) {
> -    return Span.Ctx.derive(RSKey, std::unique_ptr<RequestSpan>(
> -                                                 new
> RequestSpan(Span.Args)));
> +    return Context::current().derive(
> +        RSKey, std::unique_ptr<RequestSpan>(new RequestSpan(Span.Args)));
>    }
>
>    // If there's an enclosing request and the tracer is interested, calls
> \p F
>    // with a json::obj where request info can be added.
> -  template <typename Func> static void attach(const Context &Ctx, Func
> &&F) {
> -    auto *RequestArgs = Ctx.get(RSKey);
> +  template <typename Func> static void attach(Func &&F) {
> +    auto *RequestArgs = Context::current().get(RSKey);
>      if (!RequestArgs || !*RequestArgs || !(*RequestArgs)->Args)
>        return;
>      std::lock_guard<std::mutex> Lock((*RequestArgs)->Mu);
> @@ -70,8 +70,8 @@ void JSONOutput::writeMessage(const json
>    Outs.flush();
>  }
>
> -void JSONOutput::log(const Context &Ctx, const Twine &Message) {
> -  trace::log(Ctx, Message);
> +void JSONOutput::log(const Twine &Message) {
> +  trace::log(Message);
>    std::lock_guard<std::mutex> Guard(StreamMutex);
>    Logs << Message << '\n';
>    Logs.flush();
> @@ -85,16 +85,15 @@ void JSONOutput::mirrorInput(const Twine
>    InputMirror->flush();
>  }
>
> -void clangd::reply(const Context &Ctx, json::Expr &&Result) {
> -  auto ID = Ctx.get(RequestID);
> +void clangd::reply(json::Expr &&Result) {
> +  auto ID = Context::current().get(RequestID);
>    if (!ID) {
> -    log(Ctx, "Attempted to reply to a notification!");
> +    log("Attempted to reply to a notification!");
>      return;
>    }
> -
> -  RequestSpan::attach(Ctx, [&](json::obj &Args) { Args["Reply"] = Result;
> });
> -
> -  Ctx.getExisting(RequestOut)
> +  RequestSpan::attach([&](json::obj &Args) { Args["Reply"] = Result; });
> +  Context::current()
> +      .getExisting(RequestOut)
>        ->writeMessage(json::obj{
>            {"jsonrpc", "2.0"},
>            {"id", *ID},
> @@ -102,16 +101,16 @@ void clangd::reply(const Context &Ctx, j
>        });
>  }
>
> -void clangd::replyError(const Context &Ctx, ErrorCode code,
> -                        const llvm::StringRef &Message) {
> -  log(Ctx, "Error " + Twine(static_cast<int>(code)) + ": " + Message);
> -  RequestSpan::attach(Ctx, [&](json::obj &Args) {
> +void clangd::replyError(ErrorCode code, const llvm::StringRef &Message) {
> +  log("Error " + Twine(static_cast<int>(code)) + ": " + Message);
> +  RequestSpan::attach([&](json::obj &Args) {
>      Args["Error"] =
>          json::obj{{"code", static_cast<int>(code)}, {"message",
> Message.str()}};
>    });
>
> -  if (auto ID = Ctx.get(RequestID)) {
> -    Ctx.getExisting(RequestOut)
> +  if (auto ID = Context::current().get(RequestID)) {
> +    Context::current()
> +        .getExisting(RequestOut)
>          ->writeMessage(json::obj{
>              {"jsonrpc", "2.0"},
>              {"id", *ID},
> @@ -121,13 +120,14 @@ void clangd::replyError(const Context &C
>    }
>  }
>
> -void clangd::call(const Context &Ctx, StringRef Method, json::Expr
> &&Params) {
> +void clangd::call(StringRef Method, json::Expr &&Params) {
>    // FIXME: Generate/Increment IDs for every request so that we can get
> proper
>    // replies once we need to.
> -  RequestSpan::attach(Ctx, [&](json::obj &Args) {
> +  RequestSpan::attach([&](json::obj &Args) {
>      Args["Call"] = json::obj{{"method", Method.str()}, {"params",
> Params}};
>    });
> -  Ctx.getExisting(RequestOut)
> +  Context::current()
> +      .getExisting(RequestOut)
>        ->writeMessage(json::obj{
>            {"jsonrpc", "2.0"},
>            {"id", 1},
> @@ -163,18 +163,20 @@ bool JSONRPCDispatcher::call(const json:
>    auto &Handler = I != Handlers.end() ? I->second : UnknownHandler;
>
>    // Create a Context that contains request information.
> -  auto Ctx = Context::empty().derive(RequestOut, &Out);
> +  WithContextValue WithRequestOut(RequestOut, &Out);
> +  llvm::Optional<WithContextValue> WithID;
>    if (ID)
> -    Ctx = std::move(Ctx).derive(RequestID, *ID);
> +    WithID.emplace(RequestID, *ID);
>
>    // Create a tracing Span covering the whole request lifetime.
> -  trace::Span Tracer(Ctx, *Method);
> +  trace::Span Tracer(*Method);
>    if (ID)
>      SPAN_ATTACH(Tracer, "ID", *ID);
>    SPAN_ATTACH(Tracer, "Params", Params);
>
>    // Stash a reference to the span args, so later calls can add metadata.
> -  Handler(RequestSpan::stash(Tracer), std::move(Params));
> +  WithContext WithRequestSpan(RequestSpan::stash(Tracer));
> +  Handler(std::move(Params));
>    return true;
>  }
>
> @@ -216,10 +218,9 @@ void clangd::runLanguageServerLoop(std::
>        // The end of headers is signified by an empty line.
>        if (LineRef.consume_front("Content-Length: ")) {
>          if (ContentLength != 0) {
> -          log(Context::empty(),
> -              "Warning: Duplicate Content-Length header received. "
> +          log("Warning: Duplicate Content-Length header received. "
>                "The previous value for this message (" +
> -                  llvm::Twine(ContentLength) + ") was ignored.\n");
> +              llvm::Twine(ContentLength) + ") was ignored.\n");
>          }
>
>          llvm::getAsUnsignedInteger(LineRef.trim(), 0, ContentLength);
> @@ -238,8 +239,8 @@ void clangd::runLanguageServerLoop(std::
>      // and we don't want to crash downstream because of it.
>      if (ContentLength > 1 << 30) { // 1024M
>        In.ignore(ContentLength);
> -      log(Context::empty(), "Skipped overly large message of " +
> -                                Twine(ContentLength) + " bytes.\n");
> +      log("Skipped overly large message of " + Twine(ContentLength) +
> +          " bytes.\n");
>        continue;
>      }
>
> @@ -253,9 +254,8 @@ void clangd::runLanguageServerLoop(std::
>          // If the stream is aborted before we read ContentLength bytes, In
>          // will have eofbit and failbit set.
>          if (!In) {
> -          log(Context::empty(),
> -              "Input was aborted. Read only " + llvm::Twine(In.gcount()) +
> -                  " bytes of expected " + llvm::Twine(ContentLength) +
> ".\n");
> +          log("Input was aborted. Read only " + llvm::Twine(In.gcount()) +
> +              " bytes of expected " + llvm::Twine(ContentLength) + ".\n");
>            break;
>          }
>
> @@ -264,24 +264,22 @@ void clangd::runLanguageServerLoop(std::
>
>        if (auto Doc = json::parse(JSONRef)) {
>          // Log the formatted message.
> -        log(Context::empty(),
> -            llvm::formatv(Out.Pretty ? "<-- {0:2}\n" : "<-- {0}\n",
> *Doc));
> +        log(llvm::formatv(Out.Pretty ? "<-- {0:2}\n" : "<-- {0}\n",
> *Doc));
>          // Finally, execute the action for this JSON message.
>          if (!Dispatcher.call(*Doc, Out))
> -          log(Context::empty(), "JSON dispatch failed!\n");
> +          log("JSON dispatch failed!\n");
>        } else {
>          // Parse error. Log the raw message.
> -        log(Context::empty(), "<-- " + JSONRef + "\n");
> -        log(Context::empty(), llvm::Twine("JSON parse error: ") +
> -                                  llvm::toString(Doc.takeError()) +
> "\n");
> +        log("<-- " + JSONRef + "\n");
> +        log(llvm::Twine("JSON parse error: ") +
> +            llvm::toString(Doc.takeError()) + "\n");
>        }
>
>        // If we're done, exit the loop.
>        if (IsDone)
>          break;
>      } else {
> -      log(Context::empty(),
> -          "Warning: Missing Content-Length header, or message has zero "
> +      log("Warning: Missing Content-Length header, or message has zero "
>            "length.\n");
>      }
>    }
>
> Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/
> JSONRPCDispatcher.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h (original)
> +++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h Wed Jan 31
> 05:40:48 2018
> @@ -10,7 +10,6 @@
>  #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"
> @@ -38,7 +37,7 @@ public:
>    void writeMessage(const json::Expr &Result);
>
>    /// Write a line to the logging stream.
> -  void log(const Context &Ctx, const Twine &Message) override;
> +  void log(const Twine &Message) override;
>
>    /// Mirror \p Message into InputMirror stream. Does nothing if
> InputMirror is
>    /// null.
> @@ -56,23 +55,22 @@ private:
>    std::mutex StreamMutex;
>  };
>
> -/// Sends a successful reply. \p Ctx must either be the Context accepted
> by
> -/// JSONRPCDispatcher::Handler or be derived from it.
> -void reply(const Context &Ctx, json::Expr &&Result);
> -/// Sends an error response to the client, and logs it. \p Ctx must
> either be
> -/// the Context accepted by JSONRPCDispatcher::Handler or be derived from
> it.
> -void replyError(const Context &Ctx, ErrorCode code,
> -                const llvm::StringRef &Message);
> -/// Sends a request to the client. \p Ctx must either be the Context
> accepted by
> -/// JSONRPCDispatcher::Handler or be derived from it.
> -void call(const Context &Ctx, llvm::StringRef Method, json::Expr
> &&Params);
> +/// Sends a successful reply.
> +/// Current context must derive from JSONRPCDispatcher::Handler.
> +void reply(json::Expr &&Result);
> +/// Sends an error response to the client, and logs it.
> +/// Current context must derive from JSONRPCDispatcher::Handler.
> +void replyError(ErrorCode code, const llvm::StringRef &Message);
> +/// Sends a request to the client.
> +/// Current context must derive from JSONRPCDispatcher::Handler.
> +void call(llvm::StringRef Method, json::Expr &&Params);
>
>  /// Main JSONRPC entry point. This parses the JSONRPC "header" and calls
> the
>  /// registered Handler for the method received.
>  class JSONRPCDispatcher {
>  public:
>    // A handler responds to requests for a particular method name.
> -  using Handler = std::function<void(Context, const json::Expr &)>;
> +  using Handler = std::function<void(const json::Expr &)>;
>
>    /// Create a new JSONRPCDispatcher. UnknownHandler is called when an
> unknown
>    /// method is received.
>
> Modified: clang-tools-extra/trunk/clangd/Logger.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Logger.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Logger.cpp (original)
> +++ clang-tools-extra/trunk/clangd/Logger.cpp Wed Jan 31 05:40:48 2018
> @@ -25,9 +25,9 @@ LoggingSession::LoggingSession(clangd::L
>
>  LoggingSession::~LoggingSession() { L = nullptr; }
>
> -void log(const Context &Ctx, const llvm::Twine &Message) {
> +void log(const llvm::Twine &Message) {
>    if (L)
> -    L->log(Ctx, Message);
> +    L->log(Message);
>    else {
>      static std::mutex Mu;
>      std::lock_guard<std::mutex> Guard(Mu);
>
> Modified: clang-tools-extra/trunk/clangd/Logger.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Logger.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Logger.h (original)
> +++ clang-tools-extra/trunk/clangd/Logger.h Wed Jan 31 05:40:48 2018
> @@ -10,7 +10,6 @@
>  #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 {
> @@ -19,7 +18,7 @@ namespace clangd {
>  /// Main logging function.
>  /// Logs messages to a global logger, which can be set up by
> LoggingSesssion.
>  /// If no logger is registered, writes to llvm::errs().
> -void log(const Context &Ctx, const llvm::Twine &Message);
> +void log(const llvm::Twine &Message);
>
>  /// Interface to allow custom logging in clangd.
>  class Logger {
> @@ -27,7 +26,7 @@ public:
>    virtual ~Logger() = default;
>
>    /// Implementations of this method must be thread-safe.
> -  virtual void log(const Context &Ctx, const llvm::Twine &Message) = 0;
> +  virtual void log(const llvm::Twine &Message) = 0;
>  };
>
>  /// Only one LoggingSession can be active at a time.
>
> Modified: clang-tools-extra/trunk/clangd/Protocol.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Protocol.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Protocol.cpp (original)
> +++ clang-tools-extra/trunk/clangd/Protocol.cpp Wed Jan 31 05:40:48 2018
> @@ -28,18 +28,16 @@ bool fromJSON(const json::Expr &E, URIFo
>    if (auto S = E.asString()) {
>      auto U = URI::parse(*S);
>      if (!U) {
> -      log(Context::empty(),
> -          "Failed to parse URI " + *S + ": " +
> llvm::toString(U.takeError()));
> +      log("Failed to parse URI " + *S + ": " +
> llvm::toString(U.takeError()));
>        return false;
>      }
>      if (U->scheme() != "file") {
> -      log(Context::empty(),
> -          "Clangd only supports 'file' URI scheme for workspace files: "
> + *S);
> +      log("Clangd only supports 'file' URI scheme for workspace files: "
> + *S);
>        return false;
>      }
>      auto Path = URI::resolve(*U);
>      if (!Path) {
> -      log(Context::empty(), llvm::toString(Path.takeError()));
> +      log(llvm::toString(Path.takeError()));
>        return false;
>      }
>      R.file = *Path;
>
> Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ProtocolHandlers.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp (original)
> +++ clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp Wed Jan 31
> 05:40:48 2018
> @@ -24,19 +24,17 @@ namespace {
>  // FooParams should have a fromJSON function.
>  struct HandlerRegisterer {
>    template <typename Param>
> -  void operator()(StringRef Method,
> -                  void (ProtocolCallbacks::*Handler)(Context, Param)) {
> +  void operator()(StringRef Method, void (ProtocolCallbacks::*Handler)(Param))
> {
>      // Capture pointers by value, as the lambda will outlive this object.
>      auto *Callbacks = this->Callbacks;
> -    Dispatcher.registerHandler(
> -        Method, [=](Context C, const json::Expr &RawParams) {
> -          typename std::remove_reference<Param>::type P;
> -          if (fromJSON(RawParams, P)) {
> -            (Callbacks->*Handler)(std::move(C), P);
> -          } else {
> -            log(C, "Failed to decode " + Method + " request.");
> -          }
> -        });
> +    Dispatcher.registerHandler(Method, [=](const json::Expr &RawParams) {
> +      typename std::remove_reference<Param>::type P;
> +      if (fromJSON(RawParams, P)) {
> +        (Callbacks->*Handler)(P);
> +      } else {
> +        log("Failed to decode " + Method + " request.");
> +      }
> +    });
>    }
>
>    JSONRPCDispatcher &Dispatcher;
>
> Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ProtocolHandlers.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ProtocolHandlers.h (original)
> +++ clang-tools-extra/trunk/clangd/ProtocolHandlers.h Wed Jan 31 05:40:48
> 2018
> @@ -29,34 +29,28 @@ namespace clangd {
>  // The interface implemented by ClangLSPServer to handle incoming
> requests.
>  class ProtocolCallbacks {
>  public:
> -  // FIXME(ibiryukov): remove this typedef, inline its usages.
> -  using Ctx = Context;
>    virtual ~ProtocolCallbacks() = default;
>
> -  virtual void onInitialize(Ctx C, InitializeParams &Params) = 0;
> -  virtual void onShutdown(Ctx C, ShutdownParams &Params) = 0;
> -  virtual void onExit(Ctx C, ExitParams &Params) = 0;
> -  virtual void onDocumentDidOpen(Ctx C, DidOpenTextDocumentParams
> &Params) = 0;
> -  virtual void onDocumentDidChange(Ctx C,
> -                                   DidChangeTextDocumentParams &Params) =
> 0;
> -  virtual void onDocumentDidClose(Ctx C,
> -                                  DidCloseTextDocumentParams &Params) = 0;
> -  virtual void onDocumentFormatting(Ctx C,
> -                                    DocumentFormattingParams &Params) = 0;
> +  virtual void onInitialize(InitializeParams &Params) = 0;
> +  virtual void onShutdown(ShutdownParams &Params) = 0;
> +  virtual void onExit(ExitParams &Params) = 0;
> +  virtual void onDocumentDidOpen(DidOpenTextDocumentParams &Params) = 0;
> +  virtual void onDocumentDidChange(DidChangeTextDocumentParams &Params)
> = 0;
> +  virtual void onDocumentDidClose(DidCloseTextDocumentParams &Params) =
> 0;
> +  virtual void onDocumentFormatting(DocumentFormattingParams &Params) =
> 0;
>    virtual void
> -  onDocumentOnTypeFormatting(Ctx C, DocumentOnTypeFormattingParams
> &Params) = 0;
> +  onDocumentOnTypeFormatting(DocumentOnTypeFormattingParams &Params) = 0;
>    virtual void
> -  onDocumentRangeFormatting(Ctx C, DocumentRangeFormattingParams &Params)
> = 0;
> -  virtual void onCodeAction(Ctx C, CodeActionParams &Params) = 0;
> -  virtual void onCompletion(Ctx C, TextDocumentPositionParams &Params) =
> 0;
> -  virtual void onSignatureHelp(Ctx C, TextDocumentPositionParams &Params)
> = 0;
> -  virtual void onGoToDefinition(Ctx C, TextDocumentPositionParams
> &Params) = 0;
> -  virtual void onSwitchSourceHeader(Ctx C, TextDocumentIdentifier
> &Params) = 0;
> -  virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) =
> 0;
> -  virtual void onCommand(Ctx C, ExecuteCommandParams &Params) = 0;
> -  virtual void onRename(Ctx C, RenameParams &Parames) = 0;
> -  virtual void onDocumentHighlight(Ctx C,
> -                                   TextDocumentPositionParams &Params) =
> 0;
> +  onDocumentRangeFormatting(DocumentRangeFormattingParams &Params) = 0;
> +  virtual void onCodeAction(CodeActionParams &Params) = 0;
> +  virtual void onCompletion(TextDocumentPositionParams &Params) = 0;
> +  virtual void onSignatureHelp(TextDocumentPositionParams &Params) = 0;
> +  virtual void onGoToDefinition(TextDocumentPositionParams &Params) = 0;
> +  virtual void onSwitchSourceHeader(TextDocumentIdentifier &Params) = 0;
> +  virtual void onFileEvent(DidChangeWatchedFilesParams &Params) = 0;
> +  virtual void onCommand(ExecuteCommandParams &Params) = 0;
> +  virtual void onRename(RenameParams &Parames) = 0;
> +  virtual void onDocumentHighlight(TextDocumentPositionParams &Params) =
> 0;
>  };
>
>  void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput
> &Out,
>
> Modified: clang-tools-extra/trunk/clangd/TUScheduler.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/TUScheduler.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/TUScheduler.cpp (original)
> +++ clang-tools-extra/trunk/clangd/TUScheduler.cpp Wed Jan 31 05:40:48
> 2018
> @@ -23,9 +23,8 @@ TUScheduler::TUScheduler(unsigned AsyncT
>        Threads(AsyncThreadsCount) {}
>
>  void TUScheduler::update(
> -    Context Ctx, PathRef File, ParseInputs Inputs,
> -    UniqueFunction<void(Context Ctx,
> -                        llvm::Optional<std::vector<DiagWithFixIts>>)>
> +    PathRef File, ParseInputs Inputs,
> +    UniqueFunction<void(llvm::Optional<std::vector<DiagWithFixIts>>)>
>          OnUpdated) {
>    CachedInputs[File] = Inputs;
>
> @@ -33,12 +32,12 @@ void TUScheduler::update(
>    auto DeferredRebuild = Resources->deferRebuild(std::move(Inputs));
>
>    Threads.addToFront(
> -      [](Context Ctx, decltype(OnUpdated) OnUpdated,
> +      [](decltype(OnUpdated) OnUpdated,
>           decltype(DeferredRebuild) DeferredRebuild) {
> -        auto Diags = DeferredRebuild(Ctx);
> -        OnUpdated(std::move(Ctx), Diags);
> +        auto Diags = DeferredRebuild();
> +        OnUpdated(Diags);
>        },
> -      std::move(Ctx), std::move(OnUpdated), std::move(DeferredRebuild));
> +      std::move(OnUpdated), std::move(DeferredRebuild));
>  }
>
>  void TUScheduler::remove(PathRef File,
>
> Modified: clang-tools-extra/trunk/clangd/TUScheduler.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/TUScheduler.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/TUScheduler.h (original)
> +++ clang-tools-extra/trunk/clangd/TUScheduler.h Wed Jan 31 05:40:48 2018
> @@ -50,10 +50,9 @@ public:
>    /// Schedule an update for \p File. Adds \p File to a list of tracked
> files if
>    /// \p File was not part of it before.
>    /// FIXME(ibiryukov): remove the callback from this function.
> -  void update(
> -      Context Ctx, PathRef File, ParseInputs Inputs,
> -      UniqueFunction<void(Context, llvm::Optional<std::vector<
> DiagWithFixIts>>)>
> -          OnUpdated);
> +  void update(PathRef File, ParseInputs Inputs,
> +              UniqueFunction<void(llvm::Optional<std::vector<
> DiagWithFixIts>>)>
> +                  OnUpdated);
>
>    /// Remove \p File from the list of tracked files and schedule removal
> of its
>    /// resources. \p Action will be called when resources are freed.
>
> Modified: clang-tools-extra/trunk/clangd/Threading.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Threading.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Threading.cpp (original)
> +++ clang-tools-extra/trunk/clangd/Threading.cpp Wed Jan 31 05:40:48 2018
> @@ -17,6 +17,7 @@ ThreadPool::ThreadPool(unsigned AsyncThr
>        llvm::set_thread_name(llvm::formatv("scheduler/{0}", I));
>        while (true) {
>          UniqueFunction<void()> Request;
> +        Context Ctx;
>
>          // Pick request from the queue
>          {
> @@ -33,10 +34,11 @@ ThreadPool::ThreadPool(unsigned AsyncThr
>            // ThreadPool have a way to prioritise their requests by putting
>            // them to the either side of the queue (using either addToEnd
> or
>            // addToFront).
> -          Request = std::move(RequestQueue.front());
> +          std::tie(Request, Ctx) = std::move(RequestQueue.front());
>            RequestQueue.pop_front();
>          } // unlock Mutex
>
> +        WithContext WithCtx(std::move(Ctx));
>          Request();
>        }
>      }));
>
> Modified: clang-tools-extra/trunk/clangd/Threading.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Threading.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Threading.h (original)
> +++ clang-tools-extra/trunk/clangd/Threading.h Wed Jan 31 05:40:48 2018
> @@ -10,6 +10,7 @@
>  #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_THREADING_H
>  #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_THREADING_H
>
> +#include "Context.h"
>  #include "Function.h"
>  #include <condition_variable>
>  #include <deque>
> @@ -42,8 +43,9 @@ public:
>
>      {
>        std::lock_guard<std::mutex> Lock(Mutex);
> -      RequestQueue.push_front(
> -          BindWithForward(std::forward<Func>(F),
> std::forward<Args>(As)...));
> +      RequestQueue.emplace_front(
> +          BindWithForward(std::forward<Func>(F),
> std::forward<Args>(As)...),
> +          Context::current().clone());
>      }
>      RequestCV.notify_one();
>    }
> @@ -58,8 +60,9 @@ public:
>
>      {
>        std::lock_guard<std::mutex> Lock(Mutex);
> -      RequestQueue.push_back(
> -          BindWithForward(std::forward<Func>(F),
> std::forward<Args>(As)...));
> +      RequestQueue.emplace_back(
> +          BindWithForward(std::forward<Func>(F),
> std::forward<Args>(As)...),
> +          Context::current().clone());
>      }
>      RequestCV.notify_one();
>    }
> @@ -74,7 +77,7 @@ private:
>    /// Setting Done to true will make the worker threads terminate.
>    bool Done = false;
>    /// A queue of requests.
> -  std::deque<UniqueFunction<void()>> RequestQueue;
> +  std::deque<std::pair<UniqueFunction<void()>, Context>> RequestQueue;
>    /// Condition variable to wake up worker threads.
>    std::condition_variable RequestCV;
>  };
>
> Modified: clang-tools-extra/trunk/clangd/Trace.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Trace.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Trace.cpp (original)
> +++ clang-tools-extra/trunk/clangd/Trace.cpp Wed Jan 31 05:40:48 2018
> @@ -46,16 +46,14 @@ public:
>      Out.flush();
>    }
>
> -  Context beginSpan(const Context &Ctx, llvm::StringRef Name,
> -                    json::obj *Args) override {
> +  Context beginSpan(llvm::StringRef Name, json::obj *Args) override {
>      jsonEvent("B", json::obj{{"name", Name}});
> -    return Ctx.derive(make_scope_exit([this, Args] {
> +    return Context::current().derive(make_scope_exit([this, Args] {
>        jsonEvent("E", json::obj{{"args", std::move(*Args)}});
>      }));
>    }
>
> -  void instant(const Context &Ctx, llvm::StringRef Name,
> -               json::obj &&Args) override {
> +  void instant(llvm::StringRef Name, json::obj &&Args) override {
>      jsonEvent("i", json::obj{{"name", Name}, {"args", std::move(Args)}});
>    }
>
> @@ -120,20 +118,26 @@ std::unique_ptr<EventTracer> createJSONT
>    return llvm::make_unique<JSONTracer>(OS, Pretty);
>  }
>
> -void log(const Context &Ctx, const Twine &Message) {
> +void log(const Twine &Message) {
>    if (!T)
>      return;
> -  T->instant(Ctx, "Log", json::obj{{"Message", Message.str()}});
> +  T->instant("Log", json::obj{{"Message", Message.str()}});
> +}
> +
> +// Returned context owns Args.
> +static Context makeSpanContext(llvm::StringRef Name, json::obj *Args) {
> +  if (!T)
> +    return Context::current().clone();
> +  WithContextValue WithArgs{std::unique_ptr<json::obj>(Args)};
> +  return T->beginSpan(Name, Args);
>  }
>
>  // Span keeps a non-owning pointer to the args, which is how users access
> them.
>  // The args are owned by the context though. They stick around until the
>  // beginSpan() context is destroyed, when the tracing engine will consume
> them.
> -Span::Span(const Context &Ctx, llvm::StringRef Name)
> +Span::Span(llvm::StringRef Name)
>      : Args(T ? new json::obj() : nullptr),
> -      Ctx(T ? T->beginSpan(Ctx.derive(std::unique_ptr<json::obj>(Args)),
> Name,
> -                           Args)
> -            : Ctx.clone()) {}
> +      RestoreCtx(makeSpanContext(Name, Args)) {}
>
>  } // namespace trace
>  } // namespace clangd
>
> Modified: clang-tools-extra/trunk/clangd/Trace.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Trace.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Trace.h (original)
> +++ clang-tools-extra/trunk/clangd/Trace.h Wed Jan 31 05:40:48 2018
> @@ -39,12 +39,10 @@ public:
>    /// Usually implementations will store an object in the returned context
>    /// whose destructor records the end of the event.
>    /// The args are *Args, only complete when the event ends.
> -  virtual Context beginSpan(const Context &Ctx, llvm::StringRef Name,
> -                            json::obj *Args) = 0;
> +  virtual Context beginSpan(llvm::StringRef Name, json::obj *Args) = 0;
>
>    /// Called for instant events.
> -  virtual void instant(const Context &Ctx, llvm::StringRef Name,
> -                       json::obj &&Args) = 0;
> +  virtual void instant(llvm::StringRef Name, json::obj &&Args) = 0;
>  };
>
>  /// Sets up a global EventTracer that consumes events produced by Span and
> @@ -65,7 +63,7 @@ std::unique_ptr<EventTracer> createJSONT
>                                                bool Pretty = false);
>
>  /// Records a single instant event, associated with the current thread.
> -void log(const Context &Ctx, const llvm::Twine &Name);
> +void log(const llvm::Twine &Name);
>
>  /// Records an event whose duration is the lifetime of the Span object.
>  /// This lifetime is extended when the span's context is reused.
> @@ -78,18 +76,19 @@ void log(const Context &Ctx, const llvm:
>  /// SomeJSONExpr is evaluated and copied only if actually needed.
>  class Span {
>  public:
> -  Span(const Context &Ctx, llvm::StringRef Name);
> +  Span(llvm::StringRef Name);
>
>    /// Mutable metadata, if this span is interested.
>    /// Prefer to use SPAN_ATTACH rather than accessing this directly.
>    json::obj *const Args;
> -  /// Propagating this context will keep the span alive.
> -  const Context Ctx;
> +
> +private:
> +  WithContext RestoreCtx;
>  };
>
>  /// Returns mutable span metadata if this span is interested.
>  /// Prefer to use SPAN_ATTACH rather than accessing this directly.
> -json::obj *spanArgs(const Context &Ctx);
> +json::obj *spanArgs();
>
>  /// Attach a key-value pair to a Span event.
>  /// This is not threadsafe when used with the same Span.
>
> Modified: clang-tools-extra/trunk/clangd/XRefs.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/XRefs.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/XRefs.cpp (original)
> +++ clang-tools-extra/trunk/clangd/XRefs.cpp Wed Jan 31 05:40:48 2018
> @@ -148,8 +148,7 @@ getDeclarationLocation(ParsedAST &AST, c
>
>  } // namespace
>
> -std::vector<Location> findDefinitions(const Context &Ctx, ParsedAST &AST,
> -                                      Position Pos) {
> +std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos) {
>    const SourceManager &SourceMgr = AST.getASTContext().
> getSourceManager();
>    const FileEntry *FE = SourceMgr.getFileEntryForID(
> SourceMgr.getMainFileID());
>    if (!FE)
> @@ -260,8 +259,8 @@ private:
>
>  } // namespace
>
> -std::vector<DocumentHighlight>
> -findDocumentHighlights(const Context &Ctx, ParsedAST &AST, Position Pos) {
> +std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
> +                                                      Position Pos) {
>    const SourceManager &SourceMgr = AST.getASTContext().
> getSourceManager();
>    const FileEntry *FE = SourceMgr.getFileEntryForID(
> SourceMgr.getMainFileID());
>    if (!FE)
>
> Modified: clang-tools-extra/trunk/clangd/XRefs.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/XRefs.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/XRefs.h (original)
> +++ clang-tools-extra/trunk/clangd/XRefs.h Wed Jan 31 05:40:48 2018
> @@ -14,7 +14,6 @@
>  #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_XREFS_H
>
>  #include "ClangdUnit.h"
> -#include "Context.h"
>  #include "Protocol.h"
>  #include <vector>
>
> @@ -22,12 +21,11 @@ namespace clang {
>  namespace clangd {
>
>  /// Get definition of symbol at a specified \p Pos.
> -std::vector<Location> findDefinitions(const Context &Ctx, ParsedAST &AST,
> -                                      Position Pos);
> +std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos);
>
>  /// Returns highlights for all usages of a symbol at \p Pos.
> -std::vector<DocumentHighlight>
> -findDocumentHighlights(const Context &Ctx, ParsedAST &AST, Position Pos);
> +std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
> +                                                      Position Pos);
>
>  } // namespace clangd
>  } // namespace clang
>
> Modified: clang-tools-extra/trunk/clangd/index/FileIndex.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/index/FileIndex.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/index/FileIndex.cpp (original)
> +++ clang-tools-extra/trunk/clangd/index/FileIndex.cpp Wed Jan 31
> 05:40:48 2018
> @@ -69,7 +69,7 @@ std::shared_ptr<std::vector<const Symbol
>    return {std::move(Snap), Pointers};
>  }
>
> -void FileIndex::update(const Context &Ctx, PathRef Path, ParsedAST *AST) {
> +void FileIndex::update(PathRef Path, ParsedAST *AST) {
>    if (!AST) {
>      FSymbols.update(Path, nullptr);
>    } else {
> @@ -82,9 +82,9 @@ void FileIndex::update(const Context &Ct
>  }
>
>  bool FileIndex::fuzzyFind(
> -    const Context &Ctx, const FuzzyFindRequest &Req,
> +    const FuzzyFindRequest &Req,
>      llvm::function_ref<void(const Symbol &)> Callback) const {
> -  return Index.fuzzyFind(Ctx, Req, Callback);
> +  return Index.fuzzyFind(Req, Callback);
>  }
>
>  } // namespace clangd
>
> Modified: clang-tools-extra/trunk/clangd/index/FileIndex.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/index/FileIndex.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/index/FileIndex.h (original)
> +++ clang-tools-extra/trunk/clangd/index/FileIndex.h Wed Jan 31 05:40:48
> 2018
> @@ -17,7 +17,6 @@
>  #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
>
>  #include "../ClangdUnit.h"
> -#include "../Context.h"
>  #include "Index.h"
>  #include "MemIndex.h"
>
> @@ -58,10 +57,10 @@ class FileIndex : public SymbolIndex {
>  public:
>    /// \brief Update symbols in \p Path with symbols in \p AST. If \p AST
> is
>    /// nullptr, this removes all symbols in the file
> -  void update(const Context &Ctx, PathRef Path, ParsedAST *AST);
> +  void update(PathRef Path, ParsedAST *AST);
>
>    bool
> -  fuzzyFind(const Context &Ctx, const FuzzyFindRequest &Req,
> +  fuzzyFind(const FuzzyFindRequest &Req,
>              llvm::function_ref<void(const Symbol &)> Callback) const
> override;
>
>  private:
>
> Modified: clang-tools-extra/trunk/clangd/index/Index.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/index/Index.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/index/Index.h (original)
> +++ clang-tools-extra/trunk/clangd/index/Index.h Wed Jan 31 05:40:48 2018
> @@ -10,7 +10,6 @@
>  #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
>  #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
>
> -#include "../Context.h"
>  #include "clang/Index/IndexSymbol.h"
>  #include "llvm/ADT/DenseMap.h"
>  #include "llvm/ADT/DenseSet.h"
> @@ -244,7 +243,7 @@ public:
>    /// Returns true if the result list is complete, false if it was
> truncated due
>    /// to MaxCandidateCount
>    virtual bool
> -  fuzzyFind(const Context &Ctx, const FuzzyFindRequest &Req,
> +  fuzzyFind(const FuzzyFindRequest &Req,
>              llvm::function_ref<void(const Symbol &)> Callback) const = 0;
>
>    // FIXME: add interfaces for more index use cases:
>
> Modified: clang-tools-extra/trunk/clangd/index/MemIndex.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/index/MemIndex.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/index/MemIndex.cpp (original)
> +++ clang-tools-extra/trunk/clangd/index/MemIndex.cpp Wed Jan 31 05:40:48
> 2018
> @@ -29,7 +29,7 @@ void MemIndex::build(std::shared_ptr<std
>  }
>
>  bool MemIndex::fuzzyFind(
> -    const Context &Ctx, const FuzzyFindRequest &Req,
> +    const FuzzyFindRequest &Req,
>      llvm::function_ref<void(const Symbol &)> Callback) const {
>    assert(!StringRef(Req.Query).contains("::") &&
>           "There must be no :: in query.");
>
> Modified: clang-tools-extra/trunk/clangd/index/MemIndex.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/index/MemIndex.h?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/index/MemIndex.h (original)
> +++ clang-tools-extra/trunk/clangd/index/MemIndex.h Wed Jan 31 05:40:48
> 2018
> @@ -28,7 +28,7 @@ public:
>    static std::unique_ptr<SymbolIndex> build(SymbolSlab Slab);
>
>    bool
> -  fuzzyFind(const Context &Ctx, const FuzzyFindRequest &Req,
> +  fuzzyFind(const FuzzyFindRequest &Req,
>              llvm::function_ref<void(const Symbol &)> Callback) const
> override;
>
>  private:
>
> Modified: clang-tools-extra/trunk/clangd/index/Merge.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/index/Merge.cpp?rev=323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/index/Merge.cpp (original)
> +++ clang-tools-extra/trunk/clangd/index/Merge.cpp Wed Jan 31 05:40:48
> 2018
> @@ -24,7 +24,7 @@ class MergedIndex : public SymbolIndex {
>     //          - find the generating file from each Symbol which is
> Static-only
>     //          - ask Dynamic if it has that file (needs new SymbolIndex
> method)
>     //          - if so, drop the Symbol.
> -   bool fuzzyFind(const Context &Ctx, const FuzzyFindRequest &Req,
> +   bool fuzzyFind(const FuzzyFindRequest &Req,
>                    function_ref<void(const Symbol &)> Callback) const
> override {
>       // We can't step through both sources in parallel. So:
>       //  1) query all dynamic symbols, slurping results into a slab
> @@ -34,13 +34,12 @@ class MergedIndex : public SymbolIndex {
>       //  3) now yield all the dynamic symbols we haven't processed.
>       bool More = false; // We'll be incomplete if either source was.
>       SymbolSlab::Builder DynB;
> -     More |=
> -         Dynamic->fuzzyFind(Ctx, Req, [&](const Symbol &S) {
> DynB.insert(S); });
> +     More |= Dynamic->fuzzyFind(Req, [&](const Symbol &S) {
> DynB.insert(S); });
>       SymbolSlab Dyn = std::move(DynB).build();
>
>       DenseSet<SymbolID> SeenDynamicSymbols;
>       Symbol::Details Scratch;
> -     More |= Static->fuzzyFind(Ctx, Req, [&](const Symbol &S) {
> +     More |= Static->fuzzyFind(Req, [&](const Symbol &S) {
>         auto DynS = Dyn.find(S.ID);
>         if (DynS == Dyn.end())
>           return Callback(S);
>
> Modified: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/unittests/clangd/ClangdTests.cpp?rev=323872&r1=
> 323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp (original)
> +++ clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp Wed Jan 31
> 05:40:48 2018
> @@ -9,7 +9,6 @@
>
>  #include "ClangdLSPServer.h"
>  #include "ClangdServer.h"
> -#include "Context.h"
>  #include "TestFS.h"
>  #include "clang/Config/config.h"
>  #include "llvm/ADT/SmallVector.h"
> @@ -58,7 +57,7 @@ static bool diagsContainErrors(ArrayRef<
>  class ErrorCheckingDiagConsumer : public DiagnosticsConsumer {
>  public:
>    void
> -  onDiagnosticsReady(const Context &Ctx, PathRef File,
> +  onDiagnosticsReady(PathRef File,
>                       Tagged<std::vector<DiagWithFixIts>> Diagnostics)
> override {
>      bool HadError = diagsContainErrors(Diagnostics.Value);
>
> @@ -143,8 +142,7 @@ protected:
>
>      // Have to sync reparses because requests are processed on the calling
>      // thread.
> -    auto AddDocFuture =
> -        Server.addDocument(Context::empty(), SourceFilename,
> SourceContents);
> +    auto AddDocFuture = Server.addDocument(SourceFilename,
> SourceContents);
>
>      auto Result = dumpASTWithoutMemoryLocs(Server, SourceFilename);
>
> @@ -211,21 +209,21 @@ int b = a;
>    FS.ExpectedFile = FooCpp;
>
>    // To sync reparses before checking for errors.
> -  std::future<Context> ParseFuture;
> +  std::future<void> ParseFuture;
>
> -  ParseFuture = Server.addDocument(Context::empty(), FooCpp,
> SourceContents);
> +  ParseFuture = Server.addDocument(FooCpp, SourceContents);
>    auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp);
>    ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
>              std::future_status::ready);
>    EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
>
> -  ParseFuture = Server.addDocument(Context::empty(), FooCpp, "");
> +  ParseFuture = Server.addDocument(FooCpp, "");
>    auto DumpParseEmpty = dumpASTWithoutMemoryLocs(Server, FooCpp);
>    ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
>              std::future_status::ready);
>    EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
>
> -  ParseFuture = Server.addDocument(Context::empty(), FooCpp,
> SourceContents);
> +  ParseFuture = Server.addDocument(FooCpp, SourceContents);
>    auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);
>    ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
>              std::future_status::ready);
> @@ -256,23 +254,23 @@ int b = a;
>    FS.ExpectedFile = FooCpp;
>
>    // To sync reparses before checking for errors.
> -  std::future<Context> ParseFuture;
> +  std::future<void> ParseFuture;
>
> -  ParseFuture = Server.addDocument(Context::empty(), FooCpp,
> SourceContents);
> +  ParseFuture = Server.addDocument(FooCpp, SourceContents);
>    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(Context::empty(), FooCpp);
> +  ParseFuture = Server.forceReparse(FooCpp);
>    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(Context::empty(), FooCpp);
> +  ParseFuture = Server.forceReparse(FooCpp);
>    auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);
>    EXPECT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
>              std::future_status::ready);
> @@ -302,22 +300,16 @@ TEST_F(ClangdVFSTest, CheckVersions) {
>    // No need to sync reparses, because requests are processed on the
> calling
>    // thread.
>    FS.Tag = "123";
> -  Server.addDocument(Context::empty(), FooCpp, SourceContents);
> -  EXPECT_EQ(
> -      Server.codeComplete(Context::empty(), FooCpp, Position{0, 0},
> CCOpts)
> -          .get()
> -          .second.Tag,
> -      FS.Tag);
> +  Server.addDocument(FooCpp, SourceContents);
> +  EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0},
> CCOpts).get().Tag,
> +            FS.Tag);
>    EXPECT_EQ(DiagConsumer.lastVFSTag(), FS.Tag);
>
>    FS.Tag = "321";
> -  Server.addDocument(Context::empty(), FooCpp, SourceContents);
> +  Server.addDocument(FooCpp, SourceContents);
>    EXPECT_EQ(DiagConsumer.lastVFSTag(), FS.Tag);
> -  EXPECT_EQ(
> -      Server.codeComplete(Context::empty(), FooCpp, Position{0, 0},
> CCOpts)
> -          .get()
> -          .second.Tag,
> -      FS.Tag);
> +  EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0},
> CCOpts).get().Tag,
> +            FS.Tag);
>  }
>
>  // Only enable this test on Unix
> @@ -365,14 +357,14 @@ mock_string x;
>
>    // No need to sync reparses, because requests are processed on the
> calling
>    // thread.
> -  Server.addDocument(Context::empty(), FooCpp, SourceContents);
> +  Server.addDocument(FooCpp, SourceContents);
>    EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
>
>    const auto SourceContentsWithError = R"cpp(
>  #include <string>
>  std::string x;
>  )cpp";
> -  Server.addDocument(Context::empty(), FooCpp, SourceContentsWithError);
> +  Server.addDocument(FooCpp, SourceContentsWithError);
>    EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
>  }
>  #endif // LLVM_ON_UNIX
> @@ -402,26 +394,26 @@ struct bar { T x; };
>
>    // First parse files in C mode and check they produce errors.
>    CDB.ExtraClangFlags = {"-xc"};
> -  Server.addDocument(Context::empty(), FooCpp, SourceContents1);
> +  Server.addDocument(FooCpp, SourceContents1);
>    EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
> -  Server.addDocument(Context::empty(), FooCpp, SourceContents2);
> +  Server.addDocument(FooCpp, SourceContents2);
>    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(Context::empty(), FooCpp, SourceContents1);
> +  Server.addDocument(FooCpp, SourceContents1);
>    EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
> -  Server.addDocument(Context::empty(), FooCpp, SourceContents2);
> +  Server.addDocument(FooCpp, SourceContents2);
>    EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
>    // But forceReparse should reparse the file with proper flags.
> -  Server.forceReparse(Context::empty(), FooCpp);
> +  Server.forceReparse(FooCpp);
>    EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
>    // Subsequent addDocument calls should finish without errors too.
> -  Server.addDocument(Context::empty(), FooCpp, SourceContents1);
> +  Server.addDocument(FooCpp, SourceContents1);
>    EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
> -  Server.addDocument(Context::empty(), FooCpp, SourceContents2);
> +  Server.addDocument(FooCpp, SourceContents2);
>    EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
>  }
>
> @@ -448,16 +440,16 @@ struct Something {
>
>    EXPECT_THAT(Server.getUsedBytesPerFile(), IsEmpty());
>
> -  Server.addDocument(Context::empty(), FooCpp, SourceContents);
> -  Server.addDocument(Context::empty(), BarCpp, SourceContents);
> +  Server.addDocument(FooCpp, SourceContents);
> +  Server.addDocument(BarCpp, SourceContents);
>
>    EXPECT_THAT(Server.getUsedBytesPerFile(),
>                UnorderedElementsAre(Pair(FooCpp, Gt(0u)), Pair(BarCpp,
> Gt(0u))));
>
> -  Server.removeDocument(Context::empty(), FooCpp);
> +  Server.removeDocument(FooCpp);
>    EXPECT_THAT(Server.getUsedBytesPerFile(), ElementsAre(Pair(BarCpp,
> Gt(0u))));
>
> -  Server.removeDocument(Context::empty(), BarCpp);
> +  Server.removeDocument(BarCpp);
>    EXPECT_THAT(Server.getUsedBytesPerFile(), IsEmpty());
>  }
>
> @@ -515,7 +507,7 @@ int d;
>      TestDiagConsumer() : Stats(FilesCount, FileStat()) {}
>
>      void onDiagnosticsReady(
> -        const Context &Ctx, PathRef File,
> +        PathRef File,
>          Tagged<std::vector<DiagWithFixIts>> Diagnostics) override {
>        StringRef FileIndexStr = llvm::sys::path::stem(File);
>        ASSERT_TRUE(FileIndexStr.consume_front("Foo"));
> @@ -547,7 +539,7 @@ int d;
>      unsigned RequestsWithErrors = 0;
>      bool LastContentsHadErrors = false;
>      bool FileIsRemoved = true;
> -    std::future<Context> LastRequestFuture;
> +    std::future<void> LastRequestFuture;
>    };
>
>    std::vector<RequestStats> ReqStats;
> @@ -574,7 +566,7 @@ int d;
>
>      // Some helpers.
>      auto UpdateStatsOnAddDocument = [&](unsigned FileIndex, bool
> HadErrors,
> -                                        std::future<Context> Future) {
> +                                        std::future<void> Future) {
>        auto &Stats = ReqStats[FileIndex];
>
>        if (HadErrors)
> @@ -587,7 +579,7 @@ int d;
>      };
>
>      auto UpdateStatsOnRemoveDocument = [&](unsigned FileIndex,
> -                                           std::future<Context> Future) {
> +                                           std::future<void> Future) {
>        auto &Stats = ReqStats[FileIndex];
>
>        Stats.FileIsRemoved = true;
> @@ -595,7 +587,7 @@ int d;
>      };
>
>      auto UpdateStatsOnForceReparse = [&](unsigned FileIndex,
> -                                         std::future<Context> Future) {
> +                                         std::future<void> Future) {
>        auto &Stats = ReqStats[FileIndex];
>
>        Stats.LastRequestFuture = std::move(Future);
> @@ -607,10 +599,9 @@ int d;
>
>      auto AddDocument = [&](unsigned FileIndex) {
>        bool ShouldHaveErrors = ShouldHaveErrorsDist(RandGen);
> -      auto Future =
> -          Server.addDocument(Context::empty(), FilePaths[FileIndex],
> -                             ShouldHaveErrors ? SourceContentsWithErrors
> -                                              :
> SourceContentsWithoutErrors);
> +      auto Future = Server.addDocument(
> +          FilePaths[FileIndex], ShouldHaveErrors ?
> SourceContentsWithErrors
> +                                                 :
> SourceContentsWithoutErrors);
>        UpdateStatsOnAddDocument(FileIndex, ShouldHaveErrors,
> std::move(Future));
>      };
>
> @@ -626,7 +617,7 @@ int d;
>        if (ReqStats[FileIndex].FileIsRemoved)
>          AddDocument(FileIndex);
>
> -      auto Future = Server.forceReparse(Context::empty(),
> FilePaths[FileIndex]);
> +      auto Future = Server.forceReparse(FilePaths[FileIndex]);
>        UpdateStatsOnForceReparse(FileIndex, std::move(Future));
>      };
>
> @@ -636,8 +627,7 @@ int d;
>        if (ReqStats[FileIndex].FileIsRemoved)
>          AddDocument(FileIndex);
>
> -      auto Future =
> -          Server.removeDocument(Context::empty(), FilePaths[FileIndex]);
> +      auto Future = Server.removeDocument(FilePaths[FileIndex]);
>        UpdateStatsOnRemoveDocument(FileIndex, std::move(Future));
>      };
>
> @@ -655,7 +645,7 @@ int d;
>        // cancelled by any subsequent AddDocument/RemoveDocument request
> to the
>        // same file.
>        Server
> -          .codeComplete(Context::empty(), FilePaths[FileIndex], Pos,
> +          .codeComplete(FilePaths[FileIndex], Pos,
>                          clangd::CodeCompleteOptions())
>            .wait();
>      };
> @@ -667,8 +657,7 @@ int d;
>          AddDocument(FileIndex);
>
>        Position Pos{LineDist(RandGen), ColumnDist(RandGen)};
> -      ASSERT_TRUE(!!Server.findDefinitions(Context::empty(),
> -                                           FilePaths[FileIndex], Pos));
> +      ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos));
>      };
>
>      std::vector<std::function<void()>> AsyncRequests = {
> @@ -803,7 +792,7 @@ TEST_F(ClangdThreadingTest, NoConcurrent
>          : StartSecondReparse(std::move(StartSecondReparse)) {}
>
>      void onDiagnosticsReady(
> -        const Context &Ctx, PathRef File,
> +        PathRef File,
>          Tagged<std::vector<DiagWithFixIts>> Diagnostics) override {
>
>        std::unique_lock<std::mutex> Lock(Mutex, std::try_to_lock_t());
> @@ -851,11 +840,10 @@ int d;
>    MockCompilationDatabase CDB;
>    ClangdServer Server(CDB, DiagConsumer, FS, 4,
>                        /*StorePreamblesInMemory=*/true);
> -  Server.addDocument(Context::empty(), FooCpp, SourceContentsWithErrors);
> +  Server.addDocument(FooCpp, SourceContentsWithErrors);
>    StartSecondReparse.wait();
>
> -  auto Future =
> -      Server.addDocument(Context::empty(), FooCpp,
> SourceContentsWithoutErrors);
> +  auto Future = Server.addDocument(FooCpp, SourceContentsWithoutErrors);
>    Future.wait();
>  }
>
>
> Modified: clang-tools-extra/trunk/unittests/clangd/ClangdUnitTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/unittests/clangd/ClangdUnitTests.cpp?rev=323872&r1=323871&r2=323872&
> view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/unittests/clangd/ClangdUnitTests.cpp
> (original)
> +++ clang-tools-extra/trunk/unittests/clangd/ClangdUnitTests.cpp Wed Jan
> 31 05:40:48 2018
> @@ -43,9 +43,9 @@ ParsedAST build(StringRef Code, std::vec
>    Cmd.insert(Cmd.begin() + 1, Flags.begin(), Flags.end());
>    auto CI = createInvocationFromCommandLine(Cmd);
>    auto Buf = MemoryBuffer::getMemBuffer(Code);
> -  auto AST = ParsedAST::Build(
> -      Context::empty(), std::move(CI), nullptr, std::move(Buf),
> -      std::make_shared<PCHContainerOperations>(),
> vfs::getRealFileSystem());
> +  auto AST = ParsedAST::Build(std::move(CI), nullptr, std::move(Buf),
> +                              std::make_shared<PCHContainerOperations>(),
> +                              vfs::getRealFileSystem());
>    assert(AST.hasValue());
>    return std::move(*AST);
>  }
>
> Modified: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/unittests/clangd/CodeCompleteTests.cpp?rev=
> 323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
> (original)
> +++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Wed
> Jan 31 05:40:48 2018
> @@ -11,7 +11,6 @@
>  #include "ClangdServer.h"
>  #include "CodeComplete.h"
>  #include "Compiler.h"
> -#include "Context.h"
>  #include "Matchers.h"
>  #include "Protocol.h"
>  #include "SourceCode.h"
> @@ -61,10 +60,8 @@ using ::testing::UnorderedElementsAre;
>  using ::testing::Field;
>
>  class IgnoreDiagnostics : public DiagnosticsConsumer {
> -  void
> -  onDiagnosticsReady(const Context &Ctx, PathRef File,
> -                     Tagged<std::vector<DiagWithFixIts>> Diagnostics)
> override {
> -  }
> +  void onDiagnosticsReady(
> +      PathRef File, Tagged<std::vector<DiagWithFixIts>> Diagnostics)
> override {}
>  };
>
>  // GMock helpers for matching completion items.
> @@ -123,11 +120,9 @@ CompletionList completions(StringRef Tex
>                        /*StorePreamblesInMemory=*/true);
>    auto File = getVirtualTestFilePath("foo.cpp");
>    Annotations Test(Text);
> -  Server.addDocument(Context::empty(), File, Test.code()).wait();
> +  Server.addDocument(File, Test.code()).wait();
>    auto CompletionList =
> -      Server.codeComplete(Context::empty(), File, Test.point(), Opts)
> -          .get()
> -          .second.Value;
> +      Server.codeComplete(File, Test.point(), Opts).get().Value;
>    // Sanity-check that filterText is valid.
>    EXPECT_THAT(CompletionList.items, Each(NameContainsFilter()));
>    return CompletionList;
> @@ -349,15 +344,15 @@ TEST(CompletionTest, CheckContentsOverri
>    ClangdServer Server(CDB, DiagConsumer, FS,
> getDefaultAsyncThreadsCount(),
>                        /*StorePreamblesInMemory=*/true);
>    auto File = getVirtualTestFilePath("foo.cpp");
> -  Server.addDocument(Context::empty(), File, "ignored text!");
> +  Server.addDocument(File, "ignored text!");
>
>    Annotations Example("int cbc; int b = ^;");
> -  auto Results = Server
> -                     .codeComplete(Context::empty(), File,
> Example.point(),
> -                                   clangd::CodeCompleteOptions(),
> -                                   StringRef(Example.code()))
> -                     .get()
> -                     .second.Value;
> +  auto Results =
> +      Server
> +          .codeComplete(File, Example.point(),
> clangd::CodeCompleteOptions(),
> +                        StringRef(Example.code()))
> +          .get()
> +          .Value;
>    EXPECT_THAT(Results.items, Contains(Named("cbc")));
>  }
>
> @@ -558,28 +553,20 @@ TEST(CompletionTest, IndexSuppressesPrea
>        void f() { ns::^; }
>        void f() { ns::preamble().$2^; }
>    )cpp");
> -  Server.addDocument(Context::empty(), File, Test.code()).wait();
> +  Server.addDocument(File, Test.code()).wait();
>    clangd::CodeCompleteOptions Opts = {};
>
> -  auto WithoutIndex =
> -      Server.codeComplete(Context::empty(), File, Test.point(), Opts)
> -          .get()
> -          .second.Value;
> +  auto WithoutIndex = Server.codeComplete(File, Test.point(),
> Opts).get().Value;
>    EXPECT_THAT(WithoutIndex.items,
>                UnorderedElementsAre(Named("local"), Named("preamble")));
>
>    auto I = memIndex({var("ns::index")});
>    Opts.Index = I.get();
> -  auto WithIndex =
> -      Server.codeComplete(Context::empty(), File, Test.point(), Opts)
> -          .get()
> -          .second.Value;
> +  auto WithIndex = Server.codeComplete(File, Test.point(),
> Opts).get().Value;
>    EXPECT_THAT(WithIndex.items,
>                UnorderedElementsAre(Named("local"), Named("index")));
>    auto ClassFromPreamble =
> -      Server.codeComplete(Context::empty(), File, Test.point("2"), Opts)
> -          .get()
> -          .second.Value;
> +      Server.codeComplete(File, Test.point("2"), Opts).get().Value;
>    EXPECT_THAT(ClassFromPreamble.items, Contains(Named("member")));
>  }
>
> @@ -592,7 +579,7 @@ TEST(CompletionTest, DynamicIndexMultiFi
>                        /*BuildDynamicSymbolIndex=*/true);
>
>    Server
> -      .addDocument(Context::empty(), getVirtualTestFilePath("foo.cpp"),
> R"cpp(
> +      .addDocument(getVirtualTestFilePath("foo.cpp"), R"cpp(
>        namespace ns { class XYZ {}; void foo(int x) {} }
>    )cpp")
>        .wait();
> @@ -606,11 +593,9 @@ TEST(CompletionTest, DynamicIndexMultiFi
>        }
>        void f() { ns::^ }
>    )cpp");
> -  Server.addDocument(Context::empty(), File, Test.code()).wait();
> +  Server.addDocument(File, Test.code()).wait();
>
> -  auto Results = Server.codeComplete(Context::empty(), File,
> Test.point(), {})
> -                     .get()
> -                     .second.Value;
> +  auto Results = Server.codeComplete(File, Test.point(), {}).get().Value;
>    // "XYZ" and "foo" are not included in the file being completed but are
> still
>    // visible through the index.
>    EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
> @@ -637,8 +622,8 @@ SignatureHelp signatures(StringRef Text)
>                        /*StorePreamblesInMemory=*/true);
>    auto File = getVirtualTestFilePath("foo.cpp");
>    Annotations Test(Text);
> -  Server.addDocument(Context::empty(), File, Test.code());
> -  auto R = Server.signatureHelp(Context::empty(), File, Test.point());
> +  Server.addDocument(File, Test.code());
> +  auto R = Server.signatureHelp(File, Test.point());
>    assert(R);
>    return R.get().Value;
>  }
> @@ -707,7 +692,7 @@ TEST(SignatureHelpTest, ActiveArg) {
>  class IndexRequestCollector : public SymbolIndex {
>  public:
>    bool
> -  fuzzyFind(const Context &Ctx, const FuzzyFindRequest &Req,
> +  fuzzyFind(const FuzzyFindRequest &Req,
>              llvm::function_ref<void(const Symbol &)> Callback) const
> override {
>      Requests.push_back(Req);
>      return false;
>
> Modified: clang-tools-extra/trunk/unittests/clangd/FileIndexTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/unittests/clangd/FileIndexTests.cpp?rev=323872&
> r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/unittests/clangd/FileIndexTests.cpp (original)
> +++ clang-tools-extra/trunk/unittests/clangd/FileIndexTests.cpp Wed Jan
> 31 05:40:48 2018
> @@ -76,8 +76,7 @@ TEST(FileSymbolsTest, SnapshotAliveAfter
>  std::vector<std::string> match(const SymbolIndex &I,
>                                 const FuzzyFindRequest &Req) {
>    std::vector<std::string> Matches;
> -  auto Ctx = Context::empty();
> -  I.fuzzyFind(Ctx, Req, [&](const Symbol &Sym) {
> +  I.fuzzyFind(Req, [&](const Symbol &Sym) {
>      Matches.push_back((Sym.Scope + Sym.Name).str());
>    });
>    return Matches;
> @@ -85,7 +84,6 @@ std::vector<std::string> match(const Sym
>
>  /// Create an ParsedAST for \p Code. Returns None if \p Code is empty.
>  llvm::Optional<ParsedAST> build(std::string Path, llvm::StringRef Code) {
> -  Context Ctx = Context::empty();
>    if (Code.empty())
>      return llvm::None;
>    const char *Args[] = {"clang", "-xc++", Path.c_str()};
> @@ -93,7 +91,7 @@ llvm::Optional<ParsedAST> build(std::str
>    auto CI = createInvocationFromCommandLine(Args);
>
>    auto Buf = llvm::MemoryBuffer::getMemBuffer(Code);
> -  auto AST = ParsedAST::Build(Ctx, std::move(CI), nullptr, std::move(Buf),
> +  auto AST = ParsedAST::Build(std::move(CI), nullptr, std::move(Buf),
>                                std::make_shared<PCHContainerOperations>(),
>                                vfs::getRealFileSystem());
>    assert(AST.hasValue());
> @@ -102,9 +100,8 @@ llvm::Optional<ParsedAST> build(std::str
>
>  TEST(FileIndexTest, IndexAST) {
>    FileIndex M;
> -  auto Ctx = Context::empty();
>    M.update(
> -      Ctx, "f1",
> +      "f1",
>        build("f1", "namespace ns { void f() {} class X {};
> }").getPointer());
>
>    FuzzyFindRequest Req;
> @@ -115,9 +112,8 @@ TEST(FileIndexTest, IndexAST) {
>
>  TEST(FileIndexTest, NoLocal) {
>    FileIndex M;
> -  auto Ctx = Context::empty();
>    M.update(
> -      Ctx, "f1",
> +      "f1",
>        build("f1", "namespace ns { void f() { int local = 0; } class X {};
> }")
>            .getPointer());
>
> @@ -128,12 +124,11 @@ TEST(FileIndexTest, NoLocal) {
>
>  TEST(FileIndexTest, IndexMultiASTAndDeduplicate) {
>    FileIndex M;
> -  auto Ctx = Context::empty();
>    M.update(
> -      Ctx, "f1",
> +      "f1",
>        build("f1", "namespace ns { void f() {} class X {};
> }").getPointer());
>    M.update(
> -      Ctx, "f2",
> +      "f2",
>        build("f2", "namespace ns { void ff() {} class X {};
> }").getPointer());
>
>    FuzzyFindRequest Req;
> @@ -144,9 +139,8 @@ TEST(FileIndexTest, IndexMultiASTAndDedu
>
>  TEST(FileIndexTest, RemoveAST) {
>    FileIndex M;
> -  auto Ctx = Context::empty();
>    M.update(
> -      Ctx, "f1",
> +      "f1",
>        build("f1", "namespace ns { void f() {} class X {};
> }").getPointer());
>
>    FuzzyFindRequest Req;
> @@ -154,21 +148,19 @@ TEST(FileIndexTest, RemoveAST) {
>    Req.Scopes = {"ns::"};
>    EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X"));
>
> -  M.update(Ctx, "f1", nullptr);
> +  M.update("f1", nullptr);
>    EXPECT_THAT(match(M, Req), UnorderedElementsAre());
>  }
>
>  TEST(FileIndexTest, RemoveNonExisting) {
>    FileIndex M;
> -  auto Ctx = Context::empty();
> -  M.update(Ctx, "no", nullptr);
> +  M.update("no", nullptr);
>    EXPECT_THAT(match(M, FuzzyFindRequest()), UnorderedElementsAre());
>  }
>
>  TEST(FileIndexTest, IgnoreClassMembers) {
>    FileIndex M;
> -  auto Ctx = Context::empty();
> -  M.update(Ctx, "f1",
> +  M.update("f1",
>             build("f1", "class X { static int m1; int m2; static void f();
> };")
>                 .getPointer());
>
>
> Modified: clang-tools-extra/trunk/unittests/clangd/IndexTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/unittests/clangd/IndexTests.cpp?rev=323872&r1=
> 323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/unittests/clangd/IndexTests.cpp (original)
> +++ clang-tools-extra/trunk/unittests/clangd/IndexTests.cpp Wed Jan 31
> 05:40:48 2018
> @@ -92,8 +92,7 @@ generateNumSymbols(int Begin, int End,
>  std::vector<std::string> match(const SymbolIndex &I,
>                                 const FuzzyFindRequest &Req) {
>    std::vector<std::string> Matches;
> -  auto Ctx = Context::empty();
> -  I.fuzzyFind(Ctx, Req, [&](const Symbol &Sym) {
> +  I.fuzzyFind(Req, [&](const Symbol &Sym) {
>      Matches.push_back(
>          (Sym.Scope + (Sym.Scope.empty() ? "" : "::") + Sym.Name).str());
>    });
>
> Modified: clang-tools-extra/trunk/unittests/clangd/TUSchedulerTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/unittests/clangd/TUSchedulerTests.cpp?rev=
> 323872&r1=323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/unittests/clangd/TUSchedulerTests.cpp
> (original)
> +++ clang-tools-extra/trunk/unittests/clangd/TUSchedulerTests.cpp Wed Jan
> 31 05:40:48 2018
> @@ -7,6 +7,7 @@
>  //
>  //===-------------------------------------------------------
> ---------------===//
>
> +#include "Context.h"
>  #include "TUScheduler.h"
>  #include "TestFS.h"
>  #include "gmock/gmock.h"
> @@ -20,7 +21,7 @@ namespace clangd {
>  using ::testing::Pair;
>  using ::testing::Pointee;
>
> -void ignoreUpdate(Context, llvm::Optional<std::vector<DiagWithFixIts>>)
> {}
> +void ignoreUpdate(llvm::Optional<std::vector<DiagWithFixIts>>) {}
>  void ignoreError(llvm::Error Err) {
>    handleAllErrors(std::move(Err), [](const llvm::ErrorInfoBase &) {});
>  }
> @@ -52,7 +53,7 @@ TEST_F(TUSchedulerTests, MissingFiles) {
>    auto Missing = getVirtualTestFilePath("missing.cpp");
>    changeFile(Missing, "");
>
> -  S.update(Context::empty(), Added, getInputs(Added, ""), ignoreUpdate);
> +  S.update(Added, getInputs(Added, ""), ignoreUpdate);
>
>    // Assert each operation for missing file is an error (even if it's
> available
>    // in VFS).
> @@ -122,46 +123,61 @@ TEST_F(TUSchedulerTests, ManyUpdates) {
>      llvm::StringRef AllContents[] = {Contents1, Contents2, Contents3};
>      const int AllContentsSize = 3;
>
> +    // Scheduler may run tasks asynchronously, but should propagate the
> context.
> +    // We stash a nonce in the context, and verify it in the task.
> +    static Key<int> NonceKey;
> +    int Nonce = 0;
> +
>      for (int FileI = 0; FileI < FilesCount; ++FileI) {
>        for (int UpdateI = 0; UpdateI < UpdatesPerFile; ++UpdateI) {
>          auto Contents = AllContents[(FileI + UpdateI) % AllContentsSize];
>
>          auto File = Files[FileI];
>          auto Inputs = getInputs(File, Contents.str());
> -        static Key<std::pair<int, int>> FileAndUpdateKey;
> -        auto Ctx = Context::empty().derive(FileAndUpdateKey,
> -                                           std::make_pair(FileI,
> UpdateI));
> -        S.update(std::move(Ctx), File, Inputs,
> -                 [FileI, UpdateI, &Mut, &TotalUpdates](
> -                     Context Ctx,
> -                     llvm::Optional<std::vector<DiagWithFixIts>> Diags) {
> -                   EXPECT_THAT(Ctx.get(FileAndUpdateKey),
> -                               Pointee(Pair(FileI, UpdateI)));
> -
> -                   std::lock_guard<std::mutex> Lock(Mut);
> -                   ++TotalUpdates;
> -                 });
> -
> -        S.runWithAST(File, [Inputs, &Mut,
> -                            &TotalASTReads](llvm::Expected<InputsAndAST>
> AST) {
> -          ASSERT_TRUE((bool)AST);
> -          EXPECT_EQ(AST->Inputs.FS, Inputs.FS);
> -          EXPECT_EQ(AST->Inputs.Contents, Inputs.Contents);
> -
> -          std::lock_guard<std::mutex> Lock(Mut);
> -          ++TotalASTReads;
> -        });
> -
> -        S.runWithPreamble(
> -            File, [Inputs, &Mut, &TotalPreambleReads](
> -                      llvm::Expected<InputsAndPreamble> Preamble) {
> -              ASSERT_TRUE((bool)Preamble);
> -              EXPECT_EQ(Preamble->Inputs.FS, Inputs.FS);
> -              EXPECT_EQ(Preamble->Inputs.Contents, Inputs.Contents);
> -
> -              std::lock_guard<std::mutex> Lock(Mut);
> -              ++TotalPreambleReads;
> -            });
> +
> +        {
> +          WithContextValue WithNonce(NonceKey, ++Nonce);
> +          S.update(File, Inputs,
> +                   [Nonce, &Mut, &TotalUpdates](
> +                       llvm::Optional<std::vector<DiagWithFixIts>>
> Diags) {
> +                     EXPECT_THAT(Context::current().get(NonceKey),
> +                                 Pointee(Nonce));
> +
> +                     std::lock_guard<std::mutex> Lock(Mut);
> +                     ++TotalUpdates;
> +                   });
> +        }
> +
> +        {
> +          WithContextValue WithNonce(NonceKey, ++Nonce);
> +          S.runWithAST(File, [Inputs, Nonce, &Mut, &TotalASTReads](
> +                                 llvm::Expected<InputsAndAST> AST) {
> +            EXPECT_THAT(Context::current().get(NonceKey),
> Pointee(Nonce));
> +
> +            ASSERT_TRUE((bool)AST);
> +            EXPECT_EQ(AST->Inputs.FS, Inputs.FS);
> +            EXPECT_EQ(AST->Inputs.Contents, Inputs.Contents);
> +
> +            std::lock_guard<std::mutex> Lock(Mut);
> +            ++TotalASTReads;
> +          });
> +        }
> +
> +        {
> +          WithContextValue WithNonce(NonceKey, ++Nonce);
> +          S.runWithPreamble(
> +              File, [Inputs, Nonce, &Mut, &TotalPreambleReads](
> +                        llvm::Expected<InputsAndPreamble> Preamble) {
> +                EXPECT_THAT(Context::current().get(NonceKey),
> Pointee(Nonce));
> +
> +                ASSERT_TRUE((bool)Preamble);
> +                EXPECT_EQ(Preamble->Inputs.FS, Inputs.FS);
> +                EXPECT_EQ(Preamble->Inputs.Contents, Inputs.Contents);
> +
> +                std::lock_guard<std::mutex> Lock(Mut);
> +                ++TotalPreambleReads;
> +              });
> +        }
>        }
>      }
>    } // TUScheduler destructor waits for all operations to finish.
>
> Modified: clang-tools-extra/trunk/unittests/clangd/TraceTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/unittests/clangd/TraceTests.cpp?rev=323872&r1=
> 323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/unittests/clangd/TraceTests.cpp (original)
> +++ clang-tools-extra/trunk/unittests/clangd/TraceTests.cpp Wed Jan 31
> 05:40:48 2018
> @@ -7,7 +7,6 @@
>  //
>  //===-------------------------------------------------------
> ---------------===//
>
> -#include "Context.h"
>  #include "Trace.h"
>
>  #include "llvm/ADT/DenseMap.h"
> @@ -78,8 +77,8 @@ TEST(TraceTest, SmokeTest) {
>      auto JSONTracer = trace::createJSONTracer(OS);
>      trace::Session Session(*JSONTracer);
>      {
> -      trace::Span Tracer(Context::empty(), "A");
> -      trace::log(Tracer.Ctx, "B");
> +      trace::Span Tracer("A");
> +      trace::log("B");
>      }
>    }
>
>
> Modified: clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/unittests/clangd/XRefsTests.cpp?rev=323872&r1=
> 323871&r2=323872&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp (original)
> +++ clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp Wed Jan 31
> 05:40:48 2018
> @@ -43,9 +43,9 @@ ParsedAST build(StringRef Code) {
>    auto CI =
>        createInvocationFromCommandLine({"clang", "-xc++",
> TestFile.c_str()});
>    auto Buf = MemoryBuffer::getMemBuffer(Code);
> -  auto AST = ParsedAST::Build(
> -      Context::empty(), std::move(CI), nullptr, std::move(Buf),
> -      std::make_shared<PCHContainerOperations>(),
> vfs::getRealFileSystem());
> +  auto AST = ParsedAST::Build(std::move(CI), nullptr, std::move(Buf),
> +                              std::make_shared<PCHContainerOperations>(),
> +                              vfs::getRealFileSystem());
>    assert(AST.hasValue());
>    return std::move(*AST);
>  }
> @@ -101,8 +101,7 @@ TEST(HighlightsTest, All) {
>    for (const char *Test : Tests) {
>      Annotations T(Test);
>      auto AST = build(T.code());
> -    EXPECT_THAT(findDocumentHighlights(Context::empty(), AST, T.point()),
> -                HighlightsFrom(T))
> +    EXPECT_THAT(findDocumentHighlights(AST, T.point()),
> HighlightsFrom(T))
>          << Test;
>    }
>  }
> @@ -222,7 +221,7 @@ TEST(GoToDefinition, All) {
>    for (const char *Test : Tests) {
>      Annotations T(Test);
>      auto AST = build(T.code());
> -    EXPECT_THAT(findDefinitions(Context::empty(), AST, T.point()),
> +    EXPECT_THAT(findDefinitions(AST, T.point()),
>                  ElementsAre(RangeIs(T.range())))
>          << Test;
>    }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180131/5ddd590b/attachment-0001.html>


More information about the cfe-commits mailing list