//===--- ClangdLSPServer.cpp - LSP server ------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "ClangdLSPServer.h"
#include "ClangdServer.h"
#include "CodeComplete.h"
#include "CompileCommands.h"
#include "Diagnostics.h"
#include "Feature.h"
#include "GlobalCompilationDatabase.h"
#include "LSPBinder.h"
#include "Protocol.h"
#include "SemanticHighlighting.h"
#include "SourceCode.h"
#include "TUScheduler.h"
#include "URI.h"
#include "refactor/Tweak.h"
#include "support/Cancellation.h"
#include "support/Context.h"
#include "support/MemoryTree.h"
#include "support/Trace.h"
#include "clang/Tooling/Core/Replacement.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <utility>
#include <vector>

namespace clang {
namespace clangd {
namespace {
// Tracks end-to-end latency of high level lsp calls. Measurements are in
// seconds.
constexpr trace::Metric LSPLatency("lsp_latency", trace::Metric::Distribution,
                                   "method_name");

// LSP defines file versions as numbers that increase.
// ClangdServer treats them as opaque and therefore uses strings instead.
std::string encodeVersion(std::optional<int64_t> LSPVersion) {
  return LSPVersion ? llvm::to_string(*LSPVersion) : "";
}
std::optional<int64_t> decodeVersion(llvm::StringRef Encoded) {
  int64_t Result;
  if (llvm::to_integer(Encoded, Result, 10))
    return Result;
  if (!Encoded.empty()) // Empty can be e.g. diagnostics on close.
    elog("unexpected non-numeric version {0}", Encoded);
  return std::nullopt;
}

const llvm::StringLiteral ApplyFixCommand = "clangd.applyFix";
const llvm::StringLiteral ApplyTweakCommand = "clangd.applyTweak";
const llvm::StringLiteral ApplyRenameCommand = "clangd.applyRename";

CodeAction toCodeAction(const ClangdServer::CodeActionResult::Rename &R,
                        const URIForFile &File) {
  CodeAction CA;
  CA.title = R.FixMessage;
  CA.kind = std::string(CodeAction::REFACTOR_KIND);
  CA.command.emplace();
  CA.command->title = R.FixMessage;
  CA.command->command = std::string(ApplyRenameCommand);
  RenameParams Params;
  Params.textDocument = TextDocumentIdentifier{File};
  Params.position = R.Diag.Range.start;
  Params.newName = R.NewName;
  CA.command->argument = Params;
  return CA;
}

/// Transforms a tweak into a code action that would apply it if executed.
/// EXPECTS: T.prepare() was called and returned true.
CodeAction toCodeAction(const ClangdServer::TweakRef &T, const URIForFile &File,
                        Range Selection) {
  CodeAction CA;
  CA.title = T.Title;
  CA.kind = T.Kind.str();
  // This tweak may have an expensive second stage, we only run it if the user
  // actually chooses it in the UI. We reply with a command that would run the
  // corresponding tweak.
  // FIXME: for some tweaks, computing the edits is cheap and we could send them
  //        directly.
  CA.command.emplace();
  CA.command->title = T.Title;
  CA.command->command = std::string(ApplyTweakCommand);
  TweakArgs Args;
  Args.file = File;
  Args.tweakID = T.ID;
  Args.selection = Selection;
  CA.command->argument = std::move(Args);
  return CA;
}

/// Convert from Fix to LSP CodeAction.
CodeAction toCodeAction(const Fix &F, const URIForFile &File,
                        const std::optional<int64_t> &Version,
                        bool SupportsDocumentChanges,
                        bool SupportChangeAnnotation) {
  CodeAction Action;
  Action.title = F.Message;
  Action.kind = std::string(CodeAction::QUICKFIX_KIND);
  Action.edit.emplace();
  if (!SupportsDocumentChanges) {
    Action.edit->changes.emplace();
    auto &Changes = (*Action.edit->changes)[File.uri()];
    for (const auto &E : F.Edits)
      Changes.push_back({E.range, E.newText, /*annotationId=*/""});
  } else {
    Action.edit->documentChanges.emplace();
    TextDocumentEdit &Edit = Action.edit->documentChanges->emplace_back();
    Edit.textDocument = VersionedTextDocumentIdentifier{{File}, Version};
    for (const auto &E : F.Edits)
      Edit.edits.push_back(
          {E.range, E.newText,
           SupportChangeAnnotation ? E.annotationId : ""});
    if (SupportChangeAnnotation) {
      for (const auto &[AID, Annotation]: F.Annotations)
        Action.edit->changeAnnotations[AID] = Annotation;
    }
  }
  return Action;
}

void adjustSymbolKinds(llvm::MutableArrayRef<DocumentSymbol> Syms,
                       SymbolKindBitset Kinds) {
  for (auto &S : Syms) {
    S.kind = adjustKindToCapability(S.kind, Kinds);
    adjustSymbolKinds(S.children, Kinds);
  }
}

SymbolKindBitset defaultSymbolKinds() {
  SymbolKindBitset Defaults;
  for (size_t I = SymbolKindMin; I <= static_cast<size_t>(SymbolKind::Array);
       ++I)
    Defaults.set(I);
  return Defaults;
}

CompletionItemKindBitset defaultCompletionItemKinds() {
  CompletionItemKindBitset Defaults;
  for (size_t I = CompletionItemKindMin;
       I <= static_cast<size_t>(CompletionItemKind::Reference); ++I)
    Defaults.set(I);
  return Defaults;
}

// Makes sure edits in \p FE are applicable to latest file contents reported by
// editor. If not generates an error message containing information about files
// that needs to be saved.
llvm::Error validateEdits(const ClangdServer &Server, const FileEdits &FE) {
  size_t InvalidFileCount = 0;
  llvm::StringRef LastInvalidFile;
  for (const auto &It : FE) {
    if (auto Draft = Server.getDraft(It.first())) {
      // If the file is open in user's editor, make sure the version we
      // saw and current version are compatible as this is the text that
      // will be replaced by editors.
      if (!It.second.canApplyTo(*Draft)) {
        ++InvalidFileCount;
        LastInvalidFile = It.first();
      }
    }
  }
  if (!InvalidFileCount)
    return llvm::Error::success();
  if (InvalidFileCount == 1)
    return error("File must be saved first: {0}", LastInvalidFile);
  return error("Files must be saved first: {0} (and {1} others)",
               LastInvalidFile, InvalidFileCount - 1);
}
} // namespace

// MessageHandler dispatches incoming LSP messages.
// It handles cross-cutting concerns:
//  - serializes/deserializes protocol objects to JSON
//  - logging of inbound messages
//  - cancellation handling
//  - basic call tracing
// MessageHandler ensures that initialize() is called before any other handler.
class ClangdLSPServer::MessageHandler : public Transport::MessageHandler {
public:
  MessageHandler(ClangdLSPServer &Server) : Server(Server) {}

  bool onNotify(llvm::StringRef Method, llvm::json::Value Params) override {
    trace::Span Tracer(Method, LSPLatency);
    SPAN_ATTACH(Tracer, "Params", Params);
    WithContext HandlerContext(handlerContext());
    log("<-- {0}", Method);
    if (Method == "exit")
      return false;
    auto Handler = Server.Handlers.NotificationHandlers.find(Method);
    if (Handler != Server.Handlers.NotificationHandlers.end()) {
      Handler->second(std::move(Params));
      Server.maybeExportMemoryProfile();
      Server.maybeCleanupMemory();
    } else if (!Server.Server) {
      elog("Notification {0} before initialization", Method);
    } else if (Method == "$/cancelRequest") {
      onCancel(std::move(Params));
    } else {
      log("unhandled notification {0}", Method);
    }
    return true;
  }

  bool onCall(llvm::StringRef Method, llvm::json::Value Params,
              llvm::json::Value ID) override {
    WithContext HandlerContext(handlerContext());
    // Calls can be canceled by the client. Add cancellation context.
    WithContext WithCancel(cancelableRequestContext(ID));
    trace::Span Tracer(Method, LSPLatency);
    SPAN_ATTACH(Tracer, "Params", Params);
    ReplyOnce Reply(ID, Method, &Server, Tracer.Args);
    log("<-- {0}({1})", Method, ID);
    auto Handler = Server.Handlers.MethodHandlers.find(Method);
    if (Handler != Server.Handlers.MethodHandlers.end()) {
      Handler->second(std::move(Params), std::move(Reply));
    } else if (!Server.Server) {
      elog("Call {0} before initialization.", Method);
      Reply(llvm::make_error<LSPError>("server not initialized",
                                       ErrorCode::ServerNotInitialized));
    } else {
      Reply(llvm::make_error<LSPError>("method not found",
                                       ErrorCode::MethodNotFound));
    }
    return true;
  }

  bool onReply(llvm::json::Value ID,
               llvm::Expected<llvm::json::Value> Result) override {
    WithContext HandlerContext(handlerContext());

    Callback<llvm::json::Value> ReplyHandler = nullptr;
    if (auto IntID = ID.getAsInteger()) {
      std::lock_guard<std::mutex> Mutex(CallMutex);
      // Find a corresponding callback for the request ID;
      for (size_t Index = 0; Index < ReplyCallbacks.size(); ++Index) {
        if (ReplyCallbacks[Index].first == *IntID) {
          ReplyHandler = std::move(ReplyCallbacks[Index].second);
          ReplyCallbacks.erase(ReplyCallbacks.begin() +
                               Index); // remove the entry
          break;
        }
      }
    }

    if (!ReplyHandler) {
      // No callback being found, use a default log callback.
      ReplyHandler = [&ID](llvm::Expected<llvm::json::Value> Result) {
        elog("received a reply with ID {0}, but there was no such call", ID);
        if (!Result)
          llvm::consumeError(Result.takeError());
      };
    }

    // Log and run the reply handler.
    if (Result) {
      log("<-- reply({0})", ID);
      ReplyHandler(std::move(Result));
    } else {
      auto Err = Result.takeError();
      log("<-- reply({0}) error: {1}", ID, Err);
      ReplyHandler(std::move(Err));
    }
    return true;
  }

  // Bind a reply callback to a request. The callback will be invoked when
  // clangd receives the reply from the LSP client.
  // Return a call id of the request.
  llvm::json::Value bindReply(Callback<llvm::json::Value> Reply) {
    std::optional<std::pair<int, Callback<llvm::json::Value>>> OldestCB;
    int ID;
    {
      std::lock_guard<std::mutex> Mutex(CallMutex);
      ID = NextCallID++;
      ReplyCallbacks.emplace_back(ID, std::move(Reply));

      // If the queue overflows, we assume that the client didn't reply the
      // oldest request, and run the corresponding callback which replies an
      // error to the client.
      if (ReplyCallbacks.size() > MaxReplayCallbacks) {
        elog("more than {0} outstanding LSP calls, forgetting about {1}",
             MaxReplayCallbacks, ReplyCallbacks.front().first);
        OldestCB = std::move(ReplyCallbacks.front());
        ReplyCallbacks.pop_front();
      }
    }
    if (OldestCB)
      OldestCB->second(
          error("failed to receive a client reply for request ({0})",
                OldestCB->first));
    return ID;
  }

private:
  // Function object to reply to an LSP call.
  // Each instance must be called exactly once, otherwise:
  //  - the bug is logged, and (in debug mode) an assert will fire
  //  - if there was no reply, an error reply is sent
  //  - if there were multiple replies, only the first is sent
  class ReplyOnce {
    std::atomic<bool> Replied = {false};
    std::chrono::steady_clock::time_point Start;
    llvm::json::Value ID;
    std::string Method;
    ClangdLSPServer *Server; // Null when moved-from.
    llvm::json::Object *TraceArgs;

  public:
    ReplyOnce(const llvm::json::Value &ID, llvm::StringRef Method,
              ClangdLSPServer *Server, llvm::json::Object *TraceArgs)
        : Start(std::chrono::steady_clock::now()), ID(ID), Method(Method),
          Server(Server), TraceArgs(TraceArgs) {
      assert(Server);
    }
    ReplyOnce(ReplyOnce &&Other)
        : Replied(Other.Replied.load()), Start(Other.Start),
          ID(std::move(Other.ID)), Method(std::move(Other.Method)),
          Server(Other.Server), TraceArgs(Other.TraceArgs) {
      Other.Server = nullptr;
    }
    ReplyOnce &operator=(ReplyOnce &&) = delete;
    ReplyOnce(const ReplyOnce &) = delete;
    ReplyOnce &operator=(const ReplyOnce &) = delete;

    ~ReplyOnce() {
      // There's one legitimate reason to never reply to a request: clangd's
      // request handler send a call to the client (e.g. applyEdit) and the
      // client never replied. In this case, the ReplyOnce is owned by
      // ClangdLSPServer's reply callback table and is destroyed along with the
      // server. We don't attempt to send a reply in this case, there's little
      // to be gained from doing so.
      if (Server && !Server->IsBeingDestroyed && !Replied) {
        elog("No reply to message {0}({1})", Method, ID);
        assert(false && "must reply to all calls!");
        (*this)(llvm::make_error<LSPError>("server failed to reply",
                                           ErrorCode::InternalError));
      }
    }

    void operator()(llvm::Expected<llvm::json::Value> Reply) {
      assert(Server && "moved-from!");
      if (Replied.exchange(true)) {
        elog("Replied twice to message {0}({1})", Method, ID);
        assert(false && "must reply to each call only once!");
        return;
      }
      auto Duration = std::chrono::steady_clock::now() - Start;
      if (Reply) {
        log("--> reply:{0}({1}) {2:ms}", Method, ID, Duration);
        if (TraceArgs)
          (*TraceArgs)["Reply"] = *Reply;
        std::lock_guard<std::mutex> Lock(Server->TranspWriter);
        Server->Transp.reply(std::move(ID), std::move(Reply));
      } else {
        llvm::Error Err = Reply.takeError();
        log("--> reply:{0}({1}) {2:ms}, error: {3}", Method, ID, Duration, Err);
        if (TraceArgs)
          (*TraceArgs)["Error"] = llvm::to_string(Err);
        std::lock_guard<std::mutex> Lock(Server->TranspWriter);
        Server->Transp.reply(std::move(ID), std::move(Err));
      }
    }
  };

  // Method calls may be cancelled by ID, so keep track of their state.
  // This needs a mutex: handlers may finish on a different thread, and that's
  // when we clean up entries in the map.
  mutable std::mutex RequestCancelersMutex;
  llvm::StringMap<std::pair<Canceler, /*Cookie*/ unsigned>> RequestCancelers;
  unsigned NextRequestCookie = 0; // To disambiguate reused IDs, see below.
  void onCancel(const llvm::json::Value &Params) {
    const llvm::json::Value *ID = nullptr;
    if (auto *O = Params.getAsObject())
      ID = O->get("id");
    if (!ID) {
      elog("Bad cancellation request: {0}", Params);
      return;
    }
    auto StrID = llvm::to_string(*ID);
    std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
    auto It = RequestCancelers.find(StrID);
    if (It != RequestCancelers.end())
      It->second.first(); // Invoke the canceler.
  }

  Context handlerContext() const {
    return Context::current().derive(
        kCurrentOffsetEncoding,
        Server.Opts.Encoding.value_or(OffsetEncoding::UTF16));
  }

  // We run cancelable requests in a context that does two things:
  //  - allows cancellation using RequestCancelers[ID]
  //  - cleans up the entry in RequestCancelers when it's no longer needed
  // If a client reuses an ID, the last wins and the first cannot be canceled.
  Context cancelableRequestContext(const llvm::json::Value &ID) {
    auto Task = cancelableTask(
        /*Reason=*/static_cast<int>(ErrorCode::RequestCancelled));
    auto StrID = llvm::to_string(ID);  // JSON-serialize ID for map key.
    auto Cookie = NextRequestCookie++; // No lock, only called on main thread.
    {
      std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
      RequestCancelers[StrID] = {std::move(Task.second), Cookie};
    }
    // When the request ends, we can clean up the entry we just added.
    // The cookie lets us check that it hasn't been overwritten due to ID
    // reuse.
    return Task.first.derive(llvm::make_scope_exit([this, StrID, Cookie] {
      std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
      auto It = RequestCancelers.find(StrID);
      if (It != RequestCancelers.end() && It->second.second == Cookie)
        RequestCancelers.erase(It);
    }));
  }

  // The maximum number of callbacks held in clangd.
  //
  // We bound the maximum size to the pending map to prevent memory leakage
  // for cases where LSP clients don't reply for the request.
  // This has to go after RequestCancellers and RequestCancellersMutex since it
  // can contain a callback that has a cancelable context.
  static constexpr int MaxReplayCallbacks = 100;
  mutable std::mutex CallMutex;
  int NextCallID = 0; /* GUARDED_BY(CallMutex) */
  std::deque<std::pair</*RequestID*/ int,
                       /*ReplyHandler*/ Callback<llvm::json::Value>>>
      ReplyCallbacks; /* GUARDED_BY(CallMutex) */

  ClangdLSPServer &Server;
};
constexpr int ClangdLSPServer::MessageHandler::MaxReplayCallbacks;

// call(), notify(), and reply() wrap the Transport, adding logging and locking.
void ClangdLSPServer::callMethod(StringRef Method, llvm::json::Value Params,
                                 Callback<llvm::json::Value> CB) {
  auto ID = MsgHandler->bindReply(std::move(CB));
  log("--> {0}({1})", Method, ID);
  std::lock_guard<std::mutex> Lock(TranspWriter);
  Transp.call(Method, std::move(Params), ID);
}

void ClangdLSPServer::notify(llvm::StringRef Method, llvm::json::Value Params) {
  log("--> {0}", Method);
  maybeCleanupMemory();
  std::lock_guard<std::mutex> Lock(TranspWriter);
  Transp.notify(Method, std::move(Params));
}

static std::vector<llvm::StringRef> semanticTokenTypes() {
  std::vector<llvm::StringRef> Types;
  for (unsigned I = 0; I <= static_cast<unsigned>(HighlightingKind::LastKind);
       ++I)
    Types.push_back(toSemanticTokenType(static_cast<HighlightingKind>(I)));
  return Types;
}

static std::vector<llvm::StringRef> semanticTokenModifiers() {
  std::vector<llvm::StringRef> Modifiers;
  for (unsigned I = 0;
       I <= static_cast<unsigned>(HighlightingModifier::LastModifier); ++I)
    Modifiers.push_back(
        toSemanticTokenModifier(static_cast<HighlightingModifier>(I)));
  return Modifiers;
}

void ClangdLSPServer::onInitialize(const InitializeParams &Params,
                                   Callback<llvm::json::Value> Reply) {
  // Determine character encoding first as it affects constructed ClangdServer.
  if (Params.capabilities.offsetEncoding && !Opts.Encoding) {
    Opts.Encoding = OffsetEncoding::UTF16; // fallback
    for (OffsetEncoding Supported : *Params.capabilities.offsetEncoding)
      if (Supported != OffsetEncoding::UnsupportedEncoding) {
        Opts.Encoding = Supported;
        break;
      }
  }

  if (Params.capabilities.TheiaSemanticHighlighting &&
      !Params.capabilities.SemanticTokens) {
    elog("Client requested legacy semanticHighlights notification, which is "
         "no longer supported. Migrate to standard semanticTokens request");
  }

  if (Params.rootUri && *Params.rootUri)
    Opts.WorkspaceRoot = std::string(Params.rootUri->file());
  else if (Params.rootPath && !Params.rootPath->empty())
    Opts.WorkspaceRoot = *Params.rootPath;
  if (Server)
    return Reply(llvm::make_error<LSPError>("server already initialized",
                                            ErrorCode::InvalidRequest));

  Opts.CodeComplete.EnableSnippets = Params.capabilities.CompletionSnippets;
  Opts.CodeComplete.IncludeFixIts = Params.capabilities.CompletionFixes;
  if (!Opts.CodeComplete.BundleOverloads)
    Opts.CodeComplete.BundleOverloads = Params.capabilities.HasSignatureHelp;
  Opts.CodeComplete.DocumentationFormat =
      Params.capabilities.CompletionDocumentationFormat;
  Opts.SignatureHelpDocumentationFormat =
      Params.capabilities.SignatureHelpDocumentationFormat;
  DiagOpts.EmbedFixesInDiagnostics = Params.capabilities.DiagnosticFixes;
  DiagOpts.SendDiagnosticCategory = Params.capabilities.DiagnosticCategory;
  DiagOpts.EmitRelatedLocations =
      Params.capabilities.DiagnosticRelatedInformation;
  if (Params.capabilities.WorkspaceSymbolKinds)
    SupportedSymbolKinds |= *Params.capabilities.WorkspaceSymbolKinds;
  if (Params.capabilities.CompletionItemKinds)
    SupportedCompletionItemKinds |= *Params.capabilities.CompletionItemKinds;
  SupportsCompletionLabelDetails = Params.capabilities.CompletionLabelDetail;
  SupportsCodeAction = Params.capabilities.CodeActionStructure;
  SupportsHierarchicalDocumentSymbol =
      Params.capabilities.HierarchicalDocumentSymbol;
  SupportsReferenceContainer = Params.capabilities.ReferenceContainer;
  SupportFileStatus = Params.initializationOptions.FileStatus;
  SupportsDocumentChanges = Params.capabilities.DocumentChanges;
  SupportsChangeAnnotation = Params.capabilities.ChangeAnnotation;
  HoverContentFormat = Params.capabilities.HoverContentFormat;
  Opts.LineFoldingOnly = Params.capabilities.LineFoldingOnly;
  SupportsOffsetsInSignatureHelp = Params.capabilities.OffsetsInSignatureHelp;
  if (Params.capabilities.WorkDoneProgress)
    BackgroundIndexProgressState = BackgroundIndexProgress::Empty;
  BackgroundIndexSkipCreate = Params.capabilities.ImplicitProgressCreation;
  Opts.ImplicitCancellation = !Params.capabilities.CancelsStaleRequests;
  Opts.PublishInactiveRegions = Params.capabilities.InactiveRegions;

  if (Opts.UseDirBasedCDB) {
    DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS);
    if (const auto &Dir = Params.initializationOptions.compilationDatabasePath)
      CDBOpts.CompileCommandsDir = Dir;
    CDBOpts.ContextProvider = Opts.ContextProvider;
    BaseCDB =
        std::make_unique<DirectoryBasedGlobalCompilationDatabase>(CDBOpts);
  }
  auto Mangler = CommandMangler::detect();
  Mangler.SystemIncludeExtractor =
      getSystemIncludeExtractor(llvm::ArrayRef(Opts.QueryDriverGlobs));
  if (Opts.ResourceDir)
    Mangler.ResourceDir = *Opts.ResourceDir;
  CDB.emplace(BaseCDB.get(), Params.initializationOptions.fallbackFlags,
              std::move(Mangler));
  {
    // Switch caller's context with LSPServer's background context. Since we
    // rather want to propagate information from LSPServer's context into the
    // Server, CDB, etc.
    WithContext MainContext(BackgroundContext.clone());
    std::optional<WithContextValue> WithOffsetEncoding;
    if (Opts.Encoding)
      WithOffsetEncoding.emplace(kCurrentOffsetEncoding, *Opts.Encoding);
    Server.emplace(*CDB, TFS, Opts,
                   static_cast<ClangdServer::Callbacks *>(this));
  }

  llvm::json::Object ServerCaps{
      {"textDocumentSync",
       llvm::json::Object{
           {"openClose", true},
           {"change", (int)TextDocumentSyncKind::Incremental},
           {"save", true},
       }},
      {"documentFormattingProvider", true},
      {"documentRangeFormattingProvider", true},
      {"documentOnTypeFormattingProvider",
       llvm::json::Object{
           {"firstTriggerCharacter", "\n"},
           {"moreTriggerCharacter", {}},
       }},
      {"completionProvider",
       llvm::json::Object{
           // We don't set `(` etc as allCommitCharacters as they interact
           // poorly with snippet results.
           // See https://github.com/clangd/vscode-clangd/issues/357
           // Hopefully we can use them one day without this side-effect:
           //     https://github.com/microsoft/vscode/issues/42544
           {"resolveProvider", false},
           // We do extra checks, e.g. that > is part of ->.
           {"triggerCharacters", {".", "<", ">", ":", "\"", "/", "*"}},
       }},
      {"semanticTokensProvider",
       llvm::json::Object{
           {"full", llvm::json::Object{{"delta", true}}},
           {"range", false},
           {"legend",
            llvm::json::Object{{"tokenTypes", semanticTokenTypes()},
                               {"tokenModifiers", semanticTokenModifiers()}}},
       }},
      {"signatureHelpProvider",
       llvm::json::Object{
           {"triggerCharacters", {"(", ")", "{", "}", "<", ">", ","}},
       }},
      {"declarationProvider", true},
      {"definitionProvider", true},
      {"implementationProvider", true},
      {"typeDefinitionProvider", true},
      {"documentHighlightProvider", true},
      {"documentLinkProvider",
       llvm::json::Object{
           {"resolveProvider", false},
       }},
      {"hoverProvider", true},
      {"selectionRangeProvider", true},
      {"documentSymbolProvider", true},
      {"workspaceSymbolProvider", true},
      {"referencesProvider", true},
      {"astProvider", true}, // clangd extension
      {"typeHierarchyProvider", true},
      // Unfortunately our extension made use of the same capability name as the
      // standard. Advertise this capability to tell clients that implement our
      // extension we really have support for the standardized one as well.
      {"standardTypeHierarchyProvider", true}, // clangd extension
      {"memoryUsageProvider", true},           // clangd extension
      {"compilationDatabase",                  // clangd extension
       llvm::json::Object{{"automaticReload", true}}},
      {"inactiveRegionsProvider", true}, // clangd extension
      {"callHierarchyProvider", true},
      {"clangdInlayHintsProvider", true},
      {"inlayHintProvider", true},
      {"foldingRangeProvider", true},
  };

  {
    LSPBinder Binder(Handlers, *this);
    bindMethods(Binder, Params.capabilities);
    if (Opts.FeatureModules)
      for (auto &Mod : *Opts.FeatureModules)
        Mod.initializeLSP(Binder, Params.rawCapabilities, ServerCaps);
  }

  // Per LSP, renameProvider can be either boolean or RenameOptions.
  // RenameOptions will be specified if the client states it supports prepare.
  ServerCaps["renameProvider"] =
      Params.capabilities.RenamePrepareSupport
          ? llvm::json::Object{{"prepareProvider", true}}
          : llvm::json::Value(true);

  // Per LSP, codeActionProvider can be either boolean or CodeActionOptions.
  // CodeActionOptions is only valid if the client supports action literal
  // via textDocument.codeAction.codeActionLiteralSupport.
  ServerCaps["codeActionProvider"] =
      Params.capabilities.CodeActionStructure
          ? llvm::json::Object{{"codeActionKinds",
                                {CodeAction::QUICKFIX_KIND,
                                 CodeAction::REFACTOR_KIND,
                                 CodeAction::INFO_KIND}}}
          : llvm::json::Value(true);

  std::vector<llvm::StringRef> Commands;
  for (llvm::StringRef Command : Handlers.CommandHandlers.keys())
    Commands.push_back(Command);
  llvm::sort(Commands);
  ServerCaps["executeCommandProvider"] =
      llvm::json::Object{{"commands", Commands}};

  llvm::json::Object Result{
      {{"serverInfo",
        llvm::json::Object{
            {"name", "clangd"},
            {"version", llvm::formatv("{0} {1} {2}", versionString(),
                                      featureString(), platformString())}}},
       {"capabilities", std::move(ServerCaps)}}};
  if (Opts.Encoding)
    Result["offsetEncoding"] = *Opts.Encoding;
  Reply(std::move(Result));

  // Apply settings after we're fully initialized.
  // This can start background indexing and in turn trigger LSP notifications.
  applyConfiguration(Params.initializationOptions.ConfigSettings);
}

void ClangdLSPServer::onInitialized(const InitializedParams &Params) {}

void ClangdLSPServer::onShutdown(const NoParams &,
                                 Callback<std::nullptr_t> Reply) {
  // Do essentially nothing, just say we're ready to exit.
  ShutdownRequestReceived = true;
  Reply(nullptr);
}

// sync is a clangd extension: it blocks until all background work completes.
// It blocks the calling thread, so no messages are processed until it returns!
void ClangdLSPServer::onSync(const NoParams &, Callback<std::nullptr_t> Reply) {
  if (Server->blockUntilIdleForTest(/*TimeoutSeconds=*/60))
    Reply(nullptr);
  else
    Reply(error("Not idle after a minute"));
}

void ClangdLSPServer::onDocumentDidOpen(
    const DidOpenTextDocumentParams &Params) {
  PathRef File = Params.textDocument.uri.file();

  const std::string &Contents = Params.textDocument.text;

  Server->addDocument(File, Contents,
                      encodeVersion(Params.textDocument.version),
                      WantDiagnostics::Yes);
}

void ClangdLSPServer::onDocumentDidChange(
    const DidChangeTextDocumentParams &Params) {
  auto WantDiags = WantDiagnostics::Auto;
  if (Params.wantDiagnostics)
    WantDiags =
        *Params.wantDiagnostics ? WantDiagnostics::Yes : WantDiagnostics::No;

  PathRef File = Params.textDocument.uri.file();
  auto Code = Server->getDraft(File);
  if (!Code) {
    log("Trying to incrementally change non-added document: {0}", File);
    return;
  }
  std::string NewCode(*Code);
  for (const auto &Change : Params.contentChanges) {
    if (auto Err = applyChange(NewCode, Change)) {
      // If this fails, we are most likely going to be not in sync anymore with
      // the client.  It is better to remove the draft and let further
      // operations fail rather than giving wrong results.
      Server->removeDocument(File);
      elog("Failed to update {0}: {1}", File, std::move(Err));
      return;
    }
  }
  Server->addDocument(File, NewCode, encodeVersion(Params.textDocument.version),
                      WantDiags, Params.forceRebuild);
}

void ClangdLSPServer::onDocumentDidSave(
    const DidSaveTextDocumentParams &Params) {
  Server->reparseOpenFilesIfNeeded([](llvm::StringRef) { return true; });
}

void ClangdLSPServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
  // We could also reparse all open files here. However:
  //  - this could be frequent, and revalidating all the preambles isn't free
  //  - this is useful e.g. when switching git branches, but we're likely to see
  //    fresh headers but still have the old-branch main-file content
  Server->onFileEvent(Params);
  // FIXME: observe config files, immediately expire time-based caches, reparse:
  //  - compile_commands.json and compile_flags.txt
  //  - .clang_format and .clang-tidy
  //  - .clangd and clangd/config.yaml
}

void ClangdLSPServer::onCommand(const ExecuteCommandParams &Params,
                                Callback<llvm::json::Value> Reply) {
  auto It = Handlers.CommandHandlers.find(Params.command);
  if (It == Handlers.CommandHandlers.end()) {
    return Reply(llvm::make_error<LSPError>(
        llvm::formatv("Unsupported command \"{0}\".", Params.command).str(),
        ErrorCode::InvalidParams));
  }
  It->second(Params.argument, std::move(Reply));
}

void ClangdLSPServer::onCommandApplyEdit(const WorkspaceEdit &WE,
                                         Callback<llvm::json::Value> Reply) {
  // The flow for "apply-fix" :
  // 1. We publish a diagnostic, including fixits
  // 2. The user clicks on the diagnostic, the editor asks us for code actions
  // 3. We send code actions, with the fixit embedded as context
  // 4. The user selects the fixit, the editor asks us to apply it
  // 5. We unwrap the changes and send them back to the editor
  // 6. The editor applies the changes (applyEdit), and sends us a reply
  // 7. We unwrap the reply and send a reply to the editor.
  applyEdit(WE, "Fix applied.", std::move(Reply));
}

void ClangdLSPServer::onCommandApplyTweak(const TweakArgs &Args,
                                          Callback<llvm::json::Value> Reply) {
  auto Action = [this, Reply = std::move(Reply)](
                    llvm::Expected<Tweak::Effect> R) mutable {
    if (!R)
      return Reply(R.takeError());

    assert(R->ShowMessage || (!R->ApplyEdits.empty() && "tweak has no effect"));

    if (R->ShowMessage) {
      ShowMessageParams Msg;
      Msg.message = *R->ShowMessage;
      Msg.type = MessageType::Info;
      ShowMessage(Msg);
    }
    // When no edit is specified, make sure we Reply().
    if (R->ApplyEdits.empty())
      return Reply("Tweak applied.");

    if (auto Err = validateEdits(*Server, R->ApplyEdits))
      return Reply(std::move(Err));

    WorkspaceEdit WE;
    // FIXME: use documentChanges when SupportDocumentChanges is true.
    WE.changes.emplace();
    for (const auto &It : R->ApplyEdits) {
      (*WE.changes)[URI::createFile(It.first()).toString()] =
          It.second.asTextEdits();
    }
    // ApplyEdit will take care of calling Reply().
    return applyEdit(std::move(WE), "Tweak applied.", std::move(Reply));
  };
  Server->applyTweak(Args.file.file(), Args.selection, Args.tweakID,
                     std::move(Action));
}

void ClangdLSPServer::onCommandApplyRename(const RenameParams &R,
                                           Callback<llvm::json::Value> Reply) {
  onRename(R, [this, Reply = std::move(Reply)](
                  llvm::Expected<WorkspaceEdit> Edit) mutable {
    if (!Edit)
      Reply(Edit.takeError());
    applyEdit(std::move(*Edit), "Rename applied.", std::move(Reply));
  });
}

void ClangdLSPServer::applyEdit(WorkspaceEdit WE, llvm::json::Value Success,
                                Callback<llvm::json::Value> Reply) {
  ApplyWorkspaceEditParams Edit;
  Edit.edit = std::move(WE);
  ApplyWorkspaceEdit(
      Edit, [Reply = std::move(Reply), SuccessMessage = std::move(Success)](
                llvm::Expected<ApplyWorkspaceEditResponse> Response) mutable {
        if (!Response)
          return Reply(Response.takeError());
        if (!Response->applied) {
          std::string Reason = Response->failureReason
                                   ? *Response->failureReason
                                   : "unknown reason";
          return Reply(error("edits were not applied: {0}", Reason));
        }
        return Reply(SuccessMessage);
      });
}

void ClangdLSPServer::onWorkspaceSymbol(
    const WorkspaceSymbolParams &Params,
    Callback<std::vector<SymbolInformation>> Reply) {
  Server->workspaceSymbols(
      Params.query, Params.limit.value_or(Opts.CodeComplete.Limit),
      [Reply = std::move(Reply),
       this](llvm::Expected<std::vector<SymbolInformation>> Items) mutable {
        if (!Items)
          return Reply(Items.takeError());
        for (auto &Sym : *Items)
          Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);

        Reply(std::move(*Items));
      });
}

void ClangdLSPServer::onPrepareRename(const TextDocumentPositionParams &Params,
                                      Callback<PrepareRenameResult> Reply) {
  Server->prepareRename(
      Params.textDocument.uri.file(), Params.position, /*NewName*/ std::nullopt,
      Opts.Rename,
      [Reply = std::move(Reply)](llvm::Expected<RenameResult> Result) mutable {
        if (!Result)
          return Reply(Result.takeError());
        PrepareRenameResult PrepareResult;
        PrepareResult.range = Result->Target;
        PrepareResult.placeholder = Result->Placeholder;
        return Reply(std::move(PrepareResult));
      });
}

void ClangdLSPServer::onRename(const RenameParams &Params,
                               Callback<WorkspaceEdit> Reply) {
  Path File = std::string(Params.textDocument.uri.file());
  if (!Server->getDraft(File))
    return Reply(llvm::make_error<LSPError>(
        "onRename called for non-added file", ErrorCode::InvalidParams));
  Server->rename(File, Params.position, Params.newName, Opts.Rename,
                 [File, Params, Reply = std::move(Reply),
                  this](llvm::Expected<RenameResult> R) mutable {
                   if (!R)
                     return Reply(R.takeError());
                   if (auto Err = validateEdits(*Server, R->GlobalChanges))
                     return Reply(std::move(Err));
                   WorkspaceEdit Result;
                   // FIXME: use documentChanges if SupportDocumentChanges is
                   // true.
                   Result.changes.emplace();
                   for (const auto &Rep : R->GlobalChanges) {
                     (*Result
                           .changes)[URI::createFile(Rep.first()).toString()] =
                         Rep.second.asTextEdits();
                   }
                   Reply(Result);
                 });
}

void ClangdLSPServer::onDocumentDidClose(
    const DidCloseTextDocumentParams &Params) {
  PathRef File = Params.textDocument.uri.file();
  Server->removeDocument(File);

  {
    std::lock_guard<std::mutex> Lock(DiagRefMutex);
    DiagRefMap.erase(File);
  }
  {
    std::lock_guard<std::mutex> HLock(SemanticTokensMutex);
    LastSemanticTokens.erase(File);
  }
  // clangd will not send updates for this file anymore, so we empty out the
  // list of diagnostics shown on the client (e.g. in the "Problems" pane of
  // VSCode). Note that this cannot race with actual diagnostics responses
  // because removeDocument() guarantees no diagnostic callbacks will be
  // executed after it returns.
  PublishDiagnosticsParams Notification;
  Notification.uri = URIForFile::canonicalize(File, /*TUPath=*/File);
  PublishDiagnostics(Notification);
}

void ClangdLSPServer::onDocumentOnTypeFormatting(
    const DocumentOnTypeFormattingParams &Params,
    Callback<std::vector<TextEdit>> Reply) {
  auto File = Params.textDocument.uri.file();
  Server->formatOnType(File, Params.position, Params.ch, std::move(Reply));
}

void ClangdLSPServer::onDocumentRangeFormatting(
    const DocumentRangeFormattingParams &Params,
    Callback<std::vector<TextEdit>> Reply) {
  auto File = Params.textDocument.uri.file();
  auto Code = Server->getDraft(File);
  Server->formatFile(File, Params.range,
                     [Code = std::move(Code), Reply = std::move(Reply)](
                         llvm::Expected<tooling::Replacements> Result) mutable {
                       if (Result)
                         Reply(replacementsToEdits(*Code, Result.get()));
                       else
                         Reply(Result.takeError());
                     });
}

void ClangdLSPServer::onDocumentFormatting(
    const DocumentFormattingParams &Params,
    Callback<std::vector<TextEdit>> Reply) {
  auto File = Params.textDocument.uri.file();
  auto Code = Server->getDraft(File);
  Server->formatFile(File,
                     /*Rng=*/std::nullopt,
                     [Code = std::move(Code), Reply = std::move(Reply)](
                         llvm::Expected<tooling::Replacements> Result) mutable {
                       if (Result)
                         Reply(replacementsToEdits(*Code, Result.get()));
                       else
                         Reply(Result.takeError());
                     });
}

/// The functions constructs a flattened view of the DocumentSymbol hierarchy.
/// Used by the clients that do not support the hierarchical view.
static std::vector<SymbolInformation>
flattenSymbolHierarchy(llvm::ArrayRef<DocumentSymbol> Symbols,
                       const URIForFile &FileURI) {
  std::vector<SymbolInformation> Results;
  std::function<void(const DocumentSymbol &, llvm::StringRef)> Process =
      [&](const DocumentSymbol &S, std::optional<llvm::StringRef> ParentName) {
        SymbolInformation SI;
        SI.containerName = std::string(ParentName ? "" : *ParentName);
        SI.name = S.name;
        SI.kind = S.kind;
        SI.location.range = S.range;
        SI.location.uri = FileURI;

        Results.push_back(std::move(SI));
        std::string FullName =
            !ParentName ? S.name : (ParentName->str() + "::" + S.name);
        for (auto &C : S.children)
          Process(C, /*ParentName=*/FullName);
      };
  for (auto &S : Symbols)
    Process(S, /*ParentName=*/"");
  return Results;
}

void ClangdLSPServer::onDocumentSymbol(const DocumentSymbolParams &Params,
                                       Callback<llvm::json::Value> Reply) {
  URIForFile FileURI = Params.textDocument.uri;
  Server->documentSymbols(
      Params.textDocument.uri.file(),
      [this, FileURI, Reply = std::move(Reply)](
          llvm::Expected<std::vector<DocumentSymbol>> Items) mutable {
        if (!Items)
          return Reply(Items.takeError());
        adjustSymbolKinds(*Items, SupportedSymbolKinds);
        if (SupportsHierarchicalDocumentSymbol)
          return Reply(std::move(*Items));
        return Reply(flattenSymbolHierarchy(*Items, FileURI));
      });
}

void ClangdLSPServer::onFoldingRange(
    const FoldingRangeParams &Params,
    Callback<std::vector<FoldingRange>> Reply) {
  Server->foldingRanges(Params.textDocument.uri.file(), std::move(Reply));
}

static std::optional<Command> asCommand(const CodeAction &Action) {
  Command Cmd;
  if (Action.command && Action.edit)
    return std::nullopt; // Not representable. (We never emit these anyway).
  if (Action.command) {
    Cmd = *Action.command;
  } else if (Action.edit) {
    Cmd.command = std::string(ApplyFixCommand);
    Cmd.argument = *Action.edit;
  } else {
    return std::nullopt;
  }
  Cmd.title = Action.title;
  if (Action.kind && *Action.kind == CodeAction::QUICKFIX_KIND)
    Cmd.title = "Apply fix: " + Cmd.title;
  return Cmd;
}

void ClangdLSPServer::onCodeAction(const CodeActionParams &Params,
                                   Callback<llvm::json::Value> Reply) {
  URIForFile File = Params.textDocument.uri;
  std::map<ClangdServer::DiagRef, clangd::Diagnostic> ToLSPDiags;
  ClangdServer::CodeActionInputs Inputs;

  for (const auto& LSPDiag : Params.context.diagnostics) {
    if (auto DiagRef = getDiagRef(File.file(), LSPDiag)) {
      ToLSPDiags[*DiagRef] = LSPDiag;
      Inputs.Diagnostics.push_back(*DiagRef);
    }
  }
  Inputs.File = File.file();
  Inputs.Selection = Params.range;
  Inputs.RequestedActionKinds = Params.context.only;
  Inputs.TweakFilter = [this](const Tweak &T) {
    return Opts.TweakFilter(T);
  };
  auto CB = [this,
             Reply = std::move(Reply),
             ToLSPDiags = std::move(ToLSPDiags), File,
             Selection = Params.range](
                llvm::Expected<ClangdServer::CodeActionResult> Fixits) mutable {
    if (!Fixits)
      return Reply(Fixits.takeError());
    std::vector<CodeAction> CAs;
    auto Version = decodeVersion(Fixits->Version);
    for (const auto &QF : Fixits->QuickFixes) {
      CAs.push_back(toCodeAction(QF.F, File, Version, SupportsDocumentChanges,
                                 SupportsChangeAnnotation));
      if (auto It = ToLSPDiags.find(QF.Diag);
          It != ToLSPDiags.end()) {
        CAs.back().diagnostics = {It->second};
      }
    }

    for (const auto &R : Fixits->Renames)
      CAs.push_back(toCodeAction(R, File));

    for (const auto &TR : Fixits->TweakRefs)
      CAs.push_back(toCodeAction(TR, File, Selection));

    // If there's exactly one quick-fix, call it "preferred".
    // We never consider refactorings etc as preferred.
    CodeAction *OnlyFix = nullptr;
    for (auto &Action : CAs) {
      if (Action.kind && *Action.kind == CodeAction::QUICKFIX_KIND) {
        if (OnlyFix) {
          OnlyFix = nullptr;
          break;
        }
        OnlyFix = &Action;
      }
    }
    if (OnlyFix) {
      OnlyFix->isPreferred = true;
      if (ToLSPDiags.size() == 1 &&
          ToLSPDiags.begin()->second.range == Selection)
        OnlyFix->diagnostics = {ToLSPDiags.begin()->second};
    }

    if (SupportsCodeAction)
      return Reply(llvm::json::Array(CAs));
    std::vector<Command> Commands;
    for (const auto &Action : CAs) {
      if (auto Command = asCommand(Action))
        Commands.push_back(std::move(*Command));
    }
    return Reply(llvm::json::Array(Commands));
  };
  Server->codeAction(Inputs, std::move(CB));
}

void ClangdLSPServer::onCompletion(const CompletionParams &Params,
                                   Callback<CompletionList> Reply) {
  if (!shouldRunCompletion(Params)) {
    // Clients sometimes auto-trigger completions in undesired places (e.g.
    // 'a >^ '), we return empty results in those cases.
    vlog("ignored auto-triggered completion, preceding char did not match");
    return Reply(CompletionList());
  }
  auto Opts = this->Opts.CodeComplete;
  if (Params.limit && *Params.limit >= 0)
    Opts.Limit = *Params.limit;
  Server->codeComplete(Params.textDocument.uri.file(), Params.position, Opts,
                       [Reply = std::move(Reply), Opts,
                        this](llvm::Expected<CodeCompleteResult> List) mutable {
                         if (!List)
                           return Reply(List.takeError());
                         CompletionList LSPList;
                         LSPList.isIncomplete = List->HasMore;
                         for (const auto &R : List->Completions) {
                           CompletionItem C = R.render(Opts);
                           C.kind = adjustKindToCapability(
                               C.kind, SupportedCompletionItemKinds);
                           if (!SupportsCompletionLabelDetails)
                             removeCompletionLabelDetails(C);
                           LSPList.items.push_back(std::move(C));
                         }
                         return Reply(std::move(LSPList));
                       });
}

void ClangdLSPServer::onSignatureHelp(const TextDocumentPositionParams &Params,
                                      Callback<SignatureHelp> Reply) {
  Server->signatureHelp(Params.textDocument.uri.file(), Params.position,
                        Opts.SignatureHelpDocumentationFormat,
                        [Reply = std::move(Reply), this](
                            llvm::Expected<SignatureHelp> Signature) mutable {
                          if (!Signature)
                            return Reply(Signature.takeError());
                          if (SupportsOffsetsInSignatureHelp)
                            return Reply(std::move(*Signature));
                          // Strip out the offsets from signature help for
                          // clients that only support string labels.
                          for (auto &SigInfo : Signature->signatures) {
                            for (auto &Param : SigInfo.parameters)
                              Param.labelOffsets.reset();
                          }
                          return Reply(std::move(*Signature));
                        });
}

// Go to definition has a toggle function: if def and decl are distinct, then
// the first press gives you the def, the second gives you the matching def.
// getToggle() returns the counterpart location that under the cursor.
//
// We return the toggled location alone (ignoring other symbols) to encourage
// editors to "bounce" quickly between locations, without showing a menu.
static Location *getToggle(const TextDocumentPositionParams &Point,
                           LocatedSymbol &Sym) {
  // Toggle only makes sense with two distinct locations.
  if (!Sym.Definition || *Sym.Definition == Sym.PreferredDeclaration)
    return nullptr;
  if (Sym.Definition->uri.file() == Point.textDocument.uri.file() &&
      Sym.Definition->range.contains(Point.position))
    return &Sym.PreferredDeclaration;
  if (Sym.PreferredDeclaration.uri.file() == Point.textDocument.uri.file() &&
      Sym.PreferredDeclaration.range.contains(Point.position))
    return &*Sym.Definition;
  return nullptr;
}

void ClangdLSPServer::onGoToDefinition(const TextDocumentPositionParams &Params,
                                       Callback<std::vector<Location>> Reply) {
  Server->locateSymbolAt(
      Params.textDocument.uri.file(), Params.position,
      [Params, Reply = std::move(Reply)](
          llvm::Expected<std::vector<LocatedSymbol>> Symbols) mutable {
        if (!Symbols)
          return Reply(Symbols.takeError());
        std::vector<Location> Defs;
        for (auto &S : *Symbols) {
          if (Location *Toggle = getToggle(Params, S))
            return Reply(std::vector<Location>{std::move(*Toggle)});
          Defs.push_back(S.Definition.value_or(S.PreferredDeclaration));
        }
        Reply(std::move(Defs));
      });
}

void ClangdLSPServer::onGoToDeclaration(
    const TextDocumentPositionParams &Params,
    Callback<std::vector<Location>> Reply) {
  Server->locateSymbolAt(
      Params.textDocument.uri.file(), Params.position,
      [Params, Reply = std::move(Reply)](
          llvm::Expected<std::vector<LocatedSymbol>> Symbols) mutable {
        if (!Symbols)
          return Reply(Symbols.takeError());
        std::vector<Location> Decls;
        for (auto &S : *Symbols) {
          if (Location *Toggle = getToggle(Params, S))
            return Reply(std::vector<Location>{std::move(*Toggle)});
          Decls.push_back(std::move(S.PreferredDeclaration));
        }
        Reply(std::move(Decls));
      });
}

void ClangdLSPServer::onSwitchSourceHeader(
    const TextDocumentIdentifier &Params,
    Callback<std::optional<URIForFile>> Reply) {
  Server->switchSourceHeader(
      Params.uri.file(),
      [Reply = std::move(Reply),
       Params](llvm::Expected<std::optional<clangd::Path>> Path) mutable {
        if (!Path)
          return Reply(Path.takeError());
        if (*Path)
          return Reply(URIForFile::canonicalize(**Path, Params.uri.file()));
        return Reply(std::nullopt);
      });
}

void ClangdLSPServer::onDocumentHighlight(
    const TextDocumentPositionParams &Params,
    Callback<std::vector<DocumentHighlight>> Reply) {
  Server->findDocumentHighlights(Params.textDocument.uri.file(),
                                 Params.position, std::move(Reply));
}

void ClangdLSPServer::onHover(const TextDocumentPositionParams &Params,
                              Callback<std::optional<Hover>> Reply) {
  Server->findHover(Params.textDocument.uri.file(), Params.position,
                    [Reply = std::move(Reply),
                     this](llvm::Expected<std::optional<HoverInfo>> H) mutable {
                      if (!H)
                        return Reply(H.takeError());
                      if (!*H)
                        return Reply(std::nullopt);

                      Hover R;
                      R.contents.kind = HoverContentFormat;
                      R.range = (*H)->SymRange;
                      switch (HoverContentFormat) {
                      case MarkupKind::PlainText:
                        R.contents.value = (*H)->present().asPlainText();
                        return Reply(std::move(R));
                      case MarkupKind::Markdown:
                        R.contents.value = (*H)->present().asMarkdown();
                        return Reply(std::move(R));
                      };
                      llvm_unreachable("unhandled MarkupKind");
                    });
}

// Our extension has a different representation on the wire than the standard.
// https://clangd.llvm.org/extensions#type-hierarchy
llvm::json::Value serializeTHIForExtension(TypeHierarchyItem THI) {
  llvm::json::Object Result{{
      {"name", std::move(THI.name)},
      {"kind", static_cast<int>(THI.kind)},
      {"uri", std::move(THI.uri)},
      {"range", THI.range},
      {"selectionRange", THI.selectionRange},
      {"data", std::move(THI.data)},
  }};
  if (THI.deprecated)
    Result["deprecated"] = THI.deprecated;
  if (THI.detail)
    Result["detail"] = std::move(*THI.detail);

  if (THI.parents) {
    llvm::json::Array Parents;
    for (auto &Parent : *THI.parents)
      Parents.emplace_back(serializeTHIForExtension(std::move(Parent)));
    Result["parents"] = std::move(Parents);
  }

  if (THI.children) {
    llvm::json::Array Children;
    for (auto &child : *THI.children)
      Children.emplace_back(serializeTHIForExtension(std::move(child)));
    Result["children"] = std::move(Children);
  }
  return Result;
}

void ClangdLSPServer::onTypeHierarchy(const TypeHierarchyPrepareParams &Params,
                                      Callback<llvm::json::Value> Reply) {
  auto Serialize =
      [Reply = std::move(Reply)](
          llvm::Expected<std::vector<TypeHierarchyItem>> Resp) mutable {
        if (!Resp) {
          Reply(Resp.takeError());
          return;
        }
        if (Resp->empty()) {
          Reply(nullptr);
          return;
        }
        Reply(serializeTHIForExtension(std::move(Resp->front())));
      };
  Server->typeHierarchy(Params.textDocument.uri.file(), Params.position,
                        Params.resolve, Params.direction, std::move(Serialize));
}

void ClangdLSPServer::onResolveTypeHierarchy(
    const ResolveTypeHierarchyItemParams &Params,
    Callback<llvm::json::Value> Reply) {
  auto Serialize =
      [Reply = std::move(Reply)](
          llvm::Expected<std::optional<TypeHierarchyItem>> Resp) mutable {
        if (!Resp) {
          Reply(Resp.takeError());
          return;
        }
        if (!*Resp) {
          Reply(std::move(*Resp));
          return;
        }
        Reply(serializeTHIForExtension(std::move(**Resp)));
      };
  Server->resolveTypeHierarchy(Params.item, Params.resolve, Params.direction,
                               std::move(Serialize));
}

void ClangdLSPServer::onPrepareTypeHierarchy(
    const TypeHierarchyPrepareParams &Params,
    Callback<std::vector<TypeHierarchyItem>> Reply) {
  Server->typeHierarchy(Params.textDocument.uri.file(), Params.position,
                        Params.resolve, Params.direction, std::move(Reply));
}

void ClangdLSPServer::onSuperTypes(
    const ResolveTypeHierarchyItemParams &Params,
    Callback<std::optional<std::vector<TypeHierarchyItem>>> Reply) {
  Server->superTypes(Params.item, std::move(Reply));
}

void ClangdLSPServer::onSubTypes(
    const ResolveTypeHierarchyItemParams &Params,
    Callback<std::vector<TypeHierarchyItem>> Reply) {
  Server->subTypes(Params.item, std::move(Reply));
}

void ClangdLSPServer::onPrepareCallHierarchy(
    const CallHierarchyPrepareParams &Params,
    Callback<std::vector<CallHierarchyItem>> Reply) {
  Server->prepareCallHierarchy(Params.textDocument.uri.file(), Params.position,
                               std::move(Reply));
}

void ClangdLSPServer::onCallHierarchyIncomingCalls(
    const CallHierarchyIncomingCallsParams &Params,
    Callback<std::vector<CallHierarchyIncomingCall>> Reply) {
  Server->incomingCalls(Params.item, std::move(Reply));
}

void ClangdLSPServer::onClangdInlayHints(const InlayHintsParams &Params,
                                         Callback<llvm::json::Value> Reply) {
  // Our extension has a different representation on the wire than the standard.
  // We have a "range" property and "kind" is represented as a string, not as an
  // enum value.
  // https://clangd.llvm.org/extensions#inlay-hints
  auto Serialize = [Reply = std::move(Reply)](
                       llvm::Expected<std::vector<InlayHint>> Hints) mutable {
    if (!Hints) {
      Reply(Hints.takeError());
      return;
    }
    llvm::json::Array Result;
    Result.reserve(Hints->size());
    for (auto &Hint : *Hints) {
      Result.emplace_back(llvm::json::Object{
          {"kind", llvm::to_string(Hint.kind)},
          {"range", Hint.range},
          {"position", Hint.position},
          // Extension doesn't have paddingLeft/Right so adjust the label
          // accordingly.
          {"label",
           ((Hint.paddingLeft ? " " : "") + llvm::StringRef(Hint.joinLabels()) +
            (Hint.paddingRight ? " " : ""))
               .str()},
      });
    }
    Reply(std::move(Result));
  };
  Server->inlayHints(Params.textDocument.uri.file(), Params.range,
                     std::move(Serialize));
}

void ClangdLSPServer::onInlayHint(const InlayHintsParams &Params,
                                  Callback<std::vector<InlayHint>> Reply) {
  Server->inlayHints(Params.textDocument.uri.file(), Params.range,
                     std::move(Reply));
}

void ClangdLSPServer::applyConfiguration(
    const ConfigurationSettings &Settings) {
  // Per-file update to the compilation database.
  llvm::StringSet<> ModifiedFiles;
  for (auto &Entry : Settings.compilationDatabaseChanges) {
    PathRef File = Entry.first;
    auto Old = CDB->getCompileCommand(File);
    auto New =
        tooling::CompileCommand(std::move(Entry.second.workingDirectory), File,
                                std::move(Entry.second.compilationCommand),
                                /*Output=*/"");
    if (Old != New) {
      CDB->setCompileCommand(File, std::move(New));
      ModifiedFiles.insert(File);
    }
  }

  Server->reparseOpenFilesIfNeeded(
      [&](llvm::StringRef File) { return ModifiedFiles.count(File) != 0; });
}

void ClangdLSPServer::maybeExportMemoryProfile() {
  if (!trace::enabled() || !ShouldProfile())
    return;

  static constexpr trace::Metric MemoryUsage(
      "memory_usage", trace::Metric::Value, "component_name");
  trace::Span Tracer("ProfileBrief");
  MemoryTree MT;
  profile(MT);
  record(MT, "clangd_lsp_server", MemoryUsage);
}

void ClangdLSPServer::maybeCleanupMemory() {
  if (!Opts.MemoryCleanup || !ShouldCleanupMemory())
    return;
  Opts.MemoryCleanup();
}

// FIXME: This function needs to be properly tested.
void ClangdLSPServer::onChangeConfiguration(
    const DidChangeConfigurationParams &Params) {
  applyConfiguration(Params.settings);
}

void ClangdLSPServer::onReference(
    const ReferenceParams &Params,
    Callback<std::vector<ReferenceLocation>> Reply) {
  Server->findReferences(Params.textDocument.uri.file(), Params.position,
                         Opts.ReferencesLimit, SupportsReferenceContainer,
                         [Reply = std::move(Reply),
                          IncludeDecl(Params.context.includeDeclaration)](
                             llvm::Expected<ReferencesResult> Refs) mutable {
                           if (!Refs)
                             return Reply(Refs.takeError());
                           // Filter out declarations if the client asked.
                           std::vector<ReferenceLocation> Result;
                           Result.reserve(Refs->References.size());
                           for (auto &Ref : Refs->References) {
                             bool IsDecl =
                                 Ref.Attributes & ReferencesResult::Declaration;
                             if (IncludeDecl || !IsDecl)
                               Result.push_back(std::move(Ref.Loc));
                           }
                           return Reply(std::move(Result));
                         });
}

void ClangdLSPServer::onGoToType(const TextDocumentPositionParams &Params,
                                 Callback<std::vector<Location>> Reply) {
  Server->findType(
      Params.textDocument.uri.file(), Params.position,
      [Reply = std::move(Reply)](
          llvm::Expected<std::vector<LocatedSymbol>> Types) mutable {
        if (!Types)
          return Reply(Types.takeError());
        std::vector<Location> Response;
        for (const LocatedSymbol &Sym : *Types)
          Response.push_back(Sym.Definition.value_or(Sym.PreferredDeclaration));
        return Reply(std::move(Response));
      });
}

void ClangdLSPServer::onGoToImplementation(
    const TextDocumentPositionParams &Params,
    Callback<std::vector<Location>> Reply) {
  Server->findImplementations(
      Params.textDocument.uri.file(), Params.position,
      [Reply = std::move(Reply)](
          llvm::Expected<std::vector<LocatedSymbol>> Overrides) mutable {
        if (!Overrides)
          return Reply(Overrides.takeError());
        std::vector<Location> Impls;
        for (const LocatedSymbol &Sym : *Overrides)
          Impls.push_back(Sym.Definition.value_or(Sym.PreferredDeclaration));
        return Reply(std::move(Impls));
      });
}

void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
                                   Callback<std::vector<SymbolDetails>> Reply) {
  Server->symbolInfo(Params.textDocument.uri.file(), Params.position,
                     std::move(Reply));
}

void ClangdLSPServer::onSelectionRange(
    const SelectionRangeParams &Params,
    Callback<std::vector<SelectionRange>> Reply) {
  Server->semanticRanges(
      Params.textDocument.uri.file(), Params.positions,
      [Reply = std::move(Reply)](
          llvm::Expected<std::vector<SelectionRange>> Ranges) mutable {
        if (!Ranges)
          return Reply(Ranges.takeError());
        return Reply(std::move(*Ranges));
      });
}

void ClangdLSPServer::onDocumentLink(
    const DocumentLinkParams &Params,
    Callback<std::vector<DocumentLink>> Reply) {

  // TODO(forster): This currently resolves all targets eagerly. This is slow,
  // because it blocks on the preamble/AST being built. We could respond to the
  // request faster by using string matching or the lexer to find the includes
  // and resolving the targets lazily.
  Server->documentLinks(
      Params.textDocument.uri.file(),
      [Reply = std::move(Reply)](
          llvm::Expected<std::vector<DocumentLink>> Links) mutable {
        if (!Links) {
          return Reply(Links.takeError());
        }
        return Reply(std::move(Links));
      });
}

// Increment a numeric string: "" -> 1 -> 2 -> ... -> 9 -> 10 -> 11 ...
static void increment(std::string &S) {
  for (char &C : llvm::reverse(S)) {
    if (C != '9') {
      ++C;
      return;
    }
    C = '0';
  }
  S.insert(S.begin(), '1');
}

void ClangdLSPServer::onSemanticTokens(const SemanticTokensParams &Params,
                                       Callback<SemanticTokens> CB) {
  auto File = Params.textDocument.uri.file();
  Server->semanticHighlights(
      Params.textDocument.uri.file(),
      [this, File(File.str()), CB(std::move(CB)), Code(Server->getDraft(File))](
          llvm::Expected<std::vector<HighlightingToken>> HT) mutable {
        if (!HT)
          return CB(HT.takeError());
        SemanticTokens Result;
        Result.tokens = toSemanticTokens(*HT, *Code);
        {
          std::lock_guard<std::mutex> Lock(SemanticTokensMutex);
          auto &Last = LastSemanticTokens[File];

          Last.tokens = Result.tokens;
          increment(Last.resultId);
          Result.resultId = Last.resultId;
        }
        CB(std::move(Result));
      });
}

void ClangdLSPServer::onSemanticTokensDelta(
    const SemanticTokensDeltaParams &Params,
    Callback<SemanticTokensOrDelta> CB) {
  auto File = Params.textDocument.uri.file();
  Server->semanticHighlights(
      Params.textDocument.uri.file(),
      [this, PrevResultID(Params.previousResultId), File(File.str()),
       CB(std::move(CB)), Code(Server->getDraft(File))](
          llvm::Expected<std::vector<HighlightingToken>> HT) mutable {
        if (!HT)
          return CB(HT.takeError());
        std::vector<SemanticToken> Toks = toSemanticTokens(*HT, *Code);

        SemanticTokensOrDelta Result;
        {
          std::lock_guard<std::mutex> Lock(SemanticTokensMutex);
          auto &Last = LastSemanticTokens[File];

          if (PrevResultID == Last.resultId) {
            Result.edits = diffTokens(Last.tokens, Toks);
          } else {
            vlog("semanticTokens/full/delta: wanted edits vs {0} but last "
                 "result had ID {1}. Returning full token list.",
                 PrevResultID, Last.resultId);
            Result.tokens = Toks;
          }

          Last.tokens = std::move(Toks);
          increment(Last.resultId);
          Result.resultId = Last.resultId;
        }

        CB(std::move(Result));
      });
}

void ClangdLSPServer::onMemoryUsage(const NoParams &,
                                    Callback<MemoryTree> Reply) {
  llvm::BumpPtrAllocator DetailAlloc;
  MemoryTree MT(&DetailAlloc);
  profile(MT);
  Reply(std::move(MT));
}

void ClangdLSPServer::onAST(const ASTParams &Params,
                            Callback<std::optional<ASTNode>> CB) {
  Server->getAST(Params.textDocument.uri.file(), Params.range, std::move(CB));
}

ClangdLSPServer::ClangdLSPServer(Transport &Transp, const ThreadsafeFS &TFS,
                                 const ClangdLSPServer::Options &Opts)
    : ShouldProfile(/*Period=*/std::chrono::minutes(5),
                    /*Delay=*/std::chrono::minutes(1)),
      ShouldCleanupMemory(/*Period=*/std::chrono::minutes(1),
                          /*Delay=*/std::chrono::minutes(1)),
      BackgroundContext(Context::current().clone()), Transp(Transp),
      MsgHandler(new MessageHandler(*this)), TFS(TFS),
      SupportedSymbolKinds(defaultSymbolKinds()),
      SupportedCompletionItemKinds(defaultCompletionItemKinds()), Opts(Opts) {
  if (Opts.ConfigProvider) {
    assert(!Opts.ContextProvider &&
           "Only one of ConfigProvider and ContextProvider allowed!");
    this->Opts.ContextProvider = ClangdServer::createConfiguredContextProvider(
        Opts.ConfigProvider, this);
  }
  LSPBinder Bind(this->Handlers, *this);
  Bind.method("initialize", this, &ClangdLSPServer::onInitialize);
}

void ClangdLSPServer::bindMethods(LSPBinder &Bind,
                                  const ClientCapabilities &Caps) {
  // clang-format off
  Bind.notification("initialized", this, &ClangdLSPServer::onInitialized);
  Bind.method("shutdown", this, &ClangdLSPServer::onShutdown);
  Bind.method("sync", this, &ClangdLSPServer::onSync);
  Bind.method("textDocument/rangeFormatting", this, &ClangdLSPServer::onDocumentRangeFormatting);
  Bind.method("textDocument/onTypeFormatting", this, &ClangdLSPServer::onDocumentOnTypeFormatting);
  Bind.method("textDocument/formatting", this, &ClangdLSPServer::onDocumentFormatting);
  Bind.method("textDocument/codeAction", this, &ClangdLSPServer::onCodeAction);
  Bind.method("textDocument/completion", this, &ClangdLSPServer::onCompletion);
  Bind.method("textDocument/signatureHelp", this, &ClangdLSPServer::onSignatureHelp);
  Bind.method("textDocument/definition", this, &ClangdLSPServer::onGoToDefinition);
  Bind.method("textDocument/declaration", this, &ClangdLSPServer::onGoToDeclaration);
  Bind.method("textDocument/typeDefinition", this, &ClangdLSPServer::onGoToType);
  Bind.method("textDocument/implementation", this, &ClangdLSPServer::onGoToImplementation);
  Bind.method("textDocument/references", this, &ClangdLSPServer::onReference);
  Bind.method("textDocument/switchSourceHeader", this, &ClangdLSPServer::onSwitchSourceHeader);
  Bind.method("textDocument/prepareRename", this, &ClangdLSPServer::onPrepareRename);
  Bind.method("textDocument/rename", this, &ClangdLSPServer::onRename);
  Bind.method("textDocument/hover", this, &ClangdLSPServer::onHover);
  Bind.method("textDocument/documentSymbol", this, &ClangdLSPServer::onDocumentSymbol);
  Bind.method("workspace/executeCommand", this, &ClangdLSPServer::onCommand);
  Bind.method("textDocument/documentHighlight", this, &ClangdLSPServer::onDocumentHighlight);
  Bind.method("workspace/symbol", this, &ClangdLSPServer::onWorkspaceSymbol);
  Bind.method("textDocument/ast", this, &ClangdLSPServer::onAST);
  Bind.notification("textDocument/didOpen", this, &ClangdLSPServer::onDocumentDidOpen);
  Bind.notification("textDocument/didClose", this, &ClangdLSPServer::onDocumentDidClose);
  Bind.notification("textDocument/didChange", this, &ClangdLSPServer::onDocumentDidChange);
  Bind.notification("textDocument/didSave", this, &ClangdLSPServer::onDocumentDidSave);
  Bind.notification("workspace/didChangeWatchedFiles", this, &ClangdLSPServer::onFileEvent);
  Bind.notification("workspace/didChangeConfiguration", this, &ClangdLSPServer::onChangeConfiguration);
  Bind.method("textDocument/symbolInfo", this, &ClangdLSPServer::onSymbolInfo);
  Bind.method("textDocument/typeHierarchy", this, &ClangdLSPServer::onTypeHierarchy);
  Bind.method("typeHierarchy/resolve", this, &ClangdLSPServer::onResolveTypeHierarchy);
  Bind.method("textDocument/prepareTypeHierarchy", this, &ClangdLSPServer::onPrepareTypeHierarchy);
  Bind.method("typeHierarchy/supertypes", this, &ClangdLSPServer::onSuperTypes);
  Bind.method("typeHierarchy/subtypes", this, &ClangdLSPServer::onSubTypes);
  Bind.method("textDocument/prepareCallHierarchy", this, &ClangdLSPServer::onPrepareCallHierarchy);
  Bind.method("callHierarchy/incomingCalls", this, &ClangdLSPServer::onCallHierarchyIncomingCalls);
  Bind.method("textDocument/selectionRange", this, &ClangdLSPServer::onSelectionRange);
  Bind.method("textDocument/documentLink", this, &ClangdLSPServer::onDocumentLink);
  Bind.method("textDocument/semanticTokens/full", this, &ClangdLSPServer::onSemanticTokens);
  Bind.method("textDocument/semanticTokens/full/delta", this, &ClangdLSPServer::onSemanticTokensDelta);
  Bind.method("clangd/inlayHints", this, &ClangdLSPServer::onClangdInlayHints);
  Bind.method("textDocument/inlayHint", this, &ClangdLSPServer::onInlayHint);
  Bind.method("$/memoryUsage", this, &ClangdLSPServer::onMemoryUsage);
  Bind.method("textDocument/foldingRange", this, &ClangdLSPServer::onFoldingRange);
  Bind.command(ApplyFixCommand, this, &ClangdLSPServer::onCommandApplyEdit);
  Bind.command(ApplyTweakCommand, this, &ClangdLSPServer::onCommandApplyTweak);
  Bind.command(ApplyRenameCommand, this, &ClangdLSPServer::onCommandApplyRename);

  ApplyWorkspaceEdit = Bind.outgoingMethod("workspace/applyEdit");
  PublishDiagnostics = Bind.outgoingNotification("textDocument/publishDiagnostics");
  if (Caps.InactiveRegions)
    PublishInactiveRegions = Bind.outgoingNotification("textDocument/inactiveRegions");
  ShowMessage = Bind.outgoingNotification("window/showMessage");
  NotifyFileStatus = Bind.outgoingNotification("textDocument/clangd.fileStatus");
  CreateWorkDoneProgress = Bind.outgoingMethod("window/workDoneProgress/create");
  BeginWorkDoneProgress = Bind.outgoingNotification("$/progress");
  ReportWorkDoneProgress = Bind.outgoingNotification("$/progress");
  EndWorkDoneProgress = Bind.outgoingNotification("$/progress");
  if(Caps.SemanticTokenRefreshSupport)
    SemanticTokensRefresh = Bind.outgoingMethod("workspace/semanticTokens/refresh");
  // clang-format on
}

ClangdLSPServer::~ClangdLSPServer() {
  IsBeingDestroyed = true;
  // Explicitly destroy ClangdServer first, blocking on threads it owns.
  // This ensures they don't access any other members.
  Server.reset();
}

bool ClangdLSPServer::run() {
  // Run the Language Server loop.
  bool CleanExit = true;
  if (auto Err = Transp.loop(*MsgHandler)) {
    elog("Transport error: {0}", std::move(Err));
    CleanExit = false;
  }

  return CleanExit && ShutdownRequestReceived;
}

void ClangdLSPServer::profile(MemoryTree &MT) const {
  if (Server)
    Server->profile(MT.child("clangd_server"));
}

std::optional<ClangdServer::DiagRef>
ClangdLSPServer::getDiagRef(StringRef File, const clangd::Diagnostic &D) {
  std::lock_guard<std::mutex> Lock(DiagRefMutex);
  auto DiagToDiagRefIter = DiagRefMap.find(File);
  if (DiagToDiagRefIter == DiagRefMap.end())
    return std::nullopt;

  const auto &DiagToDiagRefMap = DiagToDiagRefIter->second;
  auto FixItsIter = DiagToDiagRefMap.find(toDiagKey(D));
  if (FixItsIter == DiagToDiagRefMap.end())
    return std::nullopt;

  return FixItsIter->second;
}

// A completion request is sent when the user types '>' or ':', but we only
// want to trigger on '->' and '::'. We check the preceding text to make
// sure it matches what we expected.
// Running the lexer here would be more robust (e.g. we can detect comments
// and avoid triggering completion there), but we choose to err on the side
// of simplicity here.
bool ClangdLSPServer::shouldRunCompletion(
    const CompletionParams &Params) const {
  if (Params.context.triggerKind != CompletionTriggerKind::TriggerCharacter)
    return true;
  auto Code = Server->getDraft(Params.textDocument.uri.file());
  if (!Code)
    return true; // completion code will log the error for untracked doc.
  auto Offset = positionToOffset(*Code, Params.position,
                                 /*AllowColumnsBeyondLineLength=*/false);
  if (!Offset) {
    vlog("could not convert position '{0}' to offset for file '{1}'",
         Params.position, Params.textDocument.uri.file());
    return true;
  }
  return allowImplicitCompletion(*Code, *Offset);
}

void ClangdLSPServer::onDiagnosticsReady(PathRef File, llvm::StringRef Version,
                                         llvm::ArrayRef<Diag> Diagnostics) {
  PublishDiagnosticsParams Notification;
  Notification.version = decodeVersion(Version);
  Notification.uri = URIForFile::canonicalize(File, /*TUPath=*/File);
  DiagnosticToDiagRefMap LocalDiagMap; // Temporary storage
  for (auto &Diag : Diagnostics) {
    toLSPDiags(Diag, Notification.uri, DiagOpts,
               [&](clangd::Diagnostic LSPDiag, llvm::ArrayRef<Fix> Fixes) {
                 if (DiagOpts.EmbedFixesInDiagnostics) {
                   std::vector<CodeAction> CodeActions;
                   for (const auto &Fix : Fixes)
                     CodeActions.push_back(toCodeAction(
                         Fix, Notification.uri, Notification.version,
                         SupportsDocumentChanges, SupportsChangeAnnotation));
                   LSPDiag.codeActions.emplace(std::move(CodeActions));
                   if (LSPDiag.codeActions->size() == 1)
                     LSPDiag.codeActions->front().isPreferred = true;
                 }
                 LocalDiagMap[toDiagKey(LSPDiag)] = {Diag.Range, Diag.Message};
                 Notification.diagnostics.push_back(std::move(LSPDiag));
               });
  }

  // Cache DiagRefMap
  {
    std::lock_guard<std::mutex> Lock(DiagRefMutex);
    DiagRefMap[File] = LocalDiagMap;
  }

  // Send a notification to the LSP client.
  PublishDiagnostics(Notification);
}

void ClangdLSPServer::onInactiveRegionsReady(
    PathRef File, std::vector<Range> InactiveRegions) {
  InactiveRegionsParams Notification;
  Notification.TextDocument = {URIForFile::canonicalize(File, /*TUPath=*/File)};
  Notification.InactiveRegions = std::move(InactiveRegions);

  PublishInactiveRegions(Notification);
}

void ClangdLSPServer::onBackgroundIndexProgress(
    const BackgroundQueue::Stats &Stats) {
  static const char ProgressToken[] = "backgroundIndexProgress";

  // The background index did some work, maybe we need to cleanup
  maybeCleanupMemory();

  std::lock_guard<std::mutex> Lock(BackgroundIndexProgressMutex);

  auto NotifyProgress = [this](const BackgroundQueue::Stats &Stats) {
    if (BackgroundIndexProgressState != BackgroundIndexProgress::Live) {
      WorkDoneProgressBegin Begin;
      Begin.percentage = true;
      Begin.title = "indexing";
      BeginWorkDoneProgress({ProgressToken, std::move(Begin)});
      BackgroundIndexProgressState = BackgroundIndexProgress::Live;
    }

    if (Stats.Completed < Stats.Enqueued) {
      assert(Stats.Enqueued > Stats.LastIdle);
      WorkDoneProgressReport Report;
      Report.percentage = 100 * (Stats.Completed - Stats.LastIdle) /
                          (Stats.Enqueued - Stats.LastIdle);
      Report.message =
          llvm::formatv("{0}/{1}", Stats.Completed - Stats.LastIdle,
                        Stats.Enqueued - Stats.LastIdle);
      ReportWorkDoneProgress({ProgressToken, std::move(Report)});
    } else {
      assert(Stats.Completed == Stats.Enqueued);
      EndWorkDoneProgress({ProgressToken, WorkDoneProgressEnd()});
      BackgroundIndexProgressState = BackgroundIndexProgress::Empty;
    }
  };

  switch (BackgroundIndexProgressState) {
  case BackgroundIndexProgress::Unsupported:
    return;
  case BackgroundIndexProgress::Creating:
    // Cache this update for when the progress bar is available.
    PendingBackgroundIndexProgress = Stats;
    return;
  case BackgroundIndexProgress::Empty: {
    if (BackgroundIndexSkipCreate) {
      NotifyProgress(Stats);
      break;
    }
    // Cache this update for when the progress bar is available.
    PendingBackgroundIndexProgress = Stats;
    BackgroundIndexProgressState = BackgroundIndexProgress::Creating;
    WorkDoneProgressCreateParams CreateRequest;
    CreateRequest.token = ProgressToken;
    CreateWorkDoneProgress(
        CreateRequest,
        [this, NotifyProgress](llvm::Expected<std::nullptr_t> E) {
          std::lock_guard<std::mutex> Lock(BackgroundIndexProgressMutex);
          if (E) {
            NotifyProgress(this->PendingBackgroundIndexProgress);
          } else {
            elog("Failed to create background index progress bar: {0}",
                 E.takeError());
            // give up forever rather than thrashing about
            BackgroundIndexProgressState = BackgroundIndexProgress::Unsupported;
          }
        });
    break;
  }
  case BackgroundIndexProgress::Live:
    NotifyProgress(Stats);
    break;
  }
}

void ClangdLSPServer::onFileUpdated(PathRef File, const TUStatus &Status) {
  if (!SupportFileStatus)
    return;
  // FIXME: we don't emit "BuildingFile" and `RunningAction`, as these
  // two statuses are running faster in practice, which leads the UI constantly
  // changing, and doesn't provide much value. We may want to emit status at a
  // reasonable time interval (e.g. 0.5s).
  if (Status.PreambleActivity == PreambleAction::Idle &&
      (Status.ASTActivity.K == ASTAction::Building ||
       Status.ASTActivity.K == ASTAction::RunningAction))
    return;
  NotifyFileStatus(Status.render(File));
}

void ClangdLSPServer::onSemanticsMaybeChanged(PathRef File) {
  if (SemanticTokensRefresh) {
    SemanticTokensRefresh(NoParams{}, [](llvm::Expected<std::nullptr_t> E) {
      if (E)
        return;
      elog("Failed to refresh semantic tokens: {0}", E.takeError());
    });
  }
}

} // namespace clangd
} // namespace clang
