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