MLIR  19.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 void LSPServer::onInitialize(const InitializeParams &params,
120  // Send a response with the capabilities of this server.
121  llvm::json::Object serverCaps{
122  {"textDocumentSync",
123  llvm::json::Object{
124  {"openClose", true},
125  {"change", (int)TextDocumentSyncKind::Incremental},
126  {"save", true},
127  }},
128  {"completionProvider",
129  llvm::json::Object{
130  {"allCommitCharacters",
131  {"\t", "(", ")", "[", "]", "{", "}", "<", ">",
132  ":", ";", ",", "+", "-", "/", "*", "%", "^",
133  "&", "#", "?", ".", "=", "\"", "'", "|"}},
134  {"resolveProvider", false},
135  {"triggerCharacters",
136  {".", ">", "(", "{", ",", "<", ":", "[", " ", "\"", "/"}},
137  }},
138  {"signatureHelpProvider",
139  llvm::json::Object{
140  {"triggerCharacters", {"(", ","}},
141  }},
142  {"definitionProvider", true},
143  {"referencesProvider", true},
144  {"documentLinkProvider",
145  llvm::json::Object{
146  {"resolveProvider", false},
147  }},
148  {"hoverProvider", true},
149  {"documentSymbolProvider", true},
150  {"inlayHintProvider", true},
151  };
152 
153  llvm::json::Object result{
154  {{"serverInfo", llvm::json::Object{{"name", "mlir-pdll-lsp-server"},
155  {"version", "0.0.1"}}},
156  {"capabilities", std::move(serverCaps)}}};
157  reply(std::move(result));
158 }
159 void LSPServer::onInitialized(const InitializedParams &) {}
160 void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {
161  shutdownRequestReceived = true;
162  reply(nullptr);
163 }
164 
165 //===----------------------------------------------------------------------===//
166 // Document Change
167 
168 void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
169  PublishDiagnosticsParams diagParams(params.textDocument.uri,
170  params.textDocument.version);
171  server.addDocument(params.textDocument.uri, params.textDocument.text,
172  params.textDocument.version, diagParams.diagnostics);
173 
174  // Publish any recorded diagnostics.
175  publishDiagnostics(diagParams);
176 }
177 void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
178  std::optional<int64_t> version =
179  server.removeDocument(params.textDocument.uri);
180  if (!version)
181  return;
182 
183  // Empty out the diagnostics shown for this document. This will clear out
184  // anything currently displayed by the client for this document (e.g. in the
185  // "Problems" pane of VSCode).
186  publishDiagnostics(
187  PublishDiagnosticsParams(params.textDocument.uri, *version));
188 }
189 void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams &params) {
190  PublishDiagnosticsParams diagParams(params.textDocument.uri,
191  params.textDocument.version);
192  server.updateDocument(params.textDocument.uri, params.contentChanges,
193  params.textDocument.version, diagParams.diagnostics);
194 
195  // Publish any recorded diagnostics.
196  publishDiagnostics(diagParams);
197 }
198 
199 //===----------------------------------------------------------------------===//
200 // Definitions and References
201 
202 void LSPServer::onGoToDefinition(const TextDocumentPositionParams &params,
203  Callback<std::vector<Location>> reply) {
204  std::vector<Location> locations;
205  server.getLocationsOf(params.textDocument.uri, params.position, locations);
206  reply(std::move(locations));
207 }
208 
209 void LSPServer::onReference(const ReferenceParams &params,
210  Callback<std::vector<Location>> reply) {
211  std::vector<Location> locations;
212  server.findReferencesOf(params.textDocument.uri, params.position, locations);
213  reply(std::move(locations));
214 }
215 
216 //===----------------------------------------------------------------------===//
217 // DocumentLink
218 
219 void LSPServer::onDocumentLink(const DocumentLinkParams &params,
220  Callback<std::vector<DocumentLink>> reply) {
221  std::vector<DocumentLink> links;
222  server.getDocumentLinks(params.textDocument.uri, links);
223  reply(std::move(links));
224 }
225 
226 //===----------------------------------------------------------------------===//
227 // Hover
228 
229 void LSPServer::onHover(const TextDocumentPositionParams &params,
230  Callback<std::optional<Hover>> reply) {
231  reply(server.findHover(params.textDocument.uri, params.position));
232 }
233 
234 //===----------------------------------------------------------------------===//
235 // Document Symbols
236 
237 void LSPServer::onDocumentSymbol(const DocumentSymbolParams &params,
238  Callback<std::vector<DocumentSymbol>> reply) {
239  std::vector<DocumentSymbol> symbols;
240  server.findDocumentSymbols(params.textDocument.uri, symbols);
241  reply(std::move(symbols));
242 }
243 
244 //===----------------------------------------------------------------------===//
245 // Code Completion
246 
247 void LSPServer::onCompletion(const CompletionParams &params,
248  Callback<CompletionList> reply) {
249  reply(server.getCodeCompletion(params.textDocument.uri, params.position));
250 }
251 
252 //===----------------------------------------------------------------------===//
253 // Signature Help
254 
255 void LSPServer::onSignatureHelp(const TextDocumentPositionParams &params,
256  Callback<SignatureHelp> reply) {
257  reply(server.getSignatureHelp(params.textDocument.uri, params.position));
258 }
259 
260 //===----------------------------------------------------------------------===//
261 // Inlay Hints
262 
263 void LSPServer::onInlayHint(const InlayHintsParams &params,
264  Callback<std::vector<InlayHint>> reply) {
265  std::vector<InlayHint> hints;
266  server.getInlayHints(params.textDocument.uri, params.range, hints);
267  reply(std::move(hints));
268 }
269 
270 //===----------------------------------------------------------------------===//
271 // PDLL ViewOutput
272 
273 void LSPServer::onPDLLViewOutput(
274  const PDLLViewOutputParams &params,
275  Callback<std::optional<PDLLViewOutputResult>> reply) {
276  reply(server.getPDLLViewOutput(params.uri, params.kind));
277 }
278 
279 //===----------------------------------------------------------------------===//
280 // Entry Point
281 //===----------------------------------------------------------------------===//
282 
284  JSONTransport &transport) {
285  LSPServer lspServer(server, transport);
286  MessageHandler messageHandler(transport);
287 
288  // Initialization
289  messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);
290  messageHandler.notification("initialized", &lspServer,
291  &LSPServer::onInitialized);
292  messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);
293 
294  // Document Changes
295  messageHandler.notification("textDocument/didOpen", &lspServer,
296  &LSPServer::onDocumentDidOpen);
297  messageHandler.notification("textDocument/didClose", &lspServer,
298  &LSPServer::onDocumentDidClose);
299  messageHandler.notification("textDocument/didChange", &lspServer,
300  &LSPServer::onDocumentDidChange);
301 
302  // Definitions and References
303  messageHandler.method("textDocument/definition", &lspServer,
304  &LSPServer::onGoToDefinition);
305  messageHandler.method("textDocument/references", &lspServer,
306  &LSPServer::onReference);
307 
308  // Document Link
309  messageHandler.method("textDocument/documentLink", &lspServer,
310  &LSPServer::onDocumentLink);
311 
312  // Hover
313  messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);
314 
315  // Document Symbols
316  messageHandler.method("textDocument/documentSymbol", &lspServer,
317  &LSPServer::onDocumentSymbol);
318 
319  // Code Completion
320  messageHandler.method("textDocument/completion", &lspServer,
321  &LSPServer::onCompletion);
322 
323  // Signature Help
324  messageHandler.method("textDocument/signatureHelp", &lspServer,
325  &LSPServer::onSignatureHelp);
326 
327  // Inlay Hints
328  messageHandler.method("textDocument/inlayHint", &lspServer,
329  &LSPServer::onInlayHint);
330 
331  // PDLL ViewOutput
332  messageHandler.method("pdll/viewOutput", &lspServer,
333  &LSPServer::onPDLLViewOutput);
334 
335  // Diagnostics
336  lspServer.publishDiagnostics =
338  "textDocument/publishDiagnostics");
339 
340  // Run the main loop of the transport.
341  if (llvm::Error error = transport.run(messageHandler)) {
342  Logger::error("Transport error: {0}", error);
343  llvm::consumeError(std::move(error));
344  return failure();
345  }
346  return success(lspServer.shutdownRequestReceived);
347 }
A transport class that performs the JSON-RPC communication with the LSP client.
Definition: Transport.h:48
llvm::Error run(MessageHandler &handler)
Start executing the JSON-RPC transport.
Definition: Transport.cpp:202
static void error(const char *fmt, Ts &&...vals)
Definition: Logging.h:42
A handler used to process the incoming transport messages.
Definition: Transport.h:104
void notification(llvm::StringLiteral method, ThisT *thisPtr, void(ThisT::*handler)(const Param &))
Definition: Transport.h:146
void method(llvm::StringLiteral method, ThisT *thisPtr, void(ThisT::*handler)(const Param &, Callback< Result >))
Definition: Transport.h:133
OutgoingNotification< T > outgoingNotification(llvm::StringLiteral method)
Create an OutgoingNotification object used for the given method.
Definition: Transport.h:159
This class implements all of the PDLL related functionality necessary for a language server.
Definition: PDLLServer.h:39
llvm::unique_function< void(const T &)> OutgoingNotification
An OutgoingNotification<T> is a function used for outgoing notifications send to the client.
Definition: Transport.h:101
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Transport.h:96
LogicalResult runPdllLSPServer(PDLLServer &server, JSONTransport &transport)
Run the main loop of the LSP server using the given PDLL server and transport.
Definition: LSPServer.cpp:283
@ Incremental
Documents are synced by sending the full content on open.
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
VersionedTextDocumentIdentifier textDocument
The document that changed.
Definition: Protocol.h:506
std::vector< TextDocumentContentChangeEvent > contentChanges
The actual content changes.
Definition: Protocol.h:509
TextDocumentIdentifier textDocument
The document that was closed.
Definition: Protocol.h:472
TextDocumentItem textDocument
The document that was opened.
Definition: Protocol.h:459
Parameters for the document link request.
Definition: Protocol.h:1005
TextDocumentIdentifier textDocument
The document to provide document links for.
Definition: Protocol.h:1007
TextDocumentIdentifier textDocument
Definition: Protocol.h:636
A parameter literal used in inlay hint requests.
Definition: Protocol.h:1055
Range range
The visible document range for which inlay hints should be computed.
Definition: Protocol.h:1060
TextDocumentIdentifier textDocument
The text document.
Definition: Protocol.h:1057
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:253
int64_t version
The version number of this document.
Definition: Protocol.h:240
std::string text
The content of the opened text document.
Definition: Protocol.h:237
URIForFile uri
The text document's URI.
Definition: Protocol.h:231
TextDocumentIdentifier textDocument
The text document.
Definition: Protocol.h:422
Position position
The position inside the text document.
Definition: Protocol.h:425
int64_t version
The version number of this document.
Definition: Protocol.h:269
URIForFile uri
The text document's URI.
Definition: Protocol.h:267