[clang-tools-extra] Fix a link in ReleaseNotes.rst
[llvm-project.git] / clang-tools-extra / clangd / ClangdLSPServer.h
blob562f8e060161f091f1bb0656400853d81496f055
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 "GlobalCompilationDatabase.h"
14 #include "LSPBinder.h"
15 #include "Protocol.h"
16 #include "Transport.h"
17 #include "support/Context.h"
18 #include "support/MemoryTree.h"
19 #include "support/Path.h"
20 #include "support/Threading.h"
21 #include "llvm/ADT/Optional.h"
22 #include "llvm/Support/JSON.h"
23 #include <chrono>
24 #include <cstddef>
25 #include <memory>
27 namespace clang {
28 namespace clangd {
30 /// This class exposes ClangdServer's capabilities via Language Server Protocol.
31 ///
32 /// MessageHandler binds the implemented LSP methods (e.g. onInitialize) to
33 /// corresponding JSON-RPC methods ("initialize").
34 /// The server also supports $/cancelRequest (MessageHandler provides this).
35 class ClangdLSPServer : private ClangdServer::Callbacks,
36 private LSPBinder::RawOutgoing {
37 public:
38 struct Options : ClangdServer::Options {
39 /// Supplies configuration (overrides ClangdServer::ContextProvider).
40 config::Provider *ConfigProvider = nullptr;
41 /// Look for compilation databases, rather than using compile commands
42 /// set via LSP (extensions) only.
43 bool UseDirBasedCDB = true;
44 /// The offset-encoding to use, or None to negotiate it over LSP.
45 llvm::Optional<OffsetEncoding> Encoding;
46 /// If set, periodically called to release memory.
47 /// Consider malloc_trim(3)
48 std::function<void()> MemoryCleanup = nullptr;
50 /// Per-feature options. Generally ClangdServer lets these vary
51 /// per-request, but LSP allows limited/no customizations.
52 clangd::CodeCompleteOptions CodeComplete;
53 MarkupKind SignatureHelpDocumentationFormat = MarkupKind::PlainText;
54 clangd::RenameOptions Rename;
55 /// Returns true if the tweak should be enabled.
56 std::function<bool(const Tweak &)> TweakFilter = [](const Tweak &T) {
57 return !T.hidden(); // only enable non-hidden tweaks.
60 /// Limit the number of references returned (0 means no limit).
61 size_t ReferencesLimit = 0;
64 ClangdLSPServer(Transport &Transp, const ThreadsafeFS &TFS,
65 const ClangdLSPServer::Options &Opts);
66 /// The destructor blocks on any outstanding background tasks.
67 ~ClangdLSPServer();
69 /// Run LSP server loop, communicating with the Transport provided in the
70 /// constructor. This method must not be executed more than once.
71 ///
72 /// \return Whether we shut down cleanly with a 'shutdown' -> 'exit' sequence.
73 bool run();
75 /// Profiles resource-usage.
76 void profile(MemoryTree &MT) const;
78 private:
79 // Implement ClangdServer::Callbacks.
80 void onDiagnosticsReady(PathRef File, llvm::StringRef Version,
81 std::vector<Diag> Diagnostics) override;
82 void onFileUpdated(PathRef File, const TUStatus &Status) override;
83 void onBackgroundIndexProgress(const BackgroundQueue::Stats &Stats) override;
84 void onSemanticsMaybeChanged(PathRef File) override;
86 // LSP methods. Notifications have signature void(const Params&).
87 // Calls have signature void(const Params&, Callback<Response>).
88 void onInitialize(const InitializeParams &, Callback<llvm::json::Value>);
89 void onInitialized(const InitializedParams &);
90 void onShutdown(const NoParams &, Callback<std::nullptr_t>);
91 void onSync(const NoParams &, Callback<std::nullptr_t>);
92 void onDocumentDidOpen(const DidOpenTextDocumentParams &);
93 void onDocumentDidChange(const DidChangeTextDocumentParams &);
94 void onDocumentDidClose(const DidCloseTextDocumentParams &);
95 void onDocumentDidSave(const DidSaveTextDocumentParams &);
96 void onAST(const ASTParams &, Callback<llvm::Optional<ASTNode>>);
97 void onDocumentOnTypeFormatting(const DocumentOnTypeFormattingParams &,
98 Callback<std::vector<TextEdit>>);
99 void onDocumentRangeFormatting(const DocumentRangeFormattingParams &,
100 Callback<std::vector<TextEdit>>);
101 void onDocumentFormatting(const DocumentFormattingParams &,
102 Callback<std::vector<TextEdit>>);
103 // The results are serialized 'vector<DocumentSymbol>' if
104 // SupportsHierarchicalDocumentSymbol is true and 'vector<SymbolInformation>'
105 // otherwise.
106 void onDocumentSymbol(const DocumentSymbolParams &,
107 Callback<llvm::json::Value>);
108 void onFoldingRange(const FoldingRangeParams &,
109 Callback<std::vector<FoldingRange>>);
110 void onCodeAction(const CodeActionParams &, Callback<llvm::json::Value>);
111 void onCompletion(const CompletionParams &, Callback<CompletionList>);
112 void onSignatureHelp(const TextDocumentPositionParams &,
113 Callback<SignatureHelp>);
114 void onGoToDeclaration(const TextDocumentPositionParams &,
115 Callback<std::vector<Location>>);
116 void onGoToDefinition(const TextDocumentPositionParams &,
117 Callback<std::vector<Location>>);
118 void onGoToType(const TextDocumentPositionParams &,
119 Callback<std::vector<Location>>);
120 void onGoToImplementation(const TextDocumentPositionParams &,
121 Callback<std::vector<Location>>);
122 void onReference(const ReferenceParams &, Callback<std::vector<Location>>);
123 void onSwitchSourceHeader(const TextDocumentIdentifier &,
124 Callback<llvm::Optional<URIForFile>>);
125 void onDocumentHighlight(const TextDocumentPositionParams &,
126 Callback<std::vector<DocumentHighlight>>);
127 void onFileEvent(const DidChangeWatchedFilesParams &);
128 void onWorkspaceSymbol(const WorkspaceSymbolParams &,
129 Callback<std::vector<SymbolInformation>>);
130 void onPrepareRename(const TextDocumentPositionParams &,
131 Callback<llvm::Optional<Range>>);
132 void onRename(const RenameParams &, Callback<WorkspaceEdit>);
133 void onHover(const TextDocumentPositionParams &,
134 Callback<llvm::Optional<Hover>>);
135 void onTypeHierarchy(const TypeHierarchyParams &,
136 Callback<llvm::Optional<TypeHierarchyItem>>);
137 void onResolveTypeHierarchy(const ResolveTypeHierarchyItemParams &,
138 Callback<llvm::Optional<TypeHierarchyItem>>);
139 void onPrepareCallHierarchy(const CallHierarchyPrepareParams &,
140 Callback<std::vector<CallHierarchyItem>>);
141 void onCallHierarchyIncomingCalls(
142 const CallHierarchyIncomingCallsParams &,
143 Callback<std::vector<CallHierarchyIncomingCall>>);
144 void onCallHierarchyOutgoingCalls(
145 const CallHierarchyOutgoingCallsParams &,
146 Callback<std::vector<CallHierarchyOutgoingCall>>);
147 void onClangdInlayHints(const InlayHintsParams &,
148 Callback<llvm::json::Value>);
149 void onInlayHint(const InlayHintsParams &, Callback<std::vector<InlayHint>>);
150 void onChangeConfiguration(const DidChangeConfigurationParams &);
151 void onSymbolInfo(const TextDocumentPositionParams &,
152 Callback<std::vector<SymbolDetails>>);
153 void onSelectionRange(const SelectionRangeParams &,
154 Callback<std::vector<SelectionRange>>);
155 void onDocumentLink(const DocumentLinkParams &,
156 Callback<std::vector<DocumentLink>>);
157 void onSemanticTokens(const SemanticTokensParams &, Callback<SemanticTokens>);
158 void onSemanticTokensDelta(const SemanticTokensDeltaParams &,
159 Callback<SemanticTokensOrDelta>);
160 /// This is a clangd extension. Provides a json tree representing memory usage
161 /// hierarchy.
162 void onMemoryUsage(const NoParams &, Callback<MemoryTree>);
163 void onCommand(const ExecuteCommandParams &, Callback<llvm::json::Value>);
165 /// Implement commands.
166 void onCommandApplyEdit(const WorkspaceEdit &, Callback<llvm::json::Value>);
167 void onCommandApplyTweak(const TweakArgs &, Callback<llvm::json::Value>);
169 /// Outgoing LSP calls.
170 LSPBinder::OutgoingMethod<ApplyWorkspaceEditParams,
171 ApplyWorkspaceEditResponse>
172 ApplyWorkspaceEdit;
173 LSPBinder::OutgoingNotification<ShowMessageParams> ShowMessage;
174 LSPBinder::OutgoingNotification<PublishDiagnosticsParams> PublishDiagnostics;
175 LSPBinder::OutgoingNotification<FileStatus> NotifyFileStatus;
176 LSPBinder::OutgoingMethod<WorkDoneProgressCreateParams, std::nullptr_t>
177 CreateWorkDoneProgress;
178 LSPBinder::OutgoingNotification<ProgressParams<WorkDoneProgressBegin>>
179 BeginWorkDoneProgress;
180 LSPBinder::OutgoingNotification<ProgressParams<WorkDoneProgressReport>>
181 ReportWorkDoneProgress;
182 LSPBinder::OutgoingNotification<ProgressParams<WorkDoneProgressEnd>>
183 EndWorkDoneProgress;
184 LSPBinder::OutgoingMethod<NoParams, std::nullptr_t> SemanticTokensRefresh;
186 void applyEdit(WorkspaceEdit WE, llvm::json::Value Success,
187 Callback<llvm::json::Value> Reply);
189 void bindMethods(LSPBinder &, const ClientCapabilities &Caps);
190 std::vector<Fix> getFixes(StringRef File, const clangd::Diagnostic &D);
192 /// Checks if completion request should be ignored. We need this due to the
193 /// limitation of the LSP. Per LSP, a client sends requests for all "trigger
194 /// character" we specify, but for '>' and ':' we need to check they actually
195 /// produce '->' and '::', respectively.
196 bool shouldRunCompletion(const CompletionParams &Params) const;
198 void applyConfiguration(const ConfigurationSettings &Settings);
200 /// Runs profiling and exports memory usage metrics if tracing is enabled and
201 /// profiling hasn't happened recently.
202 void maybeExportMemoryProfile();
203 PeriodicThrottler ShouldProfile;
205 /// Run the MemoryCleanup callback if it's time.
206 /// This method is thread safe.
207 void maybeCleanupMemory();
208 PeriodicThrottler ShouldCleanupMemory;
210 /// Since initialization of CDBs and ClangdServer is done lazily, the
211 /// following context captures the one used while creating ClangdLSPServer and
212 /// passes it to above mentioned object instances to make sure they share the
213 /// same state.
214 Context BackgroundContext;
216 /// Used to indicate that the 'shutdown' request was received from the
217 /// Language Server client.
218 bool ShutdownRequestReceived = false;
220 /// Used to indicate the ClangdLSPServer is being destroyed.
221 std::atomic<bool> IsBeingDestroyed = {false};
223 std::mutex FixItsMutex;
224 typedef std::map<clangd::Diagnostic, std::vector<Fix>, LSPDiagnosticCompare>
225 DiagnosticToReplacementMap;
226 /// Caches FixIts per file and diagnostics
227 llvm::StringMap<DiagnosticToReplacementMap> FixItsMap;
228 // Last semantic-tokens response, for incremental requests.
229 std::mutex SemanticTokensMutex;
230 llvm::StringMap<SemanticTokens> LastSemanticTokens;
232 // Most code should not deal with Transport, callMethod, notify directly.
233 // Use LSPBinder to handle incoming and outgoing calls.
234 clangd::Transport &Transp;
235 class MessageHandler;
236 std::unique_ptr<MessageHandler> MsgHandler;
237 std::mutex TranspWriter;
239 void callMethod(StringRef Method, llvm::json::Value Params,
240 Callback<llvm::json::Value> CB) override;
241 void notify(StringRef Method, llvm::json::Value Params) override;
243 LSPBinder::RawHandlers Handlers;
245 const ThreadsafeFS &TFS;
246 /// Options used for diagnostics.
247 ClangdDiagnosticOptions DiagOpts;
248 /// The supported kinds of the client.
249 SymbolKindBitset SupportedSymbolKinds;
250 /// The supported completion item kinds of the client.
251 CompletionItemKindBitset SupportedCompletionItemKinds;
252 /// Whether the client supports CodeAction response objects.
253 bool SupportsCodeAction = false;
254 /// From capabilities of textDocument/documentSymbol.
255 bool SupportsHierarchicalDocumentSymbol = false;
256 /// Whether the client supports showing file status.
257 bool SupportFileStatus = false;
258 /// Which kind of markup should we use in textDocument/hover responses.
259 MarkupKind HoverContentFormat = MarkupKind::PlainText;
260 /// Whether the client supports offsets for parameter info labels.
261 bool SupportsOffsetsInSignatureHelp = false;
262 std::mutex BackgroundIndexProgressMutex;
263 enum class BackgroundIndexProgress {
264 // Client doesn't support reporting progress. No transitions possible.
265 Unsupported,
266 // The queue is idle, and the client has no progress bar.
267 // Can transition to Creating when we have some activity.
268 Empty,
269 // We've requested the client to create a progress bar.
270 // Meanwhile, the state is buffered in PendingBackgroundIndexProgress.
271 Creating,
272 // The client has a progress bar, and we can send it updates immediately.
273 Live,
274 } BackgroundIndexProgressState = BackgroundIndexProgress::Unsupported;
275 // The progress to send when the progress bar is created.
276 // Only valid in state Creating.
277 BackgroundQueue::Stats PendingBackgroundIndexProgress;
278 /// LSP extension: skip WorkDoneProgressCreate, just send progress streams.
279 bool BackgroundIndexSkipCreate = false;
281 Options Opts;
282 // The CDB is created by the "initialize" LSP method.
283 std::unique_ptr<GlobalCompilationDatabase> BaseCDB;
284 // CDB is BaseCDB plus any commands overridden via LSP extensions.
285 llvm::Optional<OverlayCDB> CDB;
286 // The ClangdServer is created by the "initialize" LSP method.
287 llvm::Optional<ClangdServer> Server;
289 } // namespace clangd
290 } // namespace clang
292 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H