xref: /llvm-project/clang-tools-extra/clangd/ClangdLSPServer.cpp (revision 61fe67a4017375fd675f75652e857e837f77fa51)
1 //===--- ClangdLSPServer.cpp - LSP server ------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ClangdLSPServer.h"
10 #include "ClangdServer.h"
11 #include "CodeComplete.h"
12 #include "CompileCommands.h"
13 #include "Diagnostics.h"
14 #include "Feature.h"
15 #include "GlobalCompilationDatabase.h"
16 #include "LSPBinder.h"
17 #include "ModulesBuilder.h"
18 #include "Protocol.h"
19 #include "SemanticHighlighting.h"
20 #include "SourceCode.h"
21 #include "TUScheduler.h"
22 #include "URI.h"
23 #include "refactor/Tweak.h"
24 #include "support/Cancellation.h"
25 #include "support/Context.h"
26 #include "support/MemoryTree.h"
27 #include "support/Trace.h"
28 #include "clang/Tooling/Core/Replacement.h"
29 #include "llvm/ADT/ArrayRef.h"
30 #include "llvm/ADT/FunctionExtras.h"
31 #include "llvm/ADT/ScopeExit.h"
32 #include "llvm/ADT/StringRef.h"
33 #include "llvm/ADT/Twine.h"
34 #include "llvm/Support/Allocator.h"
35 #include "llvm/Support/Error.h"
36 #include "llvm/Support/FormatVariadic.h"
37 #include "llvm/Support/JSON.h"
38 #include "llvm/Support/SHA1.h"
39 #include "llvm/Support/ScopedPrinter.h"
40 #include "llvm/Support/raw_ostream.h"
41 #include <chrono>
42 #include <cstddef>
43 #include <cstdint>
44 #include <functional>
45 #include <map>
46 #include <memory>
47 #include <mutex>
48 #include <optional>
49 #include <string>
50 #include <utility>
51 #include <vector>
52 
53 namespace clang {
54 namespace clangd {
55 
56 namespace {
57 // Tracks end-to-end latency of high level lsp calls. Measurements are in
58 // seconds.
59 constexpr trace::Metric LSPLatency("lsp_latency", trace::Metric::Distribution,
60                                    "method_name");
61 
62 // LSP defines file versions as numbers that increase.
63 // ClangdServer treats them as opaque and therefore uses strings instead.
64 std::string encodeVersion(std::optional<int64_t> LSPVersion) {
65   return LSPVersion ? llvm::to_string(*LSPVersion) : "";
66 }
67 std::optional<int64_t> decodeVersion(llvm::StringRef Encoded) {
68   int64_t Result;
69   if (llvm::to_integer(Encoded, Result, 10))
70     return Result;
71   if (!Encoded.empty()) // Empty can be e.g. diagnostics on close.
72     elog("unexpected non-numeric version {0}", Encoded);
73   return std::nullopt;
74 }
75 
76 const llvm::StringLiteral ApplyFixCommand = "clangd.applyFix";
77 const llvm::StringLiteral ApplyTweakCommand = "clangd.applyTweak";
78 const llvm::StringLiteral ApplyRenameCommand = "clangd.applyRename";
79 
80 CodeAction toCodeAction(const ClangdServer::CodeActionResult::Rename &R,
81                         const URIForFile &File) {
82   CodeAction CA;
83   CA.title = R.FixMessage;
84   CA.kind = std::string(CodeAction::REFACTOR_KIND);
85   CA.command.emplace();
86   CA.command->title = R.FixMessage;
87   CA.command->command = std::string(ApplyRenameCommand);
88   RenameParams Params;
89   Params.textDocument = TextDocumentIdentifier{File};
90   Params.position = R.Diag.Range.start;
91   Params.newName = R.NewName;
92   CA.command->argument = Params;
93   return CA;
94 }
95 
96 /// Transforms a tweak into a code action that would apply it if executed.
97 /// EXPECTS: T.prepare() was called and returned true.
98 CodeAction toCodeAction(const ClangdServer::TweakRef &T, const URIForFile &File,
99                         Range Selection) {
100   CodeAction CA;
101   CA.title = T.Title;
102   CA.kind = T.Kind.str();
103   // This tweak may have an expensive second stage, we only run it if the user
104   // actually chooses it in the UI. We reply with a command that would run the
105   // corresponding tweak.
106   // FIXME: for some tweaks, computing the edits is cheap and we could send them
107   //        directly.
108   CA.command.emplace();
109   CA.command->title = T.Title;
110   CA.command->command = std::string(ApplyTweakCommand);
111   TweakArgs Args;
112   Args.file = File;
113   Args.tweakID = T.ID;
114   Args.selection = Selection;
115   CA.command->argument = std::move(Args);
116   return CA;
117 }
118 
119 /// Convert from Fix to LSP CodeAction.
120 CodeAction toCodeAction(const Fix &F, const URIForFile &File,
121                         const std::optional<int64_t> &Version,
122                         bool SupportsDocumentChanges,
123                         bool SupportChangeAnnotation) {
124   CodeAction Action;
125   Action.title = F.Message;
126   Action.kind = std::string(CodeAction::QUICKFIX_KIND);
127   Action.edit.emplace();
128   if (!SupportsDocumentChanges) {
129     Action.edit->changes.emplace();
130     auto &Changes = (*Action.edit->changes)[File.uri()];
131     for (const auto &E : F.Edits)
132       Changes.push_back({E.range, E.newText, /*annotationId=*/""});
133   } else {
134     Action.edit->documentChanges.emplace();
135     TextDocumentEdit &Edit = Action.edit->documentChanges->emplace_back();
136     Edit.textDocument = VersionedTextDocumentIdentifier{{File}, Version};
137     for (const auto &E : F.Edits)
138       Edit.edits.push_back(
139           {E.range, E.newText,
140            SupportChangeAnnotation ? E.annotationId : ""});
141     if (SupportChangeAnnotation) {
142       for (const auto &[AID, Annotation]: F.Annotations)
143         Action.edit->changeAnnotations[AID] = Annotation;
144     }
145   }
146   return Action;
147 }
148 
149 void adjustSymbolKinds(llvm::MutableArrayRef<DocumentSymbol> Syms,
150                        SymbolKindBitset Kinds) {
151   for (auto &S : Syms) {
152     S.kind = adjustKindToCapability(S.kind, Kinds);
153     adjustSymbolKinds(S.children, Kinds);
154   }
155 }
156 
157 SymbolKindBitset defaultSymbolKinds() {
158   SymbolKindBitset Defaults;
159   for (size_t I = SymbolKindMin; I <= static_cast<size_t>(SymbolKind::Array);
160        ++I)
161     Defaults.set(I);
162   return Defaults;
163 }
164 
165 CompletionItemKindBitset defaultCompletionItemKinds() {
166   CompletionItemKindBitset Defaults;
167   for (size_t I = CompletionItemKindMin;
168        I <= static_cast<size_t>(CompletionItemKind::Reference); ++I)
169     Defaults.set(I);
170   return Defaults;
171 }
172 
173 // Makes sure edits in \p FE are applicable to latest file contents reported by
174 // editor. If not generates an error message containing information about files
175 // that needs to be saved.
176 llvm::Error validateEdits(const ClangdServer &Server, const FileEdits &FE) {
177   size_t InvalidFileCount = 0;
178   llvm::StringRef LastInvalidFile;
179   for (const auto &It : FE) {
180     if (auto Draft = Server.getDraft(It.first())) {
181       // If the file is open in user's editor, make sure the version we
182       // saw and current version are compatible as this is the text that
183       // will be replaced by editors.
184       if (!It.second.canApplyTo(*Draft)) {
185         ++InvalidFileCount;
186         LastInvalidFile = It.first();
187       }
188     }
189   }
190   if (!InvalidFileCount)
191     return llvm::Error::success();
192   if (InvalidFileCount == 1)
193     return error("File must be saved first: {0}", LastInvalidFile);
194   return error("Files must be saved first: {0} (and {1} others)",
195                LastInvalidFile, InvalidFileCount - 1);
196 }
197 } // namespace
198 
199 // MessageHandler dispatches incoming LSP messages.
200 // It handles cross-cutting concerns:
201 //  - serializes/deserializes protocol objects to JSON
202 //  - logging of inbound messages
203 //  - cancellation handling
204 //  - basic call tracing
205 // MessageHandler ensures that initialize() is called before any other handler.
206 class ClangdLSPServer::MessageHandler : public Transport::MessageHandler {
207 public:
208   MessageHandler(ClangdLSPServer &Server) : Server(Server) {}
209 
210   bool onNotify(llvm::StringRef Method, llvm::json::Value Params) override {
211     trace::Span Tracer(Method, LSPLatency);
212     SPAN_ATTACH(Tracer, "Params", Params);
213     WithContext HandlerContext(handlerContext());
214     log("<-- {0}", Method);
215     if (Method == "exit")
216       return false;
217     auto Handler = Server.Handlers.NotificationHandlers.find(Method);
218     if (Handler != Server.Handlers.NotificationHandlers.end()) {
219       Handler->second(std::move(Params));
220       Server.maybeExportMemoryProfile();
221       Server.maybeCleanupMemory();
222     } else if (!Server.Server) {
223       elog("Notification {0} before initialization", Method);
224     } else if (Method == "$/cancelRequest") {
225       onCancel(std::move(Params));
226     } else {
227       log("unhandled notification {0}", Method);
228     }
229     return true;
230   }
231 
232   bool onCall(llvm::StringRef Method, llvm::json::Value Params,
233               llvm::json::Value ID) override {
234     WithContext HandlerContext(handlerContext());
235     // Calls can be canceled by the client. Add cancellation context.
236     WithContext WithCancel(cancelableRequestContext(ID));
237     trace::Span Tracer(Method, LSPLatency);
238     SPAN_ATTACH(Tracer, "Params", Params);
239     ReplyOnce Reply(ID, Method, &Server, Tracer.Args);
240     log("<-- {0}({1})", Method, ID);
241     auto Handler = Server.Handlers.MethodHandlers.find(Method);
242     if (Handler != Server.Handlers.MethodHandlers.end()) {
243       Handler->second(std::move(Params), std::move(Reply));
244     } else if (!Server.Server) {
245       elog("Call {0} before initialization.", Method);
246       Reply(llvm::make_error<LSPError>("server not initialized",
247                                        ErrorCode::ServerNotInitialized));
248     } else {
249       Reply(llvm::make_error<LSPError>("method not found",
250                                        ErrorCode::MethodNotFound));
251     }
252     return true;
253   }
254 
255   bool onReply(llvm::json::Value ID,
256                llvm::Expected<llvm::json::Value> Result) override {
257     WithContext HandlerContext(handlerContext());
258 
259     Callback<llvm::json::Value> ReplyHandler = nullptr;
260     if (auto IntID = ID.getAsInteger()) {
261       std::lock_guard<std::mutex> Mutex(CallMutex);
262       // Find a corresponding callback for the request ID;
263       for (size_t Index = 0; Index < ReplyCallbacks.size(); ++Index) {
264         if (ReplyCallbacks[Index].first == *IntID) {
265           ReplyHandler = std::move(ReplyCallbacks[Index].second);
266           ReplyCallbacks.erase(ReplyCallbacks.begin() +
267                                Index); // remove the entry
268           break;
269         }
270       }
271     }
272 
273     if (!ReplyHandler) {
274       // No callback being found, use a default log callback.
275       ReplyHandler = [&ID](llvm::Expected<llvm::json::Value> Result) {
276         elog("received a reply with ID {0}, but there was no such call", ID);
277         if (!Result)
278           llvm::consumeError(Result.takeError());
279       };
280     }
281 
282     // Log and run the reply handler.
283     if (Result) {
284       log("<-- reply({0})", ID);
285       ReplyHandler(std::move(Result));
286     } else {
287       auto Err = Result.takeError();
288       log("<-- reply({0}) error: {1}", ID, Err);
289       ReplyHandler(std::move(Err));
290     }
291     return true;
292   }
293 
294   // Bind a reply callback to a request. The callback will be invoked when
295   // clangd receives the reply from the LSP client.
296   // Return a call id of the request.
297   llvm::json::Value bindReply(Callback<llvm::json::Value> Reply) {
298     std::optional<std::pair<int, Callback<llvm::json::Value>>> OldestCB;
299     int ID;
300     {
301       std::lock_guard<std::mutex> Mutex(CallMutex);
302       ID = NextCallID++;
303       ReplyCallbacks.emplace_back(ID, std::move(Reply));
304 
305       // If the queue overflows, we assume that the client didn't reply the
306       // oldest request, and run the corresponding callback which replies an
307       // error to the client.
308       if (ReplyCallbacks.size() > MaxReplayCallbacks) {
309         elog("more than {0} outstanding LSP calls, forgetting about {1}",
310              MaxReplayCallbacks, ReplyCallbacks.front().first);
311         OldestCB = std::move(ReplyCallbacks.front());
312         ReplyCallbacks.pop_front();
313       }
314     }
315     if (OldestCB)
316       OldestCB->second(
317           error("failed to receive a client reply for request ({0})",
318                 OldestCB->first));
319     return ID;
320   }
321 
322 private:
323   // Function object to reply to an LSP call.
324   // Each instance must be called exactly once, otherwise:
325   //  - the bug is logged, and (in debug mode) an assert will fire
326   //  - if there was no reply, an error reply is sent
327   //  - if there were multiple replies, only the first is sent
328   class ReplyOnce {
329     std::atomic<bool> Replied = {false};
330     std::chrono::steady_clock::time_point Start;
331     llvm::json::Value ID;
332     std::string Method;
333     ClangdLSPServer *Server; // Null when moved-from.
334     llvm::json::Object *TraceArgs;
335 
336   public:
337     ReplyOnce(const llvm::json::Value &ID, llvm::StringRef Method,
338               ClangdLSPServer *Server, llvm::json::Object *TraceArgs)
339         : Start(std::chrono::steady_clock::now()), ID(ID), Method(Method),
340           Server(Server), TraceArgs(TraceArgs) {
341       assert(Server);
342     }
343     ReplyOnce(ReplyOnce &&Other)
344         : Replied(Other.Replied.load()), Start(Other.Start),
345           ID(std::move(Other.ID)), Method(std::move(Other.Method)),
346           Server(Other.Server), TraceArgs(Other.TraceArgs) {
347       Other.Server = nullptr;
348     }
349     ReplyOnce &operator=(ReplyOnce &&) = delete;
350     ReplyOnce(const ReplyOnce &) = delete;
351     ReplyOnce &operator=(const ReplyOnce &) = delete;
352 
353     ~ReplyOnce() {
354       // There's one legitimate reason to never reply to a request: clangd's
355       // request handler send a call to the client (e.g. applyEdit) and the
356       // client never replied. In this case, the ReplyOnce is owned by
357       // ClangdLSPServer's reply callback table and is destroyed along with the
358       // server. We don't attempt to send a reply in this case, there's little
359       // to be gained from doing so.
360       if (Server && !Server->IsBeingDestroyed && !Replied) {
361         elog("No reply to message {0}({1})", Method, ID);
362         assert(false && "must reply to all calls!");
363         (*this)(llvm::make_error<LSPError>("server failed to reply",
364                                            ErrorCode::InternalError));
365       }
366     }
367 
368     void operator()(llvm::Expected<llvm::json::Value> Reply) {
369       assert(Server && "moved-from!");
370       if (Replied.exchange(true)) {
371         elog("Replied twice to message {0}({1})", Method, ID);
372         assert(false && "must reply to each call only once!");
373         return;
374       }
375       auto Duration = std::chrono::steady_clock::now() - Start;
376       if (Reply) {
377         log("--> reply:{0}({1}) {2:ms}", Method, ID, Duration);
378         if (TraceArgs)
379           (*TraceArgs)["Reply"] = *Reply;
380         std::lock_guard<std::mutex> Lock(Server->TranspWriter);
381         Server->Transp.reply(std::move(ID), std::move(Reply));
382       } else {
383         llvm::Error Err = Reply.takeError();
384         log("--> reply:{0}({1}) {2:ms}, error: {3}", Method, ID, Duration, Err);
385         if (TraceArgs)
386           (*TraceArgs)["Error"] = llvm::to_string(Err);
387         std::lock_guard<std::mutex> Lock(Server->TranspWriter);
388         Server->Transp.reply(std::move(ID), std::move(Err));
389       }
390     }
391   };
392 
393   // Method calls may be cancelled by ID, so keep track of their state.
394   // This needs a mutex: handlers may finish on a different thread, and that's
395   // when we clean up entries in the map.
396   mutable std::mutex RequestCancelersMutex;
397   llvm::StringMap<std::pair<Canceler, /*Cookie*/ unsigned>> RequestCancelers;
398   unsigned NextRequestCookie = 0; // To disambiguate reused IDs, see below.
399   void onCancel(const llvm::json::Value &Params) {
400     const llvm::json::Value *ID = nullptr;
401     if (auto *O = Params.getAsObject())
402       ID = O->get("id");
403     if (!ID) {
404       elog("Bad cancellation request: {0}", Params);
405       return;
406     }
407     auto StrID = llvm::to_string(*ID);
408     std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
409     auto It = RequestCancelers.find(StrID);
410     if (It != RequestCancelers.end())
411       It->second.first(); // Invoke the canceler.
412   }
413 
414   Context handlerContext() const {
415     return Context::current().derive(
416         kCurrentOffsetEncoding,
417         Server.Opts.Encoding.value_or(OffsetEncoding::UTF16));
418   }
419 
420   // We run cancelable requests in a context that does two things:
421   //  - allows cancellation using RequestCancelers[ID]
422   //  - cleans up the entry in RequestCancelers when it's no longer needed
423   // If a client reuses an ID, the last wins and the first cannot be canceled.
424   Context cancelableRequestContext(const llvm::json::Value &ID) {
425     auto Task = cancelableTask(
426         /*Reason=*/static_cast<int>(ErrorCode::RequestCancelled));
427     auto StrID = llvm::to_string(ID);  // JSON-serialize ID for map key.
428     auto Cookie = NextRequestCookie++; // No lock, only called on main thread.
429     {
430       std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
431       RequestCancelers[StrID] = {std::move(Task.second), Cookie};
432     }
433     // When the request ends, we can clean up the entry we just added.
434     // The cookie lets us check that it hasn't been overwritten due to ID
435     // reuse.
436     return Task.first.derive(llvm::make_scope_exit([this, StrID, Cookie] {
437       std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
438       auto It = RequestCancelers.find(StrID);
439       if (It != RequestCancelers.end() && It->second.second == Cookie)
440         RequestCancelers.erase(It);
441     }));
442   }
443 
444   // The maximum number of callbacks held in clangd.
445   //
446   // We bound the maximum size to the pending map to prevent memory leakage
447   // for cases where LSP clients don't reply for the request.
448   // This has to go after RequestCancellers and RequestCancellersMutex since it
449   // can contain a callback that has a cancelable context.
450   static constexpr int MaxReplayCallbacks = 100;
451   mutable std::mutex CallMutex;
452   int NextCallID = 0; /* GUARDED_BY(CallMutex) */
453   std::deque<std::pair</*RequestID*/ int,
454                        /*ReplyHandler*/ Callback<llvm::json::Value>>>
455       ReplyCallbacks; /* GUARDED_BY(CallMutex) */
456 
457   ClangdLSPServer &Server;
458 };
459 constexpr int ClangdLSPServer::MessageHandler::MaxReplayCallbacks;
460 
461 // call(), notify(), and reply() wrap the Transport, adding logging and locking.
462 void ClangdLSPServer::callMethod(StringRef Method, llvm::json::Value Params,
463                                  Callback<llvm::json::Value> CB) {
464   auto ID = MsgHandler->bindReply(std::move(CB));
465   log("--> {0}({1})", Method, ID);
466   std::lock_guard<std::mutex> Lock(TranspWriter);
467   Transp.call(Method, std::move(Params), ID);
468 }
469 
470 void ClangdLSPServer::notify(llvm::StringRef Method, llvm::json::Value Params) {
471   log("--> {0}", Method);
472   maybeCleanupMemory();
473   std::lock_guard<std::mutex> Lock(TranspWriter);
474   Transp.notify(Method, std::move(Params));
475 }
476 
477 static std::vector<llvm::StringRef> semanticTokenTypes() {
478   std::vector<llvm::StringRef> Types;
479   for (unsigned I = 0; I <= static_cast<unsigned>(HighlightingKind::LastKind);
480        ++I)
481     Types.push_back(toSemanticTokenType(static_cast<HighlightingKind>(I)));
482   return Types;
483 }
484 
485 static std::vector<llvm::StringRef> semanticTokenModifiers() {
486   std::vector<llvm::StringRef> Modifiers;
487   for (unsigned I = 0;
488        I <= static_cast<unsigned>(HighlightingModifier::LastModifier); ++I)
489     Modifiers.push_back(
490         toSemanticTokenModifier(static_cast<HighlightingModifier>(I)));
491   return Modifiers;
492 }
493 
494 void ClangdLSPServer::onInitialize(const InitializeParams &Params,
495                                    Callback<llvm::json::Value> Reply) {
496   // Determine character encoding first as it affects constructed ClangdServer.
497   if (Params.capabilities.offsetEncoding && !Opts.Encoding) {
498     Opts.Encoding = OffsetEncoding::UTF16; // fallback
499     for (OffsetEncoding Supported : *Params.capabilities.offsetEncoding)
500       if (Supported != OffsetEncoding::UnsupportedEncoding) {
501         Opts.Encoding = Supported;
502         break;
503       }
504   }
505 
506   if (Params.capabilities.TheiaSemanticHighlighting &&
507       !Params.capabilities.SemanticTokens) {
508     elog("Client requested legacy semanticHighlights notification, which is "
509          "no longer supported. Migrate to standard semanticTokens request");
510   }
511 
512   if (Params.rootUri && *Params.rootUri)
513     Opts.WorkspaceRoot = std::string(Params.rootUri->file());
514   else if (Params.rootPath && !Params.rootPath->empty())
515     Opts.WorkspaceRoot = *Params.rootPath;
516   if (Server)
517     return Reply(llvm::make_error<LSPError>("server already initialized",
518                                             ErrorCode::InvalidRequest));
519 
520   Opts.CodeComplete.EnableSnippets = Params.capabilities.CompletionSnippets;
521   Opts.CodeComplete.IncludeFixIts = Params.capabilities.CompletionFixes;
522   if (!Opts.CodeComplete.BundleOverloads)
523     Opts.CodeComplete.BundleOverloads = Params.capabilities.HasSignatureHelp;
524   Opts.CodeComplete.DocumentationFormat =
525       Params.capabilities.CompletionDocumentationFormat;
526   Opts.SignatureHelpDocumentationFormat =
527       Params.capabilities.SignatureHelpDocumentationFormat;
528   DiagOpts.EmbedFixesInDiagnostics = Params.capabilities.DiagnosticFixes;
529   DiagOpts.SendDiagnosticCategory = Params.capabilities.DiagnosticCategory;
530   DiagOpts.EmitRelatedLocations =
531       Params.capabilities.DiagnosticRelatedInformation;
532   if (Params.capabilities.WorkspaceSymbolKinds)
533     SupportedSymbolKinds |= *Params.capabilities.WorkspaceSymbolKinds;
534   if (Params.capabilities.CompletionItemKinds)
535     SupportedCompletionItemKinds |= *Params.capabilities.CompletionItemKinds;
536   SupportsCompletionLabelDetails = Params.capabilities.CompletionLabelDetail;
537   SupportsCodeAction = Params.capabilities.CodeActionStructure;
538   SupportsHierarchicalDocumentSymbol =
539       Params.capabilities.HierarchicalDocumentSymbol;
540   SupportsReferenceContainer = Params.capabilities.ReferenceContainer;
541   SupportFileStatus = Params.initializationOptions.FileStatus;
542   SupportsDocumentChanges = Params.capabilities.DocumentChanges;
543   SupportsChangeAnnotation = Params.capabilities.ChangeAnnotation;
544   HoverContentFormat = Params.capabilities.HoverContentFormat;
545   Opts.LineFoldingOnly = Params.capabilities.LineFoldingOnly;
546   SupportsOffsetsInSignatureHelp = Params.capabilities.OffsetsInSignatureHelp;
547   if (Params.capabilities.WorkDoneProgress)
548     BackgroundIndexProgressState = BackgroundIndexProgress::Empty;
549   BackgroundIndexSkipCreate = Params.capabilities.ImplicitProgressCreation;
550   Opts.ImplicitCancellation = !Params.capabilities.CancelsStaleRequests;
551   Opts.PublishInactiveRegions = Params.capabilities.InactiveRegions;
552 
553   if (Opts.UseDirBasedCDB) {
554     DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS);
555     if (const auto &Dir = Params.initializationOptions.compilationDatabasePath)
556       CDBOpts.CompileCommandsDir = Dir;
557     CDBOpts.ContextProvider = Opts.ContextProvider;
558     BaseCDB =
559         std::make_unique<DirectoryBasedGlobalCompilationDatabase>(CDBOpts);
560   }
561   auto Mangler = CommandMangler::detect();
562   Mangler.SystemIncludeExtractor =
563       getSystemIncludeExtractor(llvm::ArrayRef(Opts.QueryDriverGlobs));
564   if (Opts.ResourceDir)
565     Mangler.ResourceDir = *Opts.ResourceDir;
566   CDB.emplace(BaseCDB.get(), Params.initializationOptions.fallbackFlags,
567               std::move(Mangler));
568 
569   if (Opts.EnableExperimentalModulesSupport) {
570     ModulesManager.emplace(*CDB);
571     Opts.ModulesManager = &*ModulesManager;
572   }
573 
574   {
575     // Switch caller's context with LSPServer's background context. Since we
576     // rather want to propagate information from LSPServer's context into the
577     // Server, CDB, etc.
578     WithContext MainContext(BackgroundContext.clone());
579     std::optional<WithContextValue> WithOffsetEncoding;
580     if (Opts.Encoding)
581       WithOffsetEncoding.emplace(kCurrentOffsetEncoding, *Opts.Encoding);
582     Server.emplace(*CDB, TFS, Opts,
583                    static_cast<ClangdServer::Callbacks *>(this));
584   }
585 
586   llvm::json::Object ServerCaps{
587       {"textDocumentSync",
588        llvm::json::Object{
589            {"openClose", true},
590            {"change", (int)TextDocumentSyncKind::Incremental},
591            {"save", true},
592        }},
593       {"documentFormattingProvider", true},
594       {"documentRangeFormattingProvider", true},
595       {"documentOnTypeFormattingProvider",
596        llvm::json::Object{
597            {"firstTriggerCharacter", "\n"},
598            {"moreTriggerCharacter", {}},
599        }},
600       {"completionProvider",
601        llvm::json::Object{
602            // We don't set `(` etc as allCommitCharacters as they interact
603            // poorly with snippet results.
604            // See https://github.com/clangd/vscode-clangd/issues/357
605            // Hopefully we can use them one day without this side-effect:
606            //     https://github.com/microsoft/vscode/issues/42544
607            {"resolveProvider", false},
608            // We do extra checks, e.g. that > is part of ->.
609            {"triggerCharacters", {".", "<", ">", ":", "\"", "/", "*"}},
610        }},
611       {"semanticTokensProvider",
612        llvm::json::Object{
613            {"full", llvm::json::Object{{"delta", true}}},
614            {"range", false},
615            {"legend",
616             llvm::json::Object{{"tokenTypes", semanticTokenTypes()},
617                                {"tokenModifiers", semanticTokenModifiers()}}},
618        }},
619       {"signatureHelpProvider",
620        llvm::json::Object{
621            {"triggerCharacters", {"(", ")", "{", "}", "<", ">", ","}},
622        }},
623       {"declarationProvider", true},
624       {"definitionProvider", true},
625       {"implementationProvider", true},
626       {"typeDefinitionProvider", true},
627       {"documentHighlightProvider", true},
628       {"documentLinkProvider",
629        llvm::json::Object{
630            {"resolveProvider", false},
631        }},
632       {"hoverProvider", true},
633       {"selectionRangeProvider", true},
634       {"documentSymbolProvider", true},
635       {"workspaceSymbolProvider", true},
636       {"referencesProvider", true},
637       {"astProvider", true}, // clangd extension
638       {"typeHierarchyProvider", true},
639       // Unfortunately our extension made use of the same capability name as the
640       // standard. Advertise this capability to tell clients that implement our
641       // extension we really have support for the standardized one as well.
642       {"standardTypeHierarchyProvider", true}, // clangd extension
643       {"memoryUsageProvider", true},           // clangd extension
644       {"compilationDatabase",                  // clangd extension
645        llvm::json::Object{{"automaticReload", true}}},
646       {"inactiveRegionsProvider", true}, // clangd extension
647       {"callHierarchyProvider", true},
648       {"clangdInlayHintsProvider", true},
649       {"inlayHintProvider", true},
650       {"foldingRangeProvider", true},
651   };
652 
653   {
654     LSPBinder Binder(Handlers, *this);
655     bindMethods(Binder, Params.capabilities);
656     if (Opts.FeatureModules)
657       for (auto &Mod : *Opts.FeatureModules)
658         Mod.initializeLSP(Binder, Params.rawCapabilities, ServerCaps);
659   }
660 
661   // Per LSP, renameProvider can be either boolean or RenameOptions.
662   // RenameOptions will be specified if the client states it supports prepare.
663   ServerCaps["renameProvider"] =
664       Params.capabilities.RenamePrepareSupport
665           ? llvm::json::Object{{"prepareProvider", true}}
666           : llvm::json::Value(true);
667 
668   // Per LSP, codeActionProvider can be either boolean or CodeActionOptions.
669   // CodeActionOptions is only valid if the client supports action literal
670   // via textDocument.codeAction.codeActionLiteralSupport.
671   ServerCaps["codeActionProvider"] =
672       Params.capabilities.CodeActionStructure
673           ? llvm::json::Object{{"codeActionKinds",
674                                 {CodeAction::QUICKFIX_KIND,
675                                  CodeAction::REFACTOR_KIND,
676                                  CodeAction::INFO_KIND}}}
677           : llvm::json::Value(true);
678 
679   std::vector<llvm::StringRef> Commands;
680   for (llvm::StringRef Command : Handlers.CommandHandlers.keys())
681     Commands.push_back(Command);
682   llvm::sort(Commands);
683   ServerCaps["executeCommandProvider"] =
684       llvm::json::Object{{"commands", Commands}};
685 
686   llvm::json::Object Result{
687       {{"serverInfo",
688         llvm::json::Object{
689             {"name", "clangd"},
690             {"version", llvm::formatv("{0} {1} {2}", versionString(),
691                                       featureString(), platformString())}}},
692        {"capabilities", std::move(ServerCaps)}}};
693   if (Opts.Encoding)
694     Result["offsetEncoding"] = *Opts.Encoding;
695   Reply(std::move(Result));
696 
697   // Apply settings after we're fully initialized.
698   // This can start background indexing and in turn trigger LSP notifications.
699   applyConfiguration(Params.initializationOptions.ConfigSettings);
700 }
701 
702 void ClangdLSPServer::onInitialized(const InitializedParams &Params) {}
703 
704 void ClangdLSPServer::onShutdown(const NoParams &,
705                                  Callback<std::nullptr_t> Reply) {
706   // Do essentially nothing, just say we're ready to exit.
707   ShutdownRequestReceived = true;
708   Reply(nullptr);
709 }
710 
711 // sync is a clangd extension: it blocks until all background work completes.
712 // It blocks the calling thread, so no messages are processed until it returns!
713 void ClangdLSPServer::onSync(const NoParams &, Callback<std::nullptr_t> Reply) {
714   if (Server->blockUntilIdleForTest(/*TimeoutSeconds=*/60))
715     Reply(nullptr);
716   else
717     Reply(error("Not idle after a minute"));
718 }
719 
720 void ClangdLSPServer::onDocumentDidOpen(
721     const DidOpenTextDocumentParams &Params) {
722   PathRef File = Params.textDocument.uri.file();
723 
724   const std::string &Contents = Params.textDocument.text;
725 
726   Server->addDocument(File, Contents,
727                       encodeVersion(Params.textDocument.version),
728                       WantDiagnostics::Yes);
729 }
730 
731 void ClangdLSPServer::onDocumentDidChange(
732     const DidChangeTextDocumentParams &Params) {
733   auto WantDiags = WantDiagnostics::Auto;
734   if (Params.wantDiagnostics)
735     WantDiags =
736         *Params.wantDiagnostics ? WantDiagnostics::Yes : WantDiagnostics::No;
737 
738   PathRef File = Params.textDocument.uri.file();
739   auto Code = Server->getDraft(File);
740   if (!Code) {
741     log("Trying to incrementally change non-added document: {0}", File);
742     return;
743   }
744   std::string NewCode(*Code);
745   for (const auto &Change : Params.contentChanges) {
746     if (auto Err = applyChange(NewCode, Change)) {
747       // If this fails, we are most likely going to be not in sync anymore with
748       // the client.  It is better to remove the draft and let further
749       // operations fail rather than giving wrong results.
750       Server->removeDocument(File);
751       elog("Failed to update {0}: {1}", File, std::move(Err));
752       return;
753     }
754   }
755   Server->addDocument(File, NewCode, encodeVersion(Params.textDocument.version),
756                       WantDiags, Params.forceRebuild);
757 }
758 
759 void ClangdLSPServer::onDocumentDidSave(
760     const DidSaveTextDocumentParams &Params) {
761   Server->reparseOpenFilesIfNeeded([](llvm::StringRef) { return true; });
762 }
763 
764 void ClangdLSPServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
765   // We could also reparse all open files here. However:
766   //  - this could be frequent, and revalidating all the preambles isn't free
767   //  - this is useful e.g. when switching git branches, but we're likely to see
768   //    fresh headers but still have the old-branch main-file content
769   Server->onFileEvent(Params);
770   // FIXME: observe config files, immediately expire time-based caches, reparse:
771   //  - compile_commands.json and compile_flags.txt
772   //  - .clang_format and .clang-tidy
773   //  - .clangd and clangd/config.yaml
774 }
775 
776 void ClangdLSPServer::onCommand(const ExecuteCommandParams &Params,
777                                 Callback<llvm::json::Value> Reply) {
778   auto It = Handlers.CommandHandlers.find(Params.command);
779   if (It == Handlers.CommandHandlers.end()) {
780     return Reply(llvm::make_error<LSPError>(
781         llvm::formatv("Unsupported command \"{0}\".", Params.command).str(),
782         ErrorCode::InvalidParams));
783   }
784   It->second(Params.argument, std::move(Reply));
785 }
786 
787 void ClangdLSPServer::onCommandApplyEdit(const WorkspaceEdit &WE,
788                                          Callback<llvm::json::Value> Reply) {
789   // The flow for "apply-fix" :
790   // 1. We publish a diagnostic, including fixits
791   // 2. The user clicks on the diagnostic, the editor asks us for code actions
792   // 3. We send code actions, with the fixit embedded as context
793   // 4. The user selects the fixit, the editor asks us to apply it
794   // 5. We unwrap the changes and send them back to the editor
795   // 6. The editor applies the changes (applyEdit), and sends us a reply
796   // 7. We unwrap the reply and send a reply to the editor.
797   applyEdit(WE, "Fix applied.", std::move(Reply));
798 }
799 
800 void ClangdLSPServer::onCommandApplyTweak(const TweakArgs &Args,
801                                           Callback<llvm::json::Value> Reply) {
802   auto Action = [this, Reply = std::move(Reply)](
803                     llvm::Expected<Tweak::Effect> R) mutable {
804     if (!R)
805       return Reply(R.takeError());
806 
807     assert(R->ShowMessage || (!R->ApplyEdits.empty() && "tweak has no effect"));
808 
809     if (R->ShowMessage) {
810       ShowMessageParams Msg;
811       Msg.message = *R->ShowMessage;
812       Msg.type = MessageType::Info;
813       ShowMessage(Msg);
814     }
815     // When no edit is specified, make sure we Reply().
816     if (R->ApplyEdits.empty())
817       return Reply("Tweak applied.");
818 
819     if (auto Err = validateEdits(*Server, R->ApplyEdits))
820       return Reply(std::move(Err));
821 
822     WorkspaceEdit WE;
823     // FIXME: use documentChanges when SupportDocumentChanges is true.
824     WE.changes.emplace();
825     for (const auto &It : R->ApplyEdits) {
826       (*WE.changes)[URI::createFile(It.first()).toString()] =
827           It.second.asTextEdits();
828     }
829     // ApplyEdit will take care of calling Reply().
830     return applyEdit(std::move(WE), "Tweak applied.", std::move(Reply));
831   };
832   Server->applyTweak(Args.file.file(), Args.selection, Args.tweakID,
833                      std::move(Action));
834 }
835 
836 void ClangdLSPServer::onCommandApplyRename(const RenameParams &R,
837                                            Callback<llvm::json::Value> Reply) {
838   onRename(R, [this, Reply = std::move(Reply)](
839                   llvm::Expected<WorkspaceEdit> Edit) mutable {
840     if (!Edit)
841       Reply(Edit.takeError());
842     applyEdit(std::move(*Edit), "Rename applied.", std::move(Reply));
843   });
844 }
845 
846 void ClangdLSPServer::applyEdit(WorkspaceEdit WE, llvm::json::Value Success,
847                                 Callback<llvm::json::Value> Reply) {
848   ApplyWorkspaceEditParams Edit;
849   Edit.edit = std::move(WE);
850   ApplyWorkspaceEdit(
851       Edit, [Reply = std::move(Reply), SuccessMessage = std::move(Success)](
852                 llvm::Expected<ApplyWorkspaceEditResponse> Response) mutable {
853         if (!Response)
854           return Reply(Response.takeError());
855         if (!Response->applied) {
856           std::string Reason = Response->failureReason
857                                    ? *Response->failureReason
858                                    : "unknown reason";
859           return Reply(error("edits were not applied: {0}", Reason));
860         }
861         return Reply(SuccessMessage);
862       });
863 }
864 
865 void ClangdLSPServer::onWorkspaceSymbol(
866     const WorkspaceSymbolParams &Params,
867     Callback<std::vector<SymbolInformation>> Reply) {
868   Server->workspaceSymbols(
869       Params.query, Params.limit.value_or(Opts.CodeComplete.Limit),
870       [Reply = std::move(Reply),
871        this](llvm::Expected<std::vector<SymbolInformation>> Items) mutable {
872         if (!Items)
873           return Reply(Items.takeError());
874         for (auto &Sym : *Items)
875           Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);
876 
877         Reply(std::move(*Items));
878       });
879 }
880 
881 void ClangdLSPServer::onPrepareRename(const TextDocumentPositionParams &Params,
882                                       Callback<PrepareRenameResult> Reply) {
883   Server->prepareRename(
884       Params.textDocument.uri.file(), Params.position, /*NewName*/ std::nullopt,
885       Opts.Rename,
886       [Reply = std::move(Reply)](llvm::Expected<RenameResult> Result) mutable {
887         if (!Result)
888           return Reply(Result.takeError());
889         PrepareRenameResult PrepareResult;
890         PrepareResult.range = Result->Target;
891         PrepareResult.placeholder = Result->Placeholder;
892         return Reply(std::move(PrepareResult));
893       });
894 }
895 
896 void ClangdLSPServer::onRename(const RenameParams &Params,
897                                Callback<WorkspaceEdit> Reply) {
898   Path File = std::string(Params.textDocument.uri.file());
899   if (!Server->getDraft(File))
900     return Reply(llvm::make_error<LSPError>(
901         "onRename called for non-added file", ErrorCode::InvalidParams));
902   Server->rename(File, Params.position, Params.newName, Opts.Rename,
903                  [File, Params, Reply = std::move(Reply),
904                   this](llvm::Expected<RenameResult> R) mutable {
905                    if (!R)
906                      return Reply(R.takeError());
907                    if (auto Err = validateEdits(*Server, R->GlobalChanges))
908                      return Reply(std::move(Err));
909                    WorkspaceEdit Result;
910                    // FIXME: use documentChanges if SupportDocumentChanges is
911                    // true.
912                    Result.changes.emplace();
913                    for (const auto &Rep : R->GlobalChanges) {
914                      (*Result
915                            .changes)[URI::createFile(Rep.first()).toString()] =
916                          Rep.second.asTextEdits();
917                    }
918                    Reply(Result);
919                  });
920 }
921 
922 void ClangdLSPServer::onDocumentDidClose(
923     const DidCloseTextDocumentParams &Params) {
924   PathRef File = Params.textDocument.uri.file();
925   Server->removeDocument(File);
926 
927   {
928     std::lock_guard<std::mutex> Lock(DiagRefMutex);
929     DiagRefMap.erase(File);
930   }
931   {
932     std::lock_guard<std::mutex> HLock(SemanticTokensMutex);
933     LastSemanticTokens.erase(File);
934   }
935   // clangd will not send updates for this file anymore, so we empty out the
936   // list of diagnostics shown on the client (e.g. in the "Problems" pane of
937   // VSCode). Note that this cannot race with actual diagnostics responses
938   // because removeDocument() guarantees no diagnostic callbacks will be
939   // executed after it returns.
940   PublishDiagnosticsParams Notification;
941   Notification.uri = URIForFile::canonicalize(File, /*TUPath=*/File);
942   PublishDiagnostics(Notification);
943 }
944 
945 void ClangdLSPServer::onDocumentOnTypeFormatting(
946     const DocumentOnTypeFormattingParams &Params,
947     Callback<std::vector<TextEdit>> Reply) {
948   auto File = Params.textDocument.uri.file();
949   Server->formatOnType(File, Params.position, Params.ch, std::move(Reply));
950 }
951 
952 void ClangdLSPServer::onDocumentRangeFormatting(
953     const DocumentRangeFormattingParams &Params,
954     Callback<std::vector<TextEdit>> Reply) {
955   auto File = Params.textDocument.uri.file();
956   auto Code = Server->getDraft(File);
957   Server->formatFile(File, Params.range,
958                      [Code = std::move(Code), Reply = std::move(Reply)](
959                          llvm::Expected<tooling::Replacements> Result) mutable {
960                        if (Result)
961                          Reply(replacementsToEdits(*Code, Result.get()));
962                        else
963                          Reply(Result.takeError());
964                      });
965 }
966 
967 void ClangdLSPServer::onDocumentFormatting(
968     const DocumentFormattingParams &Params,
969     Callback<std::vector<TextEdit>> Reply) {
970   auto File = Params.textDocument.uri.file();
971   auto Code = Server->getDraft(File);
972   Server->formatFile(File,
973                      /*Rng=*/std::nullopt,
974                      [Code = std::move(Code), Reply = std::move(Reply)](
975                          llvm::Expected<tooling::Replacements> Result) mutable {
976                        if (Result)
977                          Reply(replacementsToEdits(*Code, Result.get()));
978                        else
979                          Reply(Result.takeError());
980                      });
981 }
982 
983 /// The functions constructs a flattened view of the DocumentSymbol hierarchy.
984 /// Used by the clients that do not support the hierarchical view.
985 static std::vector<SymbolInformation>
986 flattenSymbolHierarchy(llvm::ArrayRef<DocumentSymbol> Symbols,
987                        const URIForFile &FileURI) {
988   std::vector<SymbolInformation> Results;
989   std::function<void(const DocumentSymbol &, llvm::StringRef)> Process =
990       [&](const DocumentSymbol &S, std::optional<llvm::StringRef> ParentName) {
991         SymbolInformation SI;
992         SI.containerName = std::string(ParentName ? "" : *ParentName);
993         SI.name = S.name;
994         SI.kind = S.kind;
995         SI.location.range = S.range;
996         SI.location.uri = FileURI;
997 
998         Results.push_back(std::move(SI));
999         std::string FullName =
1000             !ParentName ? S.name : (ParentName->str() + "::" + S.name);
1001         for (auto &C : S.children)
1002           Process(C, /*ParentName=*/FullName);
1003       };
1004   for (auto &S : Symbols)
1005     Process(S, /*ParentName=*/"");
1006   return Results;
1007 }
1008 
1009 void ClangdLSPServer::onDocumentSymbol(const DocumentSymbolParams &Params,
1010                                        Callback<llvm::json::Value> Reply) {
1011   URIForFile FileURI = Params.textDocument.uri;
1012   Server->documentSymbols(
1013       Params.textDocument.uri.file(),
1014       [this, FileURI, Reply = std::move(Reply)](
1015           llvm::Expected<std::vector<DocumentSymbol>> Items) mutable {
1016         if (!Items)
1017           return Reply(Items.takeError());
1018         adjustSymbolKinds(*Items, SupportedSymbolKinds);
1019         if (SupportsHierarchicalDocumentSymbol)
1020           return Reply(std::move(*Items));
1021         return Reply(flattenSymbolHierarchy(*Items, FileURI));
1022       });
1023 }
1024 
1025 void ClangdLSPServer::onFoldingRange(
1026     const FoldingRangeParams &Params,
1027     Callback<std::vector<FoldingRange>> Reply) {
1028   Server->foldingRanges(Params.textDocument.uri.file(), std::move(Reply));
1029 }
1030 
1031 static std::optional<Command> asCommand(const CodeAction &Action) {
1032   Command Cmd;
1033   if (Action.command && Action.edit)
1034     return std::nullopt; // Not representable. (We never emit these anyway).
1035   if (Action.command) {
1036     Cmd = *Action.command;
1037   } else if (Action.edit) {
1038     Cmd.command = std::string(ApplyFixCommand);
1039     Cmd.argument = *Action.edit;
1040   } else {
1041     return std::nullopt;
1042   }
1043   Cmd.title = Action.title;
1044   if (Action.kind && *Action.kind == CodeAction::QUICKFIX_KIND)
1045     Cmd.title = "Apply fix: " + Cmd.title;
1046   return Cmd;
1047 }
1048 
1049 void ClangdLSPServer::onCodeAction(const CodeActionParams &Params,
1050                                    Callback<llvm::json::Value> Reply) {
1051   URIForFile File = Params.textDocument.uri;
1052   std::map<ClangdServer::DiagRef, clangd::Diagnostic> ToLSPDiags;
1053   ClangdServer::CodeActionInputs Inputs;
1054 
1055   for (const auto& LSPDiag : Params.context.diagnostics) {
1056     if (auto DiagRef = getDiagRef(File.file(), LSPDiag)) {
1057       ToLSPDiags[*DiagRef] = LSPDiag;
1058       Inputs.Diagnostics.push_back(*DiagRef);
1059     }
1060   }
1061   Inputs.File = File.file();
1062   Inputs.Selection = Params.range;
1063   Inputs.RequestedActionKinds = Params.context.only;
1064   Inputs.TweakFilter = [this](const Tweak &T) {
1065     return Opts.TweakFilter(T);
1066   };
1067   auto CB = [this,
1068              Reply = std::move(Reply),
1069              ToLSPDiags = std::move(ToLSPDiags), File,
1070              Selection = Params.range](
1071                 llvm::Expected<ClangdServer::CodeActionResult> Fixits) mutable {
1072     if (!Fixits)
1073       return Reply(Fixits.takeError());
1074     std::vector<CodeAction> CAs;
1075     auto Version = decodeVersion(Fixits->Version);
1076     for (const auto &QF : Fixits->QuickFixes) {
1077       CAs.push_back(toCodeAction(QF.F, File, Version, SupportsDocumentChanges,
1078                                  SupportsChangeAnnotation));
1079       if (auto It = ToLSPDiags.find(QF.Diag);
1080           It != ToLSPDiags.end()) {
1081         CAs.back().diagnostics = {It->second};
1082       }
1083     }
1084 
1085     for (const auto &R : Fixits->Renames)
1086       CAs.push_back(toCodeAction(R, File));
1087 
1088     for (const auto &TR : Fixits->TweakRefs)
1089       CAs.push_back(toCodeAction(TR, File, Selection));
1090 
1091     // If there's exactly one quick-fix, call it "preferred".
1092     // We never consider refactorings etc as preferred.
1093     CodeAction *OnlyFix = nullptr;
1094     for (auto &Action : CAs) {
1095       if (Action.kind && *Action.kind == CodeAction::QUICKFIX_KIND) {
1096         if (OnlyFix) {
1097           OnlyFix = nullptr;
1098           break;
1099         }
1100         OnlyFix = &Action;
1101       }
1102     }
1103     if (OnlyFix) {
1104       OnlyFix->isPreferred = true;
1105       if (ToLSPDiags.size() == 1 &&
1106           ToLSPDiags.begin()->second.range == Selection)
1107         OnlyFix->diagnostics = {ToLSPDiags.begin()->second};
1108     }
1109 
1110     if (SupportsCodeAction)
1111       return Reply(llvm::json::Array(CAs));
1112     std::vector<Command> Commands;
1113     for (const auto &Action : CAs) {
1114       if (auto Command = asCommand(Action))
1115         Commands.push_back(std::move(*Command));
1116     }
1117     return Reply(llvm::json::Array(Commands));
1118   };
1119   Server->codeAction(Inputs, std::move(CB));
1120 }
1121 
1122 void ClangdLSPServer::onCompletion(const CompletionParams &Params,
1123                                    Callback<CompletionList> Reply) {
1124   if (!shouldRunCompletion(Params)) {
1125     // Clients sometimes auto-trigger completions in undesired places (e.g.
1126     // 'a >^ '), we return empty results in those cases.
1127     vlog("ignored auto-triggered completion, preceding char did not match");
1128     return Reply(CompletionList());
1129   }
1130   auto Opts = this->Opts.CodeComplete;
1131   if (Params.limit && *Params.limit >= 0)
1132     Opts.Limit = *Params.limit;
1133   Server->codeComplete(Params.textDocument.uri.file(), Params.position, Opts,
1134                        [Reply = std::move(Reply), Opts,
1135                         this](llvm::Expected<CodeCompleteResult> List) mutable {
1136                          if (!List)
1137                            return Reply(List.takeError());
1138                          CompletionList LSPList;
1139                          LSPList.isIncomplete = List->HasMore;
1140                          for (const auto &R : List->Completions) {
1141                            CompletionItem C = R.render(Opts);
1142                            C.kind = adjustKindToCapability(
1143                                C.kind, SupportedCompletionItemKinds);
1144                            if (!SupportsCompletionLabelDetails)
1145                              removeCompletionLabelDetails(C);
1146                            LSPList.items.push_back(std::move(C));
1147                          }
1148                          return Reply(std::move(LSPList));
1149                        });
1150 }
1151 
1152 void ClangdLSPServer::onSignatureHelp(const TextDocumentPositionParams &Params,
1153                                       Callback<SignatureHelp> Reply) {
1154   Server->signatureHelp(Params.textDocument.uri.file(), Params.position,
1155                         Opts.SignatureHelpDocumentationFormat,
1156                         [Reply = std::move(Reply), this](
1157                             llvm::Expected<SignatureHelp> Signature) mutable {
1158                           if (!Signature)
1159                             return Reply(Signature.takeError());
1160                           if (SupportsOffsetsInSignatureHelp)
1161                             return Reply(std::move(*Signature));
1162                           // Strip out the offsets from signature help for
1163                           // clients that only support string labels.
1164                           for (auto &SigInfo : Signature->signatures) {
1165                             for (auto &Param : SigInfo.parameters)
1166                               Param.labelOffsets.reset();
1167                           }
1168                           return Reply(std::move(*Signature));
1169                         });
1170 }
1171 
1172 // Go to definition has a toggle function: if def and decl are distinct, then
1173 // the first press gives you the def, the second gives you the matching def.
1174 // getToggle() returns the counterpart location that under the cursor.
1175 //
1176 // We return the toggled location alone (ignoring other symbols) to encourage
1177 // editors to "bounce" quickly between locations, without showing a menu.
1178 static Location *getToggle(const TextDocumentPositionParams &Point,
1179                            LocatedSymbol &Sym) {
1180   // Toggle only makes sense with two distinct locations.
1181   if (!Sym.Definition || *Sym.Definition == Sym.PreferredDeclaration)
1182     return nullptr;
1183   if (Sym.Definition->uri.file() == Point.textDocument.uri.file() &&
1184       Sym.Definition->range.contains(Point.position))
1185     return &Sym.PreferredDeclaration;
1186   if (Sym.PreferredDeclaration.uri.file() == Point.textDocument.uri.file() &&
1187       Sym.PreferredDeclaration.range.contains(Point.position))
1188     return &*Sym.Definition;
1189   return nullptr;
1190 }
1191 
1192 void ClangdLSPServer::onGoToDefinition(const TextDocumentPositionParams &Params,
1193                                        Callback<std::vector<Location>> Reply) {
1194   Server->locateSymbolAt(
1195       Params.textDocument.uri.file(), Params.position,
1196       [Params, Reply = std::move(Reply)](
1197           llvm::Expected<std::vector<LocatedSymbol>> Symbols) mutable {
1198         if (!Symbols)
1199           return Reply(Symbols.takeError());
1200         std::vector<Location> Defs;
1201         for (auto &S : *Symbols) {
1202           if (Location *Toggle = getToggle(Params, S))
1203             return Reply(std::vector<Location>{std::move(*Toggle)});
1204           Defs.push_back(S.Definition.value_or(S.PreferredDeclaration));
1205         }
1206         Reply(std::move(Defs));
1207       });
1208 }
1209 
1210 void ClangdLSPServer::onGoToDeclaration(
1211     const TextDocumentPositionParams &Params,
1212     Callback<std::vector<Location>> Reply) {
1213   Server->locateSymbolAt(
1214       Params.textDocument.uri.file(), Params.position,
1215       [Params, Reply = std::move(Reply)](
1216           llvm::Expected<std::vector<LocatedSymbol>> Symbols) mutable {
1217         if (!Symbols)
1218           return Reply(Symbols.takeError());
1219         std::vector<Location> Decls;
1220         for (auto &S : *Symbols) {
1221           if (Location *Toggle = getToggle(Params, S))
1222             return Reply(std::vector<Location>{std::move(*Toggle)});
1223           Decls.push_back(std::move(S.PreferredDeclaration));
1224         }
1225         Reply(std::move(Decls));
1226       });
1227 }
1228 
1229 void ClangdLSPServer::onSwitchSourceHeader(
1230     const TextDocumentIdentifier &Params,
1231     Callback<std::optional<URIForFile>> Reply) {
1232   Server->switchSourceHeader(
1233       Params.uri.file(),
1234       [Reply = std::move(Reply),
1235        Params](llvm::Expected<std::optional<clangd::Path>> Path) mutable {
1236         if (!Path)
1237           return Reply(Path.takeError());
1238         if (*Path)
1239           return Reply(URIForFile::canonicalize(**Path, Params.uri.file()));
1240         return Reply(std::nullopt);
1241       });
1242 }
1243 
1244 void ClangdLSPServer::onDocumentHighlight(
1245     const TextDocumentPositionParams &Params,
1246     Callback<std::vector<DocumentHighlight>> Reply) {
1247   Server->findDocumentHighlights(Params.textDocument.uri.file(),
1248                                  Params.position, std::move(Reply));
1249 }
1250 
1251 void ClangdLSPServer::onHover(const TextDocumentPositionParams &Params,
1252                               Callback<std::optional<Hover>> Reply) {
1253   Server->findHover(Params.textDocument.uri.file(), Params.position,
1254                     [Reply = std::move(Reply),
1255                      this](llvm::Expected<std::optional<HoverInfo>> H) mutable {
1256                       if (!H)
1257                         return Reply(H.takeError());
1258                       if (!*H)
1259                         return Reply(std::nullopt);
1260 
1261                       Hover R;
1262                       R.contents.kind = HoverContentFormat;
1263                       R.range = (*H)->SymRange;
1264                       switch (HoverContentFormat) {
1265                       case MarkupKind::PlainText:
1266                         R.contents.value = (*H)->present().asPlainText();
1267                         return Reply(std::move(R));
1268                       case MarkupKind::Markdown:
1269                         R.contents.value = (*H)->present().asMarkdown();
1270                         return Reply(std::move(R));
1271                       };
1272                       llvm_unreachable("unhandled MarkupKind");
1273                     });
1274 }
1275 
1276 // Our extension has a different representation on the wire than the standard.
1277 // https://clangd.llvm.org/extensions#type-hierarchy
1278 llvm::json::Value serializeTHIForExtension(TypeHierarchyItem THI) {
1279   llvm::json::Object Result{{
1280       {"name", std::move(THI.name)},
1281       {"kind", static_cast<int>(THI.kind)},
1282       {"uri", std::move(THI.uri)},
1283       {"range", THI.range},
1284       {"selectionRange", THI.selectionRange},
1285       {"data", std::move(THI.data)},
1286   }};
1287   if (THI.deprecated)
1288     Result["deprecated"] = THI.deprecated;
1289   if (THI.detail)
1290     Result["detail"] = std::move(*THI.detail);
1291 
1292   if (THI.parents) {
1293     llvm::json::Array Parents;
1294     for (auto &Parent : *THI.parents)
1295       Parents.emplace_back(serializeTHIForExtension(std::move(Parent)));
1296     Result["parents"] = std::move(Parents);
1297   }
1298 
1299   if (THI.children) {
1300     llvm::json::Array Children;
1301     for (auto &child : *THI.children)
1302       Children.emplace_back(serializeTHIForExtension(std::move(child)));
1303     Result["children"] = std::move(Children);
1304   }
1305   return Result;
1306 }
1307 
1308 void ClangdLSPServer::onTypeHierarchy(const TypeHierarchyPrepareParams &Params,
1309                                       Callback<llvm::json::Value> Reply) {
1310   auto Serialize =
1311       [Reply = std::move(Reply)](
1312           llvm::Expected<std::vector<TypeHierarchyItem>> Resp) mutable {
1313         if (!Resp) {
1314           Reply(Resp.takeError());
1315           return;
1316         }
1317         if (Resp->empty()) {
1318           Reply(nullptr);
1319           return;
1320         }
1321         Reply(serializeTHIForExtension(std::move(Resp->front())));
1322       };
1323   Server->typeHierarchy(Params.textDocument.uri.file(), Params.position,
1324                         Params.resolve, Params.direction, std::move(Serialize));
1325 }
1326 
1327 void ClangdLSPServer::onResolveTypeHierarchy(
1328     const ResolveTypeHierarchyItemParams &Params,
1329     Callback<llvm::json::Value> Reply) {
1330   auto Serialize =
1331       [Reply = std::move(Reply)](
1332           llvm::Expected<std::optional<TypeHierarchyItem>> Resp) mutable {
1333         if (!Resp) {
1334           Reply(Resp.takeError());
1335           return;
1336         }
1337         if (!*Resp) {
1338           Reply(std::move(*Resp));
1339           return;
1340         }
1341         Reply(serializeTHIForExtension(std::move(**Resp)));
1342       };
1343   Server->resolveTypeHierarchy(Params.item, Params.resolve, Params.direction,
1344                                std::move(Serialize));
1345 }
1346 
1347 void ClangdLSPServer::onPrepareTypeHierarchy(
1348     const TypeHierarchyPrepareParams &Params,
1349     Callback<std::vector<TypeHierarchyItem>> Reply) {
1350   Server->typeHierarchy(Params.textDocument.uri.file(), Params.position,
1351                         Params.resolve, Params.direction, std::move(Reply));
1352 }
1353 
1354 void ClangdLSPServer::onSuperTypes(
1355     const ResolveTypeHierarchyItemParams &Params,
1356     Callback<std::optional<std::vector<TypeHierarchyItem>>> Reply) {
1357   Server->superTypes(Params.item, std::move(Reply));
1358 }
1359 
1360 void ClangdLSPServer::onSubTypes(
1361     const ResolveTypeHierarchyItemParams &Params,
1362     Callback<std::vector<TypeHierarchyItem>> Reply) {
1363   Server->subTypes(Params.item, std::move(Reply));
1364 }
1365 
1366 void ClangdLSPServer::onPrepareCallHierarchy(
1367     const CallHierarchyPrepareParams &Params,
1368     Callback<std::vector<CallHierarchyItem>> Reply) {
1369   Server->prepareCallHierarchy(Params.textDocument.uri.file(), Params.position,
1370                                std::move(Reply));
1371 }
1372 
1373 void ClangdLSPServer::onCallHierarchyIncomingCalls(
1374     const CallHierarchyIncomingCallsParams &Params,
1375     Callback<std::vector<CallHierarchyIncomingCall>> Reply) {
1376   Server->incomingCalls(Params.item, std::move(Reply));
1377 }
1378 
1379 void ClangdLSPServer::onClangdInlayHints(const InlayHintsParams &Params,
1380                                          Callback<llvm::json::Value> Reply) {
1381   // Our extension has a different representation on the wire than the standard.
1382   // We have a "range" property and "kind" is represented as a string, not as an
1383   // enum value.
1384   // https://clangd.llvm.org/extensions#inlay-hints
1385   auto Serialize = [Reply = std::move(Reply)](
1386                        llvm::Expected<std::vector<InlayHint>> Hints) mutable {
1387     if (!Hints) {
1388       Reply(Hints.takeError());
1389       return;
1390     }
1391     llvm::json::Array Result;
1392     Result.reserve(Hints->size());
1393     for (auto &Hint : *Hints) {
1394       Result.emplace_back(llvm::json::Object{
1395           {"kind", llvm::to_string(Hint.kind)},
1396           {"range", Hint.range},
1397           {"position", Hint.position},
1398           // Extension doesn't have paddingLeft/Right so adjust the label
1399           // accordingly.
1400           {"label",
1401            ((Hint.paddingLeft ? " " : "") + llvm::StringRef(Hint.joinLabels()) +
1402             (Hint.paddingRight ? " " : ""))
1403                .str()},
1404       });
1405     }
1406     Reply(std::move(Result));
1407   };
1408   Server->inlayHints(Params.textDocument.uri.file(), Params.range,
1409                      std::move(Serialize));
1410 }
1411 
1412 void ClangdLSPServer::onInlayHint(const InlayHintsParams &Params,
1413                                   Callback<std::vector<InlayHint>> Reply) {
1414   Server->inlayHints(Params.textDocument.uri.file(), Params.range,
1415                      std::move(Reply));
1416 }
1417 
1418 void ClangdLSPServer::onCallHierarchyOutgoingCalls(
1419     const CallHierarchyOutgoingCallsParams &Params,
1420     Callback<std::vector<CallHierarchyOutgoingCall>> Reply) {
1421   Server->outgoingCalls(Params.item, std::move(Reply));
1422 }
1423 
1424 void ClangdLSPServer::applyConfiguration(
1425     const ConfigurationSettings &Settings) {
1426   // Per-file update to the compilation database.
1427   llvm::StringSet<> ModifiedFiles;
1428   for (auto &[File, Command] : Settings.compilationDatabaseChanges) {
1429     auto Cmd =
1430         tooling::CompileCommand(std::move(Command.workingDirectory), File,
1431                                 std::move(Command.compilationCommand),
1432                                 /*Output=*/"");
1433     if (CDB->setCompileCommand(File, std::move(Cmd))) {
1434       ModifiedFiles.insert(File);
1435     }
1436   }
1437 
1438   Server->reparseOpenFilesIfNeeded(
1439       [&](llvm::StringRef File) { return ModifiedFiles.count(File) != 0; });
1440 }
1441 
1442 void ClangdLSPServer::maybeExportMemoryProfile() {
1443   if (!trace::enabled() || !ShouldProfile())
1444     return;
1445 
1446   static constexpr trace::Metric MemoryUsage(
1447       "memory_usage", trace::Metric::Value, "component_name");
1448   trace::Span Tracer("ProfileBrief");
1449   MemoryTree MT;
1450   profile(MT);
1451   record(MT, "clangd_lsp_server", MemoryUsage);
1452 }
1453 
1454 void ClangdLSPServer::maybeCleanupMemory() {
1455   if (!Opts.MemoryCleanup || !ShouldCleanupMemory())
1456     return;
1457   Opts.MemoryCleanup();
1458 }
1459 
1460 // FIXME: This function needs to be properly tested.
1461 void ClangdLSPServer::onChangeConfiguration(
1462     const DidChangeConfigurationParams &Params) {
1463   applyConfiguration(Params.settings);
1464 }
1465 
1466 void ClangdLSPServer::onReference(
1467     const ReferenceParams &Params,
1468     Callback<std::vector<ReferenceLocation>> Reply) {
1469   Server->findReferences(Params.textDocument.uri.file(), Params.position,
1470                          Opts.ReferencesLimit, SupportsReferenceContainer,
1471                          [Reply = std::move(Reply),
1472                           IncludeDecl(Params.context.includeDeclaration)](
1473                              llvm::Expected<ReferencesResult> Refs) mutable {
1474                            if (!Refs)
1475                              return Reply(Refs.takeError());
1476                            // Filter out declarations if the client asked.
1477                            std::vector<ReferenceLocation> Result;
1478                            Result.reserve(Refs->References.size());
1479                            for (auto &Ref : Refs->References) {
1480                              bool IsDecl =
1481                                  Ref.Attributes & ReferencesResult::Declaration;
1482                              if (IncludeDecl || !IsDecl)
1483                                Result.push_back(std::move(Ref.Loc));
1484                            }
1485                            return Reply(std::move(Result));
1486                          });
1487 }
1488 
1489 void ClangdLSPServer::onGoToType(const TextDocumentPositionParams &Params,
1490                                  Callback<std::vector<Location>> Reply) {
1491   Server->findType(
1492       Params.textDocument.uri.file(), Params.position,
1493       [Reply = std::move(Reply)](
1494           llvm::Expected<std::vector<LocatedSymbol>> Types) mutable {
1495         if (!Types)
1496           return Reply(Types.takeError());
1497         std::vector<Location> Response;
1498         for (const LocatedSymbol &Sym : *Types)
1499           Response.push_back(Sym.Definition.value_or(Sym.PreferredDeclaration));
1500         return Reply(std::move(Response));
1501       });
1502 }
1503 
1504 void ClangdLSPServer::onGoToImplementation(
1505     const TextDocumentPositionParams &Params,
1506     Callback<std::vector<Location>> Reply) {
1507   Server->findImplementations(
1508       Params.textDocument.uri.file(), Params.position,
1509       [Reply = std::move(Reply)](
1510           llvm::Expected<std::vector<LocatedSymbol>> Overrides) mutable {
1511         if (!Overrides)
1512           return Reply(Overrides.takeError());
1513         std::vector<Location> Impls;
1514         for (const LocatedSymbol &Sym : *Overrides)
1515           Impls.push_back(Sym.Definition.value_or(Sym.PreferredDeclaration));
1516         return Reply(std::move(Impls));
1517       });
1518 }
1519 
1520 void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
1521                                    Callback<std::vector<SymbolDetails>> Reply) {
1522   Server->symbolInfo(Params.textDocument.uri.file(), Params.position,
1523                      std::move(Reply));
1524 }
1525 
1526 void ClangdLSPServer::onSelectionRange(
1527     const SelectionRangeParams &Params,
1528     Callback<std::vector<SelectionRange>> Reply) {
1529   Server->semanticRanges(
1530       Params.textDocument.uri.file(), Params.positions,
1531       [Reply = std::move(Reply)](
1532           llvm::Expected<std::vector<SelectionRange>> Ranges) mutable {
1533         if (!Ranges)
1534           return Reply(Ranges.takeError());
1535         return Reply(std::move(*Ranges));
1536       });
1537 }
1538 
1539 void ClangdLSPServer::onDocumentLink(
1540     const DocumentLinkParams &Params,
1541     Callback<std::vector<DocumentLink>> Reply) {
1542 
1543   // TODO(forster): This currently resolves all targets eagerly. This is slow,
1544   // because it blocks on the preamble/AST being built. We could respond to the
1545   // request faster by using string matching or the lexer to find the includes
1546   // and resolving the targets lazily.
1547   Server->documentLinks(
1548       Params.textDocument.uri.file(),
1549       [Reply = std::move(Reply)](
1550           llvm::Expected<std::vector<DocumentLink>> Links) mutable {
1551         if (!Links) {
1552           return Reply(Links.takeError());
1553         }
1554         return Reply(std::move(Links));
1555       });
1556 }
1557 
1558 // Increment a numeric string: "" -> 1 -> 2 -> ... -> 9 -> 10 -> 11 ...
1559 static void increment(std::string &S) {
1560   for (char &C : llvm::reverse(S)) {
1561     if (C != '9') {
1562       ++C;
1563       return;
1564     }
1565     C = '0';
1566   }
1567   S.insert(S.begin(), '1');
1568 }
1569 
1570 void ClangdLSPServer::onSemanticTokens(const SemanticTokensParams &Params,
1571                                        Callback<SemanticTokens> CB) {
1572   auto File = Params.textDocument.uri.file();
1573   Server->semanticHighlights(
1574       Params.textDocument.uri.file(),
1575       [this, File(File.str()), CB(std::move(CB)), Code(Server->getDraft(File))](
1576           llvm::Expected<std::vector<HighlightingToken>> HT) mutable {
1577         if (!HT)
1578           return CB(HT.takeError());
1579         SemanticTokens Result;
1580         Result.tokens = toSemanticTokens(*HT, *Code);
1581         {
1582           std::lock_guard<std::mutex> Lock(SemanticTokensMutex);
1583           auto &Last = LastSemanticTokens[File];
1584 
1585           Last.tokens = Result.tokens;
1586           increment(Last.resultId);
1587           Result.resultId = Last.resultId;
1588         }
1589         CB(std::move(Result));
1590       });
1591 }
1592 
1593 void ClangdLSPServer::onSemanticTokensDelta(
1594     const SemanticTokensDeltaParams &Params,
1595     Callback<SemanticTokensOrDelta> CB) {
1596   auto File = Params.textDocument.uri.file();
1597   Server->semanticHighlights(
1598       Params.textDocument.uri.file(),
1599       [this, PrevResultID(Params.previousResultId), File(File.str()),
1600        CB(std::move(CB)), Code(Server->getDraft(File))](
1601           llvm::Expected<std::vector<HighlightingToken>> HT) mutable {
1602         if (!HT)
1603           return CB(HT.takeError());
1604         std::vector<SemanticToken> Toks = toSemanticTokens(*HT, *Code);
1605 
1606         SemanticTokensOrDelta Result;
1607         {
1608           std::lock_guard<std::mutex> Lock(SemanticTokensMutex);
1609           auto &Last = LastSemanticTokens[File];
1610 
1611           if (PrevResultID == Last.resultId) {
1612             Result.edits = diffTokens(Last.tokens, Toks);
1613           } else {
1614             vlog("semanticTokens/full/delta: wanted edits vs {0} but last "
1615                  "result had ID {1}. Returning full token list.",
1616                  PrevResultID, Last.resultId);
1617             Result.tokens = Toks;
1618           }
1619 
1620           Last.tokens = std::move(Toks);
1621           increment(Last.resultId);
1622           Result.resultId = Last.resultId;
1623         }
1624 
1625         CB(std::move(Result));
1626       });
1627 }
1628 
1629 void ClangdLSPServer::onMemoryUsage(const NoParams &,
1630                                     Callback<MemoryTree> Reply) {
1631   llvm::BumpPtrAllocator DetailAlloc;
1632   MemoryTree MT(&DetailAlloc);
1633   profile(MT);
1634   Reply(std::move(MT));
1635 }
1636 
1637 void ClangdLSPServer::onAST(const ASTParams &Params,
1638                             Callback<std::optional<ASTNode>> CB) {
1639   Server->getAST(Params.textDocument.uri.file(), Params.range, std::move(CB));
1640 }
1641 
1642 ClangdLSPServer::ClangdLSPServer(Transport &Transp, const ThreadsafeFS &TFS,
1643                                  const ClangdLSPServer::Options &Opts)
1644     : ShouldProfile(/*Period=*/std::chrono::minutes(5),
1645                     /*Delay=*/std::chrono::minutes(1)),
1646       ShouldCleanupMemory(/*Period=*/std::chrono::minutes(1),
1647                           /*Delay=*/std::chrono::minutes(1)),
1648       BackgroundContext(Context::current().clone()), Transp(Transp),
1649       MsgHandler(new MessageHandler(*this)), TFS(TFS),
1650       SupportedSymbolKinds(defaultSymbolKinds()),
1651       SupportedCompletionItemKinds(defaultCompletionItemKinds()), Opts(Opts) {
1652   if (Opts.ConfigProvider) {
1653     assert(!Opts.ContextProvider &&
1654            "Only one of ConfigProvider and ContextProvider allowed!");
1655     this->Opts.ContextProvider = ClangdServer::createConfiguredContextProvider(
1656         Opts.ConfigProvider, this);
1657   }
1658   LSPBinder Bind(this->Handlers, *this);
1659   Bind.method("initialize", this, &ClangdLSPServer::onInitialize);
1660 }
1661 
1662 void ClangdLSPServer::bindMethods(LSPBinder &Bind,
1663                                   const ClientCapabilities &Caps) {
1664   // clang-format off
1665   Bind.notification("initialized", this, &ClangdLSPServer::onInitialized);
1666   Bind.method("shutdown", this, &ClangdLSPServer::onShutdown);
1667   Bind.method("sync", this, &ClangdLSPServer::onSync);
1668   Bind.method("textDocument/rangeFormatting", this, &ClangdLSPServer::onDocumentRangeFormatting);
1669   Bind.method("textDocument/onTypeFormatting", this, &ClangdLSPServer::onDocumentOnTypeFormatting);
1670   Bind.method("textDocument/formatting", this, &ClangdLSPServer::onDocumentFormatting);
1671   Bind.method("textDocument/codeAction", this, &ClangdLSPServer::onCodeAction);
1672   Bind.method("textDocument/completion", this, &ClangdLSPServer::onCompletion);
1673   Bind.method("textDocument/signatureHelp", this, &ClangdLSPServer::onSignatureHelp);
1674   Bind.method("textDocument/definition", this, &ClangdLSPServer::onGoToDefinition);
1675   Bind.method("textDocument/declaration", this, &ClangdLSPServer::onGoToDeclaration);
1676   Bind.method("textDocument/typeDefinition", this, &ClangdLSPServer::onGoToType);
1677   Bind.method("textDocument/implementation", this, &ClangdLSPServer::onGoToImplementation);
1678   Bind.method("textDocument/references", this, &ClangdLSPServer::onReference);
1679   Bind.method("textDocument/switchSourceHeader", this, &ClangdLSPServer::onSwitchSourceHeader);
1680   Bind.method("textDocument/prepareRename", this, &ClangdLSPServer::onPrepareRename);
1681   Bind.method("textDocument/rename", this, &ClangdLSPServer::onRename);
1682   Bind.method("textDocument/hover", this, &ClangdLSPServer::onHover);
1683   Bind.method("textDocument/documentSymbol", this, &ClangdLSPServer::onDocumentSymbol);
1684   Bind.method("workspace/executeCommand", this, &ClangdLSPServer::onCommand);
1685   Bind.method("textDocument/documentHighlight", this, &ClangdLSPServer::onDocumentHighlight);
1686   Bind.method("workspace/symbol", this, &ClangdLSPServer::onWorkspaceSymbol);
1687   Bind.method("textDocument/ast", this, &ClangdLSPServer::onAST);
1688   Bind.notification("textDocument/didOpen", this, &ClangdLSPServer::onDocumentDidOpen);
1689   Bind.notification("textDocument/didClose", this, &ClangdLSPServer::onDocumentDidClose);
1690   Bind.notification("textDocument/didChange", this, &ClangdLSPServer::onDocumentDidChange);
1691   Bind.notification("textDocument/didSave", this, &ClangdLSPServer::onDocumentDidSave);
1692   Bind.notification("workspace/didChangeWatchedFiles", this, &ClangdLSPServer::onFileEvent);
1693   Bind.notification("workspace/didChangeConfiguration", this, &ClangdLSPServer::onChangeConfiguration);
1694   Bind.method("textDocument/symbolInfo", this, &ClangdLSPServer::onSymbolInfo);
1695   Bind.method("textDocument/typeHierarchy", this, &ClangdLSPServer::onTypeHierarchy);
1696   Bind.method("typeHierarchy/resolve", this, &ClangdLSPServer::onResolveTypeHierarchy);
1697   Bind.method("textDocument/prepareTypeHierarchy", this, &ClangdLSPServer::onPrepareTypeHierarchy);
1698   Bind.method("typeHierarchy/supertypes", this, &ClangdLSPServer::onSuperTypes);
1699   Bind.method("typeHierarchy/subtypes", this, &ClangdLSPServer::onSubTypes);
1700   Bind.method("textDocument/prepareCallHierarchy", this, &ClangdLSPServer::onPrepareCallHierarchy);
1701   Bind.method("callHierarchy/incomingCalls", this, &ClangdLSPServer::onCallHierarchyIncomingCalls);
1702   if (Opts.EnableOutgoingCalls)
1703     Bind.method("callHierarchy/outgoingCalls", this, &ClangdLSPServer::onCallHierarchyOutgoingCalls);
1704   Bind.method("textDocument/selectionRange", this, &ClangdLSPServer::onSelectionRange);
1705   Bind.method("textDocument/documentLink", this, &ClangdLSPServer::onDocumentLink);
1706   Bind.method("textDocument/semanticTokens/full", this, &ClangdLSPServer::onSemanticTokens);
1707   Bind.method("textDocument/semanticTokens/full/delta", this, &ClangdLSPServer::onSemanticTokensDelta);
1708   Bind.method("clangd/inlayHints", this, &ClangdLSPServer::onClangdInlayHints);
1709   Bind.method("textDocument/inlayHint", this, &ClangdLSPServer::onInlayHint);
1710   Bind.method("$/memoryUsage", this, &ClangdLSPServer::onMemoryUsage);
1711   Bind.method("textDocument/foldingRange", this, &ClangdLSPServer::onFoldingRange);
1712   Bind.command(ApplyFixCommand, this, &ClangdLSPServer::onCommandApplyEdit);
1713   Bind.command(ApplyTweakCommand, this, &ClangdLSPServer::onCommandApplyTweak);
1714   Bind.command(ApplyRenameCommand, this, &ClangdLSPServer::onCommandApplyRename);
1715 
1716   ApplyWorkspaceEdit = Bind.outgoingMethod("workspace/applyEdit");
1717   PublishDiagnostics = Bind.outgoingNotification("textDocument/publishDiagnostics");
1718   if (Caps.InactiveRegions)
1719     PublishInactiveRegions = Bind.outgoingNotification("textDocument/inactiveRegions");
1720   ShowMessage = Bind.outgoingNotification("window/showMessage");
1721   NotifyFileStatus = Bind.outgoingNotification("textDocument/clangd.fileStatus");
1722   CreateWorkDoneProgress = Bind.outgoingMethod("window/workDoneProgress/create");
1723   BeginWorkDoneProgress = Bind.outgoingNotification("$/progress");
1724   ReportWorkDoneProgress = Bind.outgoingNotification("$/progress");
1725   EndWorkDoneProgress = Bind.outgoingNotification("$/progress");
1726   if(Caps.SemanticTokenRefreshSupport)
1727     SemanticTokensRefresh = Bind.outgoingMethod("workspace/semanticTokens/refresh");
1728   // clang-format on
1729 }
1730 
1731 ClangdLSPServer::~ClangdLSPServer() {
1732   IsBeingDestroyed = true;
1733   // Explicitly destroy ClangdServer first, blocking on threads it owns.
1734   // This ensures they don't access any other members.
1735   Server.reset();
1736 }
1737 
1738 bool ClangdLSPServer::run() {
1739   // Run the Language Server loop.
1740   bool CleanExit = true;
1741   if (auto Err = Transp.loop(*MsgHandler)) {
1742     elog("Transport error: {0}", std::move(Err));
1743     CleanExit = false;
1744   }
1745 
1746   return CleanExit && ShutdownRequestReceived;
1747 }
1748 
1749 void ClangdLSPServer::profile(MemoryTree &MT) const {
1750   if (Server)
1751     Server->profile(MT.child("clangd_server"));
1752 }
1753 
1754 std::optional<ClangdServer::DiagRef>
1755 ClangdLSPServer::getDiagRef(StringRef File, const clangd::Diagnostic &D) {
1756   std::lock_guard<std::mutex> Lock(DiagRefMutex);
1757   auto DiagToDiagRefIter = DiagRefMap.find(File);
1758   if (DiagToDiagRefIter == DiagRefMap.end())
1759     return std::nullopt;
1760 
1761   const auto &DiagToDiagRefMap = DiagToDiagRefIter->second;
1762   auto FixItsIter = DiagToDiagRefMap.find(toDiagKey(D));
1763   if (FixItsIter == DiagToDiagRefMap.end())
1764     return std::nullopt;
1765 
1766   return FixItsIter->second;
1767 }
1768 
1769 // A completion request is sent when the user types '>' or ':', but we only
1770 // want to trigger on '->' and '::'. We check the preceding text to make
1771 // sure it matches what we expected.
1772 // Running the lexer here would be more robust (e.g. we can detect comments
1773 // and avoid triggering completion there), but we choose to err on the side
1774 // of simplicity here.
1775 bool ClangdLSPServer::shouldRunCompletion(
1776     const CompletionParams &Params) const {
1777   if (Params.context.triggerKind != CompletionTriggerKind::TriggerCharacter)
1778     return true;
1779   auto Code = Server->getDraft(Params.textDocument.uri.file());
1780   if (!Code)
1781     return true; // completion code will log the error for untracked doc.
1782   auto Offset = positionToOffset(*Code, Params.position,
1783                                  /*AllowColumnsBeyondLineLength=*/false);
1784   if (!Offset) {
1785     vlog("could not convert position '{0}' to offset for file '{1}'",
1786          Params.position, Params.textDocument.uri.file());
1787     return true;
1788   }
1789   return allowImplicitCompletion(*Code, *Offset);
1790 }
1791 
1792 void ClangdLSPServer::onDiagnosticsReady(PathRef File, llvm::StringRef Version,
1793                                          llvm::ArrayRef<Diag> Diagnostics) {
1794   PublishDiagnosticsParams Notification;
1795   Notification.version = decodeVersion(Version);
1796   Notification.uri = URIForFile::canonicalize(File, /*TUPath=*/File);
1797   DiagnosticToDiagRefMap LocalDiagMap; // Temporary storage
1798   for (auto &Diag : Diagnostics) {
1799     toLSPDiags(Diag, Notification.uri, DiagOpts,
1800                [&](clangd::Diagnostic LSPDiag, llvm::ArrayRef<Fix> Fixes) {
1801                  if (DiagOpts.EmbedFixesInDiagnostics) {
1802                    std::vector<CodeAction> CodeActions;
1803                    for (const auto &Fix : Fixes)
1804                      CodeActions.push_back(toCodeAction(
1805                          Fix, Notification.uri, Notification.version,
1806                          SupportsDocumentChanges, SupportsChangeAnnotation));
1807                    LSPDiag.codeActions.emplace(std::move(CodeActions));
1808                    if (LSPDiag.codeActions->size() == 1)
1809                      LSPDiag.codeActions->front().isPreferred = true;
1810                  }
1811                  LocalDiagMap[toDiagKey(LSPDiag)] = {Diag.Range, Diag.Message};
1812                  Notification.diagnostics.push_back(std::move(LSPDiag));
1813                });
1814   }
1815 
1816   // Cache DiagRefMap
1817   {
1818     std::lock_guard<std::mutex> Lock(DiagRefMutex);
1819     DiagRefMap[File] = LocalDiagMap;
1820   }
1821 
1822   // Send a notification to the LSP client.
1823   PublishDiagnostics(Notification);
1824 }
1825 
1826 void ClangdLSPServer::onInactiveRegionsReady(
1827     PathRef File, std::vector<Range> InactiveRegions) {
1828   InactiveRegionsParams Notification;
1829   Notification.TextDocument = {URIForFile::canonicalize(File, /*TUPath=*/File)};
1830   Notification.InactiveRegions = std::move(InactiveRegions);
1831 
1832   PublishInactiveRegions(Notification);
1833 }
1834 
1835 void ClangdLSPServer::onBackgroundIndexProgress(
1836     const BackgroundQueue::Stats &Stats) {
1837   static const char ProgressToken[] = "backgroundIndexProgress";
1838 
1839   // The background index did some work, maybe we need to cleanup
1840   maybeCleanupMemory();
1841 
1842   std::lock_guard<std::mutex> Lock(BackgroundIndexProgressMutex);
1843 
1844   auto NotifyProgress = [this](const BackgroundQueue::Stats &Stats) {
1845     if (BackgroundIndexProgressState != BackgroundIndexProgress::Live) {
1846       WorkDoneProgressBegin Begin;
1847       Begin.percentage = true;
1848       Begin.title = "indexing";
1849       BeginWorkDoneProgress({ProgressToken, std::move(Begin)});
1850       BackgroundIndexProgressState = BackgroundIndexProgress::Live;
1851     }
1852 
1853     if (Stats.Completed < Stats.Enqueued) {
1854       assert(Stats.Enqueued > Stats.LastIdle);
1855       WorkDoneProgressReport Report;
1856       Report.percentage = 100 * (Stats.Completed - Stats.LastIdle) /
1857                           (Stats.Enqueued - Stats.LastIdle);
1858       Report.message =
1859           llvm::formatv("{0}/{1}", Stats.Completed - Stats.LastIdle,
1860                         Stats.Enqueued - Stats.LastIdle);
1861       ReportWorkDoneProgress({ProgressToken, std::move(Report)});
1862     } else {
1863       assert(Stats.Completed == Stats.Enqueued);
1864       EndWorkDoneProgress({ProgressToken, WorkDoneProgressEnd()});
1865       BackgroundIndexProgressState = BackgroundIndexProgress::Empty;
1866     }
1867   };
1868 
1869   switch (BackgroundIndexProgressState) {
1870   case BackgroundIndexProgress::Unsupported:
1871     return;
1872   case BackgroundIndexProgress::Creating:
1873     // Cache this update for when the progress bar is available.
1874     PendingBackgroundIndexProgress = Stats;
1875     return;
1876   case BackgroundIndexProgress::Empty: {
1877     if (BackgroundIndexSkipCreate) {
1878       NotifyProgress(Stats);
1879       break;
1880     }
1881     // Cache this update for when the progress bar is available.
1882     PendingBackgroundIndexProgress = Stats;
1883     BackgroundIndexProgressState = BackgroundIndexProgress::Creating;
1884     WorkDoneProgressCreateParams CreateRequest;
1885     CreateRequest.token = ProgressToken;
1886     CreateWorkDoneProgress(
1887         CreateRequest,
1888         [this, NotifyProgress](llvm::Expected<std::nullptr_t> E) {
1889           std::lock_guard<std::mutex> Lock(BackgroundIndexProgressMutex);
1890           if (E) {
1891             NotifyProgress(this->PendingBackgroundIndexProgress);
1892           } else {
1893             elog("Failed to create background index progress bar: {0}",
1894                  E.takeError());
1895             // give up forever rather than thrashing about
1896             BackgroundIndexProgressState = BackgroundIndexProgress::Unsupported;
1897           }
1898         });
1899     break;
1900   }
1901   case BackgroundIndexProgress::Live:
1902     NotifyProgress(Stats);
1903     break;
1904   }
1905 }
1906 
1907 void ClangdLSPServer::onFileUpdated(PathRef File, const TUStatus &Status) {
1908   if (!SupportFileStatus)
1909     return;
1910   // FIXME: we don't emit "BuildingFile" and `RunningAction`, as these
1911   // two statuses are running faster in practice, which leads the UI constantly
1912   // changing, and doesn't provide much value. We may want to emit status at a
1913   // reasonable time interval (e.g. 0.5s).
1914   if (Status.PreambleActivity == PreambleAction::Idle &&
1915       (Status.ASTActivity.K == ASTAction::Building ||
1916        Status.ASTActivity.K == ASTAction::RunningAction))
1917     return;
1918   NotifyFileStatus(Status.render(File));
1919 }
1920 
1921 void ClangdLSPServer::onSemanticsMaybeChanged(PathRef File) {
1922   if (SemanticTokensRefresh) {
1923     SemanticTokensRefresh(NoParams{}, [](llvm::Expected<std::nullptr_t> E) {
1924       if (E)
1925         return;
1926       elog("Failed to refresh semantic tokens: {0}", E.takeError());
1927     });
1928   }
1929 }
1930 
1931 } // namespace clangd
1932 } // namespace clang
1933