MLIR  21.0.0git
LSPServer.cpp
Go to the documentation of this file.
1 //===- LSPServer.cpp - PDLL Language Server -------------------------------===//
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 "LSPServer.h"
10 
11 #include "PDLLServer.h"
12 #include "Protocol.h"
15 #include "llvm/ADT/FunctionExtras.h"
16 #include "llvm/ADT/StringMap.h"
17 #include <optional>
18 
19 #define DEBUG_TYPE "pdll-lsp-server"
20 
21 using namespace mlir;
22 using namespace mlir::lsp;
23 
24 //===----------------------------------------------------------------------===//
25 // LSPServer
26 //===----------------------------------------------------------------------===//
27 
28 namespace {
29 struct LSPServer {
30  LSPServer(PDLLServer &server, JSONTransport &transport)
31  : server(server), transport(transport) {}
32 
33  //===--------------------------------------------------------------------===//
34  // Initialization
35 
36  void onInitialize(const InitializeParams &params,
38  void onInitialized(const InitializedParams &params);
39  void onShutdown(const NoParams &params, Callback<std::nullptr_t> reply);
40 
41  //===--------------------------------------------------------------------===//
42  // Document Change
43 
44  void onDocumentDidOpen(const DidOpenTextDocumentParams &params);
45  void onDocumentDidClose(const DidCloseTextDocumentParams &params);
46  void onDocumentDidChange(const DidChangeTextDocumentParams &params);
47 
48  //===--------------------------------------------------------------------===//
49  // Definitions and References
50 
51  void onGoToDefinition(const TextDocumentPositionParams &params,
52  Callback<std::vector<Location>> reply);
53  void onReference(const ReferenceParams &params,
54  Callback<std::vector<Location>> reply);
55 
56  //===----------------------------------------------------------------------===//
57  // DocumentLink
58 
59  void onDocumentLink(const DocumentLinkParams &params,
60  Callback<std::vector<DocumentLink>> reply);
61 
62  //===--------------------------------------------------------------------===//
63  // Hover
64 
65  void onHover(const TextDocumentPositionParams &params,
66  Callback<std::optional<Hover>> reply);
67 
68  //===--------------------------------------------------------------------===//
69  // Document Symbols
70 
71  void onDocumentSymbol(const DocumentSymbolParams &params,
72  Callback<std::vector<DocumentSymbol>> reply);
73 
74  //===--------------------------------------------------------------------===//
75  // Code Completion
76 
77  void onCompletion(const CompletionParams &params,
79 
80  //===--------------------------------------------------------------------===//
81  // Signature Help
82 
83  void onSignatureHelp(const TextDocumentPositionParams &params,
85 
86  //===--------------------------------------------------------------------===//
87  // Inlay Hints
88 
89  void onInlayHint(const InlayHintsParams &params,
90  Callback<std::vector<InlayHint>> reply);
91 
92  //===--------------------------------------------------------------------===//
93  // PDLL View Output
94 
95  void onPDLLViewOutput(const PDLLViewOutputParams &params,
96  Callback<std::optional<PDLLViewOutputResult>> reply);
97 
98  //===--------------------------------------------------------------------===//
99  // Fields
100  //===--------------------------------------------------------------------===//
101 
102  PDLLServer &server;
103  JSONTransport &transport;
104 
105  /// An outgoing notification used to send diagnostics to the client when they
106  /// are ready to be processed.
108 
109  /// Used to indicate that the 'shutdown' request was received from the
110  /// Language Server client.
111  bool shutdownRequestReceived = false;
112 };
113 } // namespace
114 
115 //===----------------------------------------------------------------------===//
116 // Initialization
117 //===----------------------------------------------------------------------===//
118 
119 void LSPServer::onInitialize(const InitializeParams &params,
121  // Send a response with the capabilities of this server.
122  llvm::json::Object serverCaps{
123  {"textDocumentSync",
124  llvm::json::Object{
125  {"openClose", true},
126  {"change", (int)TextDocumentSyncKind::Incremental},
127  {"save", true},
128  }},
129  {"completionProvider",
130  llvm::json::Object{
131  {"allCommitCharacters",
132  {"\t", "(", ")", "[", "]", "{", "}", "<", ">",
133  ":", ";", ",", "+", "-", "/", "*", "%", "^",
134  "&", "#", "?", ".", "=", "\"", "'", "|"}},
135  {"resolveProvider", false},
136  {"triggerCharacters",
137  {".", ">", "(", "{", ",", "<", ":", "[", " ", "\"", "/"}},
138  }},
139  {"signatureHelpProvider",
140  llvm::json::Object{
141  {"triggerCharacters", {"(", ","}},
142  }},
143  {"definitionProvider", true},
144  {"referencesProvider", true},
145  {"documentLinkProvider",
146  llvm::json::Object{
147  {"resolveProvider", false},
148  }},
149  {"hoverProvider", true},
150  {"documentSymbolProvider", true},
151  {"inlayHintProvider", true},
152  };
153 
154  llvm::json::Object result{
155  {{"serverInfo", llvm::json::Object{{"name", "mlir-pdll-lsp-server"},
156  {"version", "0.0.1"}}},
157  {"capabilities", std::move(serverCaps)}}};
158  reply(std::move(result));
159 }
160 void LSPServer::onInitialized(const InitializedParams &) {}
161 void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {
162  shutdownRequestReceived = true;
163  reply(nullptr);
164 }
165 
166 //===----------------------------------------------------------------------===//
167 // Document Change
168 //===----------------------------------------------------------------------===//
169 
170 void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
171  PublishDiagnosticsParams diagParams(params.textDocument.uri,
172  params.textDocument.version);
173  server.addDocument(params.textDocument.uri, params.textDocument.text,
174  params.textDocument.version, diagParams.diagnostics);
175 
176  // Publish any recorded diagnostics.
177  publishDiagnostics(diagParams);
178 }
179 void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
180  std::optional<int64_t> version =
181  server.removeDocument(params.textDocument.uri);
182  if (!version)
183  return;
184 
185  // Empty out the diagnostics shown for this document. This will clear out
186  // anything currently displayed by the client for this document (e.g. in the
187  // "Problems" pane of VSCode).
188  publishDiagnostics(
189  PublishDiagnosticsParams(params.textDocument.uri, *version));
190 }
191 void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams &params) {
192  PublishDiagnosticsParams diagParams(params.textDocument.uri,
193  params.textDocument.version);
194  server.updateDocument(params.textDocument.uri, params.contentChanges,
195  params.textDocument.version, diagParams.diagnostics);
196 
197  // Publish any recorded diagnostics.
198  publishDiagnostics(diagParams);
199 }
200 
201 //===----------------------------------------------------------------------===//
202 // Definitions and References
203 //===----------------------------------------------------------------------===//
204 
205 void LSPServer::onGoToDefinition(const TextDocumentPositionParams &params,
206  Callback<std::vector<Location>> reply) {
207  std::vector<Location> locations;
208  server.getLocationsOf(params.textDocument.uri, params.position, locations);
209  reply(std::move(locations));
210 }
211 
212 void LSPServer::onReference(const ReferenceParams &params,
213  Callback<std::vector<Location>> reply) {
214  std::vector<Location> locations;
215  server.findReferencesOf(params.textDocument.uri, params.position, locations);
216  reply(std::move(locations));
217 }
218 
219 //===----------------------------------------------------------------------===//
220 // DocumentLink
221 //===----------------------------------------------------------------------===//
222 
223 void LSPServer::onDocumentLink(const DocumentLinkParams &params,
224  Callback<std::vector<DocumentLink>> reply) {
225  std::vector<DocumentLink> links;
226  server.getDocumentLinks(params.textDocument.uri, links);
227  reply(std::move(links));
228 }
229 
230 //===----------------------------------------------------------------------===//
231 // Hover
232 //===----------------------------------------------------------------------===//
233 
234 void LSPServer::onHover(const TextDocumentPositionParams &params,
235  Callback<std::optional<Hover>> reply) {
236  reply(server.findHover(params.textDocument.uri, params.position));
237 }
238 
239 //===----------------------------------------------------------------------===//
240 // Document Symbols
241 //===----------------------------------------------------------------------===//
242 
243 void LSPServer::onDocumentSymbol(const DocumentSymbolParams &params,
244  Callback<std::vector<DocumentSymbol>> reply) {
245  std::vector<DocumentSymbol> symbols;
246  server.findDocumentSymbols(params.textDocument.uri, symbols);
247  reply(std::move(symbols));
248 }
249 
250 //===----------------------------------------------------------------------===//
251 // Code Completion
252 //===----------------------------------------------------------------------===//
253 
254 void LSPServer::onCompletion(const CompletionParams &params,
255  Callback<CompletionList> reply) {
256  reply(server.getCodeCompletion(params.textDocument.uri, params.position));
257 }
258 
259 //===----------------------------------------------------------------------===//
260 // Signature Help
261 //===----------------------------------------------------------------------===//
262 
263 void LSPServer::onSignatureHelp(const TextDocumentPositionParams &params,
264  Callback<SignatureHelp> reply) {
265  reply(server.getSignatureHelp(params.textDocument.uri, params.position));
266 }
267 
268 //===----------------------------------------------------------------------===//
269 // Inlay Hints
270 //===----------------------------------------------------------------------===//
271 
272 void LSPServer::onInlayHint(const InlayHintsParams &params,
273  Callback<std::vector<InlayHint>> reply) {
274  std::vector<InlayHint> hints;
275  server.getInlayHints(params.textDocument.uri, params.range, hints);
276  reply(std::move(hints));
277 }
278 
279 //===----------------------------------------------------------------------===//
280 // PDLL ViewOutput
281 //===----------------------------------------------------------------------===//
282 
283 void LSPServer::onPDLLViewOutput(
284  const PDLLViewOutputParams &params,
285  Callback<std::optional<PDLLViewOutputResult>> reply) {
286  reply(server.getPDLLViewOutput(params.uri, params.kind));
287 }
288 
289 //===----------------------------------------------------------------------===//
290 // Entry Point
291 //===----------------------------------------------------------------------===//
292 
294  JSONTransport &transport) {
295  LSPServer lspServer(server, transport);
296  MessageHandler messageHandler(transport);
297 
298  // Initialization
299  messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);
300  messageHandler.notification("initialized", &lspServer,
301  &LSPServer::onInitialized);
302  messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);
303 
304  // Document Changes
305  messageHandler.notification("textDocument/didOpen", &lspServer,
306  &LSPServer::onDocumentDidOpen);
307  messageHandler.notification("textDocument/didClose", &lspServer,
308  &LSPServer::onDocumentDidClose);
309  messageHandler.notification("textDocument/didChange", &lspServer,
310  &LSPServer::onDocumentDidChange);
311 
312  // Definitions and References
313  messageHandler.method("textDocument/definition", &lspServer,
314  &LSPServer::onGoToDefinition);
315  messageHandler.method("textDocument/references", &lspServer,
316  &LSPServer::onReference);
317 
318  // Document Link
319  messageHandler.method("textDocument/documentLink", &lspServer,
320  &LSPServer::onDocumentLink);
321 
322  // Hover
323  messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);
324 
325  // Document Symbols
326  messageHandler.method("textDocument/documentSymbol", &lspServer,
327  &LSPServer::onDocumentSymbol);
328 
329  // Code Completion
330  messageHandler.method("textDocument/completion", &lspServer,
331  &LSPServer::onCompletion);
332 
333  // Signature Help
334  messageHandler.method("textDocument/signatureHelp", &lspServer,
335  &LSPServer::onSignatureHelp);
336 
337  // Inlay Hints
338  messageHandler.method("textDocument/inlayHint", &lspServer,
339  &LSPServer::onInlayHint);
340 
341  // PDLL ViewOutput
342  messageHandler.method("pdll/viewOutput", &lspServer,
343  &LSPServer::onPDLLViewOutput);
344 
345  // Diagnostics
346  lspServer.publishDiagnostics =
348  "textDocument/publishDiagnostics");
349 
350  // Run the main loop of the transport.
351  if (llvm::Error error = transport.run(messageHandler)) {
352  Logger::error("Transport error: {0}", error);
353  llvm::consumeError(std::move(error));
354  return failure();
355  }
356  return success(lspServer.shutdownRequestReceived);
357 }
A transport class that performs the JSON-RPC communication with the LSP client.
Definition: Transport.h:88
llvm::Error run(MessageHandler &handler)
Start executing the JSON-RPC transport.
Definition: Transport.cpp:210
static void error(const char *fmt, Ts &&...vals)
Definition: Logging.h:42
A handler used to process the incoming transport messages.
Definition: Transport.h:152
void notification(llvm::StringLiteral method, ThisT *thisPtr, void(ThisT::*handler)(const Param &))
Definition: Transport.h:194
void method(llvm::StringLiteral method, ThisT *thisPtr, void(ThisT::*handler)(const Param &, Callback< Result >))
Definition: Transport.h:181
OutgoingNotification< T > outgoingNotification(llvm::StringLiteral method)
Create an OutgoingNotification object used for the given method.
Definition: Transport.h:213
This class implements all of the PDLL related functionality necessary for a language server.
Definition: PDLLServer.h:40
llvm::unique_function< void(const T &)> OutgoingNotification
An OutgoingNotification<T> is a function used for outgoing notifications send to the client.
Definition: Transport.h:136
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Transport.h:131
llvm::LogicalResult runPdllLSPServer(PDLLServer &server, JSONTransport &transport)
Run the main loop of the LSP server using the given PDLL server and transport.
Definition: LSPServer.cpp:293
@ Incremental
Documents are synced by sending the full content on open.
Include the generated interface declarations.
VersionedTextDocumentIdentifier textDocument
The document that changed.
Definition: Protocol.h:503
std::vector< TextDocumentContentChangeEvent > contentChanges
The actual content changes.
Definition: Protocol.h:506
TextDocumentIdentifier textDocument
The document that was closed.
Definition: Protocol.h:469
TextDocumentItem textDocument
The document that was opened.
Definition: Protocol.h:456
Parameters for the document link request.
Definition: Protocol.h:1015
TextDocumentIdentifier textDocument
The document to provide document links for.
Definition: Protocol.h:1017
TextDocumentIdentifier textDocument
Definition: Protocol.h:633
A parameter literal used in inlay hint requests.
Definition: Protocol.h:1065
Range range
The visible document range for which inlay hints should be computed.
Definition: Protocol.h:1070
TextDocumentIdentifier textDocument
The text document.
Definition: Protocol.h:1067
Represents the parameters used when viewing the output of a PDLL file.
Definition: Protocol.h:39
URIForFile uri
The URI of the document to view the output of.
Definition: Protocol.h:41
PDLLViewOutputKind kind
The kind of output to generate.
Definition: Protocol.h:44
URIForFile uri
The text document's URI.
Definition: Protocol.h:250
int64_t version
The version number of this document.
Definition: Protocol.h:237
std::string text
The content of the opened text document.
Definition: Protocol.h:234
URIForFile uri
The text document's URI.
Definition: Protocol.h:228
TextDocumentIdentifier textDocument
The text document.
Definition: Protocol.h:419
Position position
The position inside the text document.
Definition: Protocol.h:422
int64_t version
The version number of this document.
Definition: Protocol.h:266
URIForFile uri
The text document's URI.
Definition: Protocol.h:264