[Reland][Runtimes] Merge 'compile_commands.json' files from runtimes build (#116303)
[llvm-project.git] / clang-tools-extra / clangd / ClangdLSPServer.h
blob0b8e4720f53236b270a47d514e2bd8ff70112662
1 //===--- ClangdLSPServer.h - 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 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H
12 #include "ClangdServer.h"
13 #include "Diagnostics.h"
14 #include "GlobalCompilationDatabase.h"
15 #include "LSPBinder.h"
16 #include "Protocol.h"
17 #include "Transport.h"
18 #include "support/Context.h"
19 #include "support/MemoryTree.h"
20 #include "support/Path.h"
21 #include "support/Threading.h"
22 #include "llvm/ADT/ArrayRef.h"
23 #include "llvm/Support/JSON.h"
24 #include <chrono>
25 #include <cstddef>
26 #include <cstdint>
27 #include <memory>
28 #include <optional>
29 #include <vector>
31 namespace clang {
32 namespace clangd {
34 /// This class exposes ClangdServer's capabilities via Language Server Protocol.
35 ///
36 /// MessageHandler binds the implemented LSP methods (e.g. onInitialize) to
37 /// corresponding JSON-RPC methods ("initialize").
38 /// The server also supports $/cancelRequest (MessageHandler provides this).
39 class ClangdLSPServer : private ClangdServer::Callbacks,
40 private LSPBinder::RawOutgoing {
41 public:
42 struct Options : ClangdServer::Options {
43 /// Supplies configuration (overrides ClangdServer::ContextProvider).
44 config::Provider *ConfigProvider = nullptr;
45 /// Look for compilation databases, rather than using compile commands
46 /// set via LSP (extensions) only.
47 bool UseDirBasedCDB = true;
48 /// The offset-encoding to use, or std::nullopt to negotiate it over LSP.
49 std::optional<OffsetEncoding> Encoding;
50 /// If set, periodically called to release memory.
51 /// Consider malloc_trim(3)
52 std::function<void()> MemoryCleanup = nullptr;
54 /// Per-feature options. Generally ClangdServer lets these vary
55 /// per-request, but LSP allows limited/no customizations.
56 clangd::CodeCompleteOptions CodeComplete;
57 MarkupKind SignatureHelpDocumentationFormat = MarkupKind::PlainText;
58 clangd::RenameOptions Rename;
59 /// Returns true if the tweak should be enabled.
60 std::function<bool(const Tweak &)> TweakFilter = [](const Tweak &T) {
61 return !T.hidden(); // only enable non-hidden tweaks.
64 /// Limit the number of references returned (0 means no limit).
65 size_t ReferencesLimit = 0;
67 /// Flag to hint the experimental modules support is enabled.
68 bool EnableExperimentalModulesSupport = false;
71 ClangdLSPServer(Transport &Transp, const ThreadsafeFS &TFS,
72 const ClangdLSPServer::Options &Opts);
73 /// The destructor blocks on any outstanding background tasks.
74 ~ClangdLSPServer();
76 /// Run LSP server loop, communicating with the Transport provided in the
77 /// constructor. This method must not be executed more than once.
78 ///
79 /// \return Whether we shut down cleanly with a 'shutdown' -> 'exit' sequence.
80 bool run();
82 /// Profiles resource-usage.
83 void profile(MemoryTree &MT) const;
85 private:
86 // Implement ClangdServer::Callbacks.
87 void onDiagnosticsReady(PathRef File, llvm::StringRef Version,
88 llvm::ArrayRef<Diag> Diagnostics) override;
89 void onFileUpdated(PathRef File, const TUStatus &Status) override;
90 void onBackgroundIndexProgress(const BackgroundQueue::Stats &Stats) override;
91 void onSemanticsMaybeChanged(PathRef File) override;
92 void onInactiveRegionsReady(PathRef File,
93 std::vector<Range> InactiveRegions) override;
95 // LSP methods. Notifications have signature void(const Params&).
96 // Calls have signature void(const Params&, Callback<Response>).
97 void onInitialize(const InitializeParams &, Callback<llvm::json::Value>);
98 void onInitialized(const InitializedParams &);
99 void onShutdown(const NoParams &, Callback<std::nullptr_t>);
100 void onSync(const NoParams &, Callback<std::nullptr_t>);
101 void onDocumentDidOpen(const DidOpenTextDocumentParams &);
102 void onDocumentDidChange(const DidChangeTextDocumentParams &);
103 void onDocumentDidClose(const DidCloseTextDocumentParams &);
104 void onDocumentDidSave(const DidSaveTextDocumentParams &);
105 void onAST(const ASTParams &, Callback<std::optional<ASTNode>>);
106 void onDocumentOnTypeFormatting(const DocumentOnTypeFormattingParams &,
107 Callback<std::vector<TextEdit>>);
108 void onDocumentRangeFormatting(const DocumentRangeFormattingParams &,
109 Callback<std::vector<TextEdit>>);
110 void onDocumentFormatting(const DocumentFormattingParams &,
111 Callback<std::vector<TextEdit>>);
112 // The results are serialized 'vector<DocumentSymbol>' if
113 // SupportsHierarchicalDocumentSymbol is true and 'vector<SymbolInformation>'
114 // otherwise.
115 void onDocumentSymbol(const DocumentSymbolParams &,
116 Callback<llvm::json::Value>);
117 void onFoldingRange(const FoldingRangeParams &,
118 Callback<std::vector<FoldingRange>>);
119 void onCodeAction(const CodeActionParams &, Callback<llvm::json::Value>);
120 void onCompletion(const CompletionParams &, Callback<CompletionList>);
121 void onSignatureHelp(const TextDocumentPositionParams &,
122 Callback<SignatureHelp>);
123 void onGoToDeclaration(const TextDocumentPositionParams &,
124 Callback<std::vector<Location>>);
125 void onGoToDefinition(const TextDocumentPositionParams &,
126 Callback<std::vector<Location>>);
127 void onGoToType(const TextDocumentPositionParams &,
128 Callback<std::vector<Location>>);
129 void onGoToImplementation(const TextDocumentPositionParams &,
130 Callback<std::vector<Location>>);
131 void onReference(const ReferenceParams &, Callback<std::vector<ReferenceLocation>>);
132 void onSwitchSourceHeader(const TextDocumentIdentifier &,
133 Callback<std::optional<URIForFile>>);
134 void onDocumentHighlight(const TextDocumentPositionParams &,
135 Callback<std::vector<DocumentHighlight>>);
136 void onFileEvent(const DidChangeWatchedFilesParams &);
137 void onWorkspaceSymbol(const WorkspaceSymbolParams &,
138 Callback<std::vector<SymbolInformation>>);
139 void onPrepareRename(const TextDocumentPositionParams &,
140 Callback<PrepareRenameResult>);
141 void onRename(const RenameParams &, Callback<WorkspaceEdit>);
142 void onHover(const TextDocumentPositionParams &,
143 Callback<std::optional<Hover>>);
144 void onPrepareTypeHierarchy(const TypeHierarchyPrepareParams &,
145 Callback<std::vector<TypeHierarchyItem>>);
146 void onSuperTypes(const ResolveTypeHierarchyItemParams &,
147 Callback<std::optional<std::vector<TypeHierarchyItem>>>);
148 void onSubTypes(const ResolveTypeHierarchyItemParams &,
149 Callback<std::vector<TypeHierarchyItem>>);
150 void onTypeHierarchy(const TypeHierarchyPrepareParams &,
151 Callback<llvm::json::Value>);
152 void onResolveTypeHierarchy(const ResolveTypeHierarchyItemParams &,
153 Callback<llvm::json::Value>);
154 void onPrepareCallHierarchy(const CallHierarchyPrepareParams &,
155 Callback<std::vector<CallHierarchyItem>>);
156 void onCallHierarchyIncomingCalls(
157 const CallHierarchyIncomingCallsParams &,
158 Callback<std::vector<CallHierarchyIncomingCall>>);
159 void onClangdInlayHints(const InlayHintsParams &,
160 Callback<llvm::json::Value>);
161 void onInlayHint(const InlayHintsParams &, Callback<std::vector<InlayHint>>);
162 void onChangeConfiguration(const DidChangeConfigurationParams &);
163 void onSymbolInfo(const TextDocumentPositionParams &,
164 Callback<std::vector<SymbolDetails>>);
165 void onSelectionRange(const SelectionRangeParams &,
166 Callback<std::vector<SelectionRange>>);
167 void onDocumentLink(const DocumentLinkParams &,
168 Callback<std::vector<DocumentLink>>);
169 void onSemanticTokens(const SemanticTokensParams &, Callback<SemanticTokens>);
170 void onSemanticTokensDelta(const SemanticTokensDeltaParams &,
171 Callback<SemanticTokensOrDelta>);
172 /// This is a clangd extension. Provides a json tree representing memory usage
173 /// hierarchy.
174 void onMemoryUsage(const NoParams &, Callback<MemoryTree>);
175 void onCommand(const ExecuteCommandParams &, Callback<llvm::json::Value>);
177 /// Implement commands.
178 void onCommandApplyEdit(const WorkspaceEdit &, Callback<llvm::json::Value>);
179 void onCommandApplyTweak(const TweakArgs &, Callback<llvm::json::Value>);
180 void onCommandApplyRename(const RenameParams &, Callback<llvm::json::Value>);
182 /// Outgoing LSP calls.
183 LSPBinder::OutgoingMethod<ApplyWorkspaceEditParams,
184 ApplyWorkspaceEditResponse>
185 ApplyWorkspaceEdit;
186 LSPBinder::OutgoingNotification<ShowMessageParams> ShowMessage;
187 LSPBinder::OutgoingNotification<PublishDiagnosticsParams> PublishDiagnostics;
188 LSPBinder::OutgoingNotification<FileStatus> NotifyFileStatus;
189 LSPBinder::OutgoingNotification<InactiveRegionsParams> PublishInactiveRegions;
190 LSPBinder::OutgoingMethod<WorkDoneProgressCreateParams, std::nullptr_t>
191 CreateWorkDoneProgress;
192 LSPBinder::OutgoingNotification<ProgressParams<WorkDoneProgressBegin>>
193 BeginWorkDoneProgress;
194 LSPBinder::OutgoingNotification<ProgressParams<WorkDoneProgressReport>>
195 ReportWorkDoneProgress;
196 LSPBinder::OutgoingNotification<ProgressParams<WorkDoneProgressEnd>>
197 EndWorkDoneProgress;
198 LSPBinder::OutgoingMethod<NoParams, std::nullptr_t> SemanticTokensRefresh;
200 void applyEdit(WorkspaceEdit WE, llvm::json::Value Success,
201 Callback<llvm::json::Value> Reply);
203 void bindMethods(LSPBinder &, const ClientCapabilities &Caps);
204 std::optional<ClangdServer::DiagRef> getDiagRef(StringRef File,
205 const clangd::Diagnostic &D);
207 /// Checks if completion request should be ignored. We need this due to the
208 /// limitation of the LSP. Per LSP, a client sends requests for all "trigger
209 /// character" we specify, but for '>' and ':' we need to check they actually
210 /// produce '->' and '::', respectively.
211 bool shouldRunCompletion(const CompletionParams &Params) const;
213 void applyConfiguration(const ConfigurationSettings &Settings);
215 /// Runs profiling and exports memory usage metrics if tracing is enabled and
216 /// profiling hasn't happened recently.
217 void maybeExportMemoryProfile();
218 PeriodicThrottler ShouldProfile;
220 /// Run the MemoryCleanup callback if it's time.
221 /// This method is thread safe.
222 void maybeCleanupMemory();
223 PeriodicThrottler ShouldCleanupMemory;
225 /// Since initialization of CDBs and ClangdServer is done lazily, the
226 /// following context captures the one used while creating ClangdLSPServer and
227 /// passes it to above mentioned object instances to make sure they share the
228 /// same state.
229 Context BackgroundContext;
231 /// Used to indicate that the 'shutdown' request was received from the
232 /// Language Server client.
233 bool ShutdownRequestReceived = false;
235 /// Used to indicate the ClangdLSPServer is being destroyed.
236 std::atomic<bool> IsBeingDestroyed = {false};
238 // FIXME: The caching is a temporary solution to get corresponding clangd
239 // diagnostic from a LSP diagnostic.
240 // Ideally, ClangdServer can generate an identifier for each diagnostic,
241 // emit them via the LSP's data field (which was newly added in LSP 3.16).
242 std::mutex DiagRefMutex;
243 struct DiagKey {
244 clangd::Range Rng;
245 std::string Message;
246 bool operator<(const DiagKey &Other) const {
247 return std::tie(Rng, Message) < std::tie(Other.Rng, Other.Message);
250 DiagKey toDiagKey(const clangd::Diagnostic &LSPDiag) {
251 return {LSPDiag.range, LSPDiag.message};
253 /// A map from LSP diagnostic to clangd-naive diagnostic.
254 typedef std::map<DiagKey, ClangdServer::DiagRef>
255 DiagnosticToDiagRefMap;
256 /// Caches the mapping LSP and clangd-naive diagnostics per file.
257 llvm::StringMap<DiagnosticToDiagRefMap>
258 DiagRefMap;
260 // Last semantic-tokens response, for incremental requests.
261 std::mutex SemanticTokensMutex;
262 llvm::StringMap<SemanticTokens> LastSemanticTokens;
264 // Most code should not deal with Transport, callMethod, notify directly.
265 // Use LSPBinder to handle incoming and outgoing calls.
266 clangd::Transport &Transp;
267 class MessageHandler;
268 std::unique_ptr<MessageHandler> MsgHandler;
269 std::mutex TranspWriter;
271 void callMethod(StringRef Method, llvm::json::Value Params,
272 Callback<llvm::json::Value> CB) override;
273 void notify(StringRef Method, llvm::json::Value Params) override;
275 LSPBinder::RawHandlers Handlers;
277 const ThreadsafeFS &TFS;
278 /// Options used for diagnostics.
279 ClangdDiagnosticOptions DiagOpts;
280 /// The supported kinds of the client.
281 SymbolKindBitset SupportedSymbolKinds;
282 /// The supported completion item kinds of the client.
283 CompletionItemKindBitset SupportedCompletionItemKinds;
284 // Whether the client supports CompletionItem.labelDetails.
285 bool SupportsCompletionLabelDetails = false;
286 /// Whether the client supports CodeAction response objects.
287 bool SupportsCodeAction = false;
288 /// From capabilities of textDocument/documentSymbol.
289 bool SupportsHierarchicalDocumentSymbol = false;
290 /// Whether the client supports showing file status.
291 bool SupportFileStatus = false;
292 /// Whether the client supports attaching a container string to references.
293 bool SupportsReferenceContainer = false;
294 /// Which kind of markup should we use in textDocument/hover responses.
295 MarkupKind HoverContentFormat = MarkupKind::PlainText;
296 /// Whether the client supports offsets for parameter info labels.
297 bool SupportsOffsetsInSignatureHelp = false;
298 /// Whether the client supports the versioned document changes.
299 bool SupportsDocumentChanges = false;
300 /// Whether the client supports change annotations on text edits.
301 bool SupportsChangeAnnotation = false;
303 std::mutex BackgroundIndexProgressMutex;
304 enum class BackgroundIndexProgress {
305 // Client doesn't support reporting progress. No transitions possible.
306 Unsupported,
307 // The queue is idle, and the client has no progress bar.
308 // Can transition to Creating when we have some activity.
309 Empty,
310 // We've requested the client to create a progress bar.
311 // Meanwhile, the state is buffered in PendingBackgroundIndexProgress.
312 Creating,
313 // The client has a progress bar, and we can send it updates immediately.
314 Live,
315 } BackgroundIndexProgressState = BackgroundIndexProgress::Unsupported;
316 // The progress to send when the progress bar is created.
317 // Only valid in state Creating.
318 BackgroundQueue::Stats PendingBackgroundIndexProgress;
319 /// LSP extension: skip WorkDoneProgressCreate, just send progress streams.
320 bool BackgroundIndexSkipCreate = false;
322 Options Opts;
323 // The CDB is created by the "initialize" LSP method.
324 std::unique_ptr<GlobalCompilationDatabase> BaseCDB;
325 // CDB is BaseCDB plus any commands overridden via LSP extensions.
326 std::optional<OverlayCDB> CDB;
327 // The ClangdServer is created by the "initialize" LSP method.
328 std::optional<ClangdServer> Server;
329 // Manages to build module files.
330 std::optional<ModulesBuilder> ModulesManager;
332 } // namespace clangd
333 } // namespace clang
335 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H