clang-tools  11.0.0
ClangdLSPServer.h
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H
11 
12 #include "ClangdServer.h"
13 #include "DraftStore.h"
14 #include "Features.inc"
15 #include "FindSymbols.h"
17 #include "Protocol.h"
18 #include "Transport.h"
19 #include "support/Context.h"
20 #include "support/Path.h"
21 #include "clang/Tooling/Core/Replacement.h"
22 #include "llvm/ADT/Optional.h"
23 #include "llvm/ADT/StringSet.h"
24 #include "llvm/Support/JSON.h"
25 #include <memory>
26 
27 namespace clang {
28 namespace clangd {
29 
30 class SymbolIndex;
31 
32 /// This class exposes ClangdServer's capabilities via Language Server Protocol.
33 ///
34 /// MessageHandler binds the implemented LSP methods (e.g. onInitialize) to
35 /// corresponding JSON-RPC methods ("initialize").
36 /// The server also supports $/cancelRequest (MessageHandler provides this).
38 public:
39  /// If \p CompileCommandsDir has a value, compile_commands.json will be
40  /// loaded only from \p CompileCommandsDir. Otherwise, clangd will look
41  /// for compile_commands.json in all parent directories of each file.
42  /// If UseDirBasedCDB is false, compile commands are not read from disk.
43  // FIXME: Clean up signature around CDBs.
44  ClangdLSPServer(Transport &Transp, const ThreadsafeFS &TFS,
45  const clangd::CodeCompleteOptions &CCOpts,
46  const clangd::RenameOptions &RenameOpts,
47  llvm::Optional<Path> CompileCommandsDir, bool UseDirBasedCDB,
48  llvm::Optional<OffsetEncoding> ForcedOffsetEncoding,
49  const ClangdServer::Options &Opts);
50  /// The destructor blocks on any outstanding background tasks.
52 
53  /// Run LSP server loop, communicating with the Transport provided in the
54  /// constructor. This method must not be executed more than once.
55  ///
56  /// \return Whether we shut down cleanly with a 'shutdown' -> 'exit' sequence.
57  bool run();
58 
59 private:
60  // Implement ClangdServer::Callbacks.
61  void onDiagnosticsReady(PathRef File, llvm::StringRef Version,
62  std::vector<Diag> Diagnostics) override;
63  void onFileUpdated(PathRef File, const TUStatus &Status) override;
64  void
65  onHighlightingsReady(PathRef File, llvm::StringRef Version,
66  std::vector<HighlightingToken> Highlightings) override;
67  void onBackgroundIndexProgress(const BackgroundQueue::Stats &Stats) override;
68 
69  // LSP methods. Notifications have signature void(const Params&).
70  // Calls have signature void(const Params&, Callback<Response>).
71  void onInitialize(const InitializeParams &, Callback<llvm::json::Value>);
72  void onInitialized(const InitializedParams &);
73  void onShutdown(const ShutdownParams &, Callback<std::nullptr_t>);
74  void onSync(const NoParams &, Callback<std::nullptr_t>);
75  void onDocumentDidOpen(const DidOpenTextDocumentParams &);
76  void onDocumentDidChange(const DidChangeTextDocumentParams &);
77  void onDocumentDidClose(const DidCloseTextDocumentParams &);
78  void onDocumentDidSave(const DidSaveTextDocumentParams &);
79  void onDocumentOnTypeFormatting(const DocumentOnTypeFormattingParams &,
80  Callback<std::vector<TextEdit>>);
81  void onDocumentRangeFormatting(const DocumentRangeFormattingParams &,
82  Callback<std::vector<TextEdit>>);
83  void onDocumentFormatting(const DocumentFormattingParams &,
84  Callback<std::vector<TextEdit>>);
85  // The results are serialized 'vector<DocumentSymbol>' if
86  // SupportsHierarchicalDocumentSymbol is true and 'vector<SymbolInformation>'
87  // otherwise.
88  void onDocumentSymbol(const DocumentSymbolParams &,
90  void onFoldingRange(const FoldingRangeParams &,
91  Callback<std::vector<FoldingRange>>);
92  void onCodeAction(const CodeActionParams &, Callback<llvm::json::Value>);
93  void onCompletion(const CompletionParams &, Callback<CompletionList>);
94  void onSignatureHelp(const TextDocumentPositionParams &,
96  void onGoToDeclaration(const TextDocumentPositionParams &,
97  Callback<std::vector<Location>>);
98  void onGoToDefinition(const TextDocumentPositionParams &,
99  Callback<std::vector<Location>>);
100  void onReference(const ReferenceParams &, Callback<std::vector<Location>>);
101  void onSwitchSourceHeader(const TextDocumentIdentifier &,
102  Callback<llvm::Optional<URIForFile>>);
103  void onDocumentHighlight(const TextDocumentPositionParams &,
104  Callback<std::vector<DocumentHighlight>>);
105  void onFileEvent(const DidChangeWatchedFilesParams &);
106  void onCommand(const ExecuteCommandParams &, Callback<llvm::json::Value>);
107  void onWorkspaceSymbol(const WorkspaceSymbolParams &,
108  Callback<std::vector<SymbolInformation>>);
109  void onPrepareRename(const TextDocumentPositionParams &,
110  Callback<llvm::Optional<Range>>);
111  void onRename(const RenameParams &, Callback<WorkspaceEdit>);
112  void onHover(const TextDocumentPositionParams &,
113  Callback<llvm::Optional<Hover>>);
114  void onTypeHierarchy(const TypeHierarchyParams &,
115  Callback<llvm::Optional<TypeHierarchyItem>>);
116  void onResolveTypeHierarchy(const ResolveTypeHierarchyItemParams &,
117  Callback<llvm::Optional<TypeHierarchyItem>>);
118  void onChangeConfiguration(const DidChangeConfigurationParams &);
119  void onSymbolInfo(const TextDocumentPositionParams &,
120  Callback<std::vector<SymbolDetails>>);
121  void onSelectionRange(const SelectionRangeParams &,
122  Callback<std::vector<SelectionRange>>);
123  void onDocumentLink(const DocumentLinkParams &,
124  Callback<std::vector<DocumentLink>>);
125  void onSemanticTokens(const SemanticTokensParams &, Callback<SemanticTokens>);
126  void onSemanticTokensDelta(const SemanticTokensDeltaParams &,
128 
129  std::vector<Fix> getFixes(StringRef File, const clangd::Diagnostic &D);
130 
131  /// Checks if completion request should be ignored. We need this due to the
132  /// limitation of the LSP. Per LSP, a client sends requests for all "trigger
133  /// character" we specify, but for '>' and ':' we need to check they actually
134  /// produce '->' and '::', respectively.
135  bool shouldRunCompletion(const CompletionParams &Params) const;
136 
137  /// Requests a reparse of currently opened files using their latest source.
138  /// This will typically only rebuild if something other than the source has
139  /// changed (e.g. the CDB yields different flags, or files included in the
140  /// preamble have been modified).
141  void reparseOpenFilesIfNeeded(
142  llvm::function_ref<bool(llvm::StringRef File)> Filter);
143  void applyConfiguration(const ConfigurationSettings &Settings);
144 
145  /// Sends a "publishSemanticHighlighting" notification to the LSP client.
146  void
147  publishTheiaSemanticHighlighting(const TheiaSemanticHighlightingParams &);
148 
149  /// Sends a "publishDiagnostics" notification to the LSP client.
150  void publishDiagnostics(const PublishDiagnosticsParams &);
151 
152  /// Since initialization of CDBs and ClangdServer is done lazily, the
153  /// following context captures the one used while creating ClangdLSPServer and
154  /// passes it to above mentioned object instances to make sure they share the
155  /// same state.
156  Context BackgroundContext;
157 
158  /// Used to indicate that the 'shutdown' request was received from the
159  /// Language Server client.
160  bool ShutdownRequestReceived = false;
161 
162  /// Used to indicate the ClangdLSPServer is being destroyed.
163  std::atomic<bool> IsBeingDestroyed = {false};
164 
165  std::mutex FixItsMutex;
166  typedef std::map<clangd::Diagnostic, std::vector<Fix>, LSPDiagnosticCompare>
167  DiagnosticToReplacementMap;
168  /// Caches FixIts per file and diagnostics
169  llvm::StringMap<DiagnosticToReplacementMap> FixItsMap;
170  std::mutex HighlightingsMutex;
171  llvm::StringMap<std::vector<HighlightingToken>> FileToHighlightings;
172  // Last semantic-tokens response, for incremental requests.
173  std::mutex SemanticTokensMutex;
174  llvm::StringMap<SemanticTokens> LastSemanticTokens;
175 
176  // Most code should not deal with Transport directly.
177  // MessageHandler deals with incoming messages, use call() etc for outgoing.
178  clangd::Transport &Transp;
179  class MessageHandler;
180  std::unique_ptr<MessageHandler> MsgHandler;
181  std::mutex TranspWriter;
182 
183  template <typename Response>
184  void call(StringRef Method, llvm::json::Value Params, Callback<Response> CB) {
185  // Wrap the callback with LSP conversion and error-handling.
186  auto HandleReply =
187  [CB = std::move(CB), Ctx = Context::current().clone()](
188  llvm::Expected<llvm::json::Value> RawResponse) mutable {
189  Response Rsp;
190  if (!RawResponse) {
191  CB(RawResponse.takeError());
192  } else if (fromJSON(*RawResponse, Rsp)) {
193  CB(std::move(Rsp));
194  } else {
195  elog("Failed to decode {0} response", *RawResponse);
196  CB(llvm::make_error<LSPError>("failed to decode response",
198  }
199  };
200  callRaw(Method, std::move(Params), std::move(HandleReply));
201  }
202  void callRaw(StringRef Method, llvm::json::Value Params,
204  void notify(StringRef Method, llvm::json::Value Params);
205  template <typename T> void progress(const llvm::json::Value &Token, T Value) {
206  ProgressParams<T> Params;
207  Params.token = Token;
208  Params.value = std::move(Value);
209  notify("$/progress", Params);
210  }
211 
212  const ThreadsafeFS &TFS;
213  /// Options used for code completion
215  /// Options used for rename.
217  /// Options used for diagnostics.
218  ClangdDiagnosticOptions DiagOpts;
219  /// The supported kinds of the client.
220  SymbolKindBitset SupportedSymbolKinds;
221  /// The supported completion item kinds of the client.
222  CompletionItemKindBitset SupportedCompletionItemKinds;
223  /// Whether the client supports CodeAction response objects.
224  bool SupportsCodeAction = false;
225  /// From capabilities of textDocument/documentSymbol.
226  bool SupportsHierarchicalDocumentSymbol = false;
227  /// Whether the client supports showing file status.
228  bool SupportFileStatus = false;
229  /// Which kind of markup should we use in textDocument/hover responses.
230  MarkupKind HoverContentFormat = MarkupKind::PlainText;
231  /// Whether the client supports offsets for parameter info labels.
232  bool SupportsOffsetsInSignatureHelp = false;
233  std::mutex BackgroundIndexProgressMutex;
234  enum class BackgroundIndexProgress {
235  // Client doesn't support reporting progress. No transitions possible.
236  Unsupported,
237  // The queue is idle, and the client has no progress bar.
238  // Can transition to Creating when we have some activity.
239  Empty,
240  // We've requested the client to create a progress bar.
241  // Meanwhile, the state is buffered in PendingBackgroundIndexProgress.
242  Creating,
243  // The client has a progress bar, and we can send it updates immediately.
244  Live,
245  } BackgroundIndexProgressState = BackgroundIndexProgress::Unsupported;
246  // The progress to send when the progress bar is created.
247  // Only valid in state Creating.
248  BackgroundQueue::Stats PendingBackgroundIndexProgress;
249  /// LSP extension: skip WorkDoneProgressCreate, just send progress streams.
250  bool BackgroundIndexSkipCreate = false;
251  // Store of the current versions of the open documents.
252  DraftStore DraftMgr;
253 
254  // The CDB is created by the "initialize" LSP method.
255  bool UseDirBasedCDB; // FIXME: make this a capability.
256  llvm::Optional<Path> CompileCommandsDir; // FIXME: merge with capability?
257  std::unique_ptr<GlobalCompilationDatabase> BaseCDB;
258  // CDB is BaseCDB plus any commands overridden via LSP extensions.
259  llvm::Optional<OverlayCDB> CDB;
260  ClangdServer::Options ClangdServerOpts;
261  llvm::Optional<OffsetEncoding> NegotiatedOffsetEncoding;
262  // The ClangdServer is created by the "initialize" LSP method.
263  llvm::Optional<ClangdServer> Server;
264 };
265 } // namespace clangd
266 } // namespace clang
267 
268 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H
clang::clangd::DraftStore
A thread-safe container for files opened in a workspace, addressed by filenames.
Definition: DraftStore.h:28
clang::clangd::ClangdLSPServer::run
bool run()
Run LSP server loop, communicating with the Transport provided in the constructor.
Definition: ClangdLSPServer.cpp:1417
clang::clangd::BackgroundQueue::Stats
Definition: Background.h:82
CCOpts
CodeCompleteOptions CCOpts
Definition: ClangdLSPServerTests.cpp:67
clang::clangd::MarkupKind::PlainText
clang::clangd::SemanticTokensParams
Body of textDocument/semanticTokens/full request.
Definition: Protocol.h:1393
clang::clangd::SemanticTokensDeltaParams
Body of textDocument/semanticTokens/full/delta request.
Definition: Protocol.h:1401
Path.h
clang::clangd::Context::current
static const Context & current()
Returns the context for the current thread, creating it if needed.
Definition: Context.cpp:27
clang::clangd::Context::clone
Context clone() const
Clone this context object.
Definition: Context.cpp:20
clang::clangd::ProgressParams::value
T value
The progress data.
Definition: Protocol.h:555
clang::clangd::DidCloseTextDocumentParams
Definition: Protocol.h:655
Ctx
Context Ctx
Definition: TUScheduler.cpp:324
clang::clangd::ClangdDiagnosticOptions
Definition: Diagnostics.h:32
clang::clangd::FoldingRangeParams
Definition: Protocol.h:1515
DraftStore.h
FindSymbols.h
clang::clangd::InitializeParams
Definition: Protocol.h:512
clang::clangd::SymbolKindBitset
std::bitset< SymbolKindMax+1 > SymbolKindBitset
Definition: Protocol.h:352
clang::clangd::DocumentFormattingParams
Definition: Protocol.h:760
clang::clangd::DocumentSymbolParams
Definition: Protocol.h:766
clang::clangd::CompletionItemKindBitset
std::bitset< CompletionItemKindMax+1 > CompletionItemKindBitset
Definition: Protocol.h:314
clang::clangd::SelectionRangeParams
Definition: Protocol.h:1458
Protocol.h
clang::clangd::ClangdLSPServer
This class exposes ClangdServer's capabilities via Language Server Protocol.
Definition: ClangdLSPServer.h:37
clang::clangd::Diagnostic
Definition: Protocol.h:784
clang::clangd::ClangdServer::Options
Definition: ClangdServer.h:90
clang::clangd::TUStatus
Definition: TUScheduler.h:108
clang::clangd::ErrorCode::InvalidParams
GlobalCompilationDatabase.h
clang::clangd::ProgressParams
Definition: Protocol.h:550
clang::clangd::TheiaSemanticHighlightingParams
Parameters for the semantic highlighting (server-side) push notification.
Definition: Protocol.h:1450
clang::clangd::DidChangeWatchedFilesParams
Definition: Protocol.h:720
clang::clangd::TextDocumentIdentifier
Definition: Protocol.h:121
clang::clangd::DocumentRangeFormattingParams
Definition: Protocol.h:739
clang::clangd::RenameOptions
Definition: Rename.h:29
clang::clangd::NoParams
Definition: Protocol.h:260
clang::clangd::fromJSON
bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request)
Definition: Index.cpp:34
clang::clangd::CompletionItemKind::Method
clang::clangd::DidChangeConfigurationParams
Definition: Protocol.h:726
clang::clangd::ConfigurationSettings
Clangd extension: parameters configurable at any time, via the workspace/didChangeConfiguration notif...
Definition: Protocol.h:487
clang::clangd::DocumentLinkParams
Parameters for the document link request.
Definition: Protocol.h:1481
clang::clangd::CodeCompleteOptions
Definition: CodeComplete.h:44
clang::clangd::ExecuteCommandParams
Exact commands are not specified in the protocol so we define the ones supported by Clangd here.
Definition: Protocol.h:893
clang::clangd::Transport
Definition: Transport.h:34
clang::clangd::CompletionItemKind::File
Transport.h
clang::clangd::PublishDiagnosticsParams
Definition: Protocol.h:832
clang::clangd::MarkupKind
MarkupKind
Definition: Protocol.h:380
clang::clangd::TypeHierarchyParams
The type hierarchy params is an extension of the TextDocumentPositionsParams with optional properties...
Definition: Protocol.h:1276
clang::clangd::Empty
Definition: FuzzyMatch.h:42
clang::clangd::DidChangeTextDocumentParams
Definition: Protocol.h:679
clang::clangd::ClangdServer::Callbacks
Interface with hooks for users of ClangdServer to be notified of events.
Definition: ClangdServer.h:66
clang::clangd::PathRef
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
clang::clangd::ThreadsafeFS
Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
Definition: ThreadsafeFS.h:28
RenameOpts
RenameOptions RenameOpts
Definition: ClangdLSPServerTests.cpp:68
clang::clangd::WorkspaceSymbolParams
The parameters of a Workspace Symbol Request.
Definition: Protocol.h:1013
clang::clangd::CompletionParams
Definition: Protocol.h:1059
clang::clangd::ProgressParams::token
llvm::json::Value token
The progress token provided by the client or server.
Definition: Protocol.h:552
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
ClangdServer.h
clang::clangd::DidSaveTextDocumentParams
Definition: Protocol.h:661
clang::clangd::CodeActionParams
Definition: Protocol.h:848
clang::clangd::TextDocumentPositionParams
Definition: Protocol.h:1030
clang::clangd::DocumentOnTypeFormattingParams
Definition: Protocol.h:748
clang::clangd::RenameParams
Definition: Protocol.h:1230
clang::clangd::DidOpenTextDocumentParams
Definition: Protocol.h:649
clang::clangd::Callback
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:28
clang::clangd::ReferenceParams
Definition: Protocol.h:1344
clang::clangd::LSPDiagnosticCompare
A LSP-specific comparator used to find diagnostic in a container like std:map.
Definition: Protocol.h:824
clang::clangd::elog
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:56
clang::clangd::ClangdLSPServer::~ClangdLSPServer
~ClangdLSPServer()
The destructor blocks on any outstanding background tasks.
Definition: ClangdLSPServer.cpp:1410
clang::clangd::ClangdLSPServer::ClangdLSPServer
ClangdLSPServer(Transport &Transp, const ThreadsafeFS &TFS, const clangd::CodeCompleteOptions &CCOpts, const clangd::RenameOptions &RenameOpts, llvm::Optional< Path > CompileCommandsDir, bool UseDirBasedCDB, llvm::Optional< OffsetEncoding > ForcedOffsetEncoding, const ClangdServer::Options &Opts)
If CompileCommandsDir has a value, compile_commands.json will be loaded only from CompileCommandsDir.
Definition: ClangdLSPServer.cpp:1356
clang::clangd::Context
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:69
clang::clangd::CompletionItemKind::Value
clang::clangd::ClangdLSPServer::MessageHandler
Definition: ClangdLSPServer.cpp:168
Context.h
clang::clangd::ResolveTypeHierarchyItemParams
Parameters for the typeHierarchy/resolve request.
Definition: Protocol.h:1332