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"
13#include "mlir/Tools/lsp-server-support/Logging.h"
14#include "mlir/Tools/lsp-server-support/Transport.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
21using namespace mlir;
22using namespace mlir::lsp;
23
24//===----------------------------------------------------------------------===//
25// LSPServer
26//===----------------------------------------------------------------------===//
27
28namespace {
29struct LSPServer {
30 LSPServer(PDLLServer &server, JSONTransport &transport)
31 : server(server), transport(transport) {}
32
33 //===--------------------------------------------------------------------===//
34 // Initialization
35
36 void onInitialize(const InitializeParams &params,
37 Callback<llvm::json::Value> reply);
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,
78 Callback<CompletionList> reply);
79
80 //===--------------------------------------------------------------------===//
81 // Signature Help
82
83 void onSignatureHelp(const TextDocumentPositionParams &params,
84 Callback<SignatureHelp> reply);
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.
107 OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;
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
118void LSPServer::onInitialize(const InitializeParams &params,
119 Callback<llvm::json::Value> reply) {
120 // Send a response with the capabilities of this server.
121 llvm::json::Object serverCaps{
122 {.K: "textDocumentSync",
123 .V: llvm::json::Object{
124 {.K: "openClose", .V: true},
125 {.K: "change", .V: (int)TextDocumentSyncKind::Incremental},
126 {.K: "save", .V: true},
127 }},
128 {.K: "completionProvider",
129 .V: llvm::json::Object{
130 {.K: "allCommitCharacters",
131 .V: {"\t", "(", ")", "[", "]", "{", "}", "<", ">",
132 ":", ";", ",", "+", "-", "/", "*", "%", "^",
133 "&", "#", "?", ".", "=", "\"", "'", "|"}},
134 {.K: "resolveProvider", .V: false},
135 {.K: "triggerCharacters",
136 .V: {".", ">", "(", "{", ",", "<", ":", "[", " ", "\"", "/"}},
137 }},
138 {.K: "signatureHelpProvider",
139 .V: llvm::json::Object{
140 {.K: "triggerCharacters", .V: {"(", ","}},
141 }},
142 {.K: "definitionProvider", .V: true},
143 {.K: "referencesProvider", .V: true},
144 {.K: "documentLinkProvider",
145 .V: llvm::json::Object{
146 {.K: "resolveProvider", .V: false},
147 }},
148 {.K: "hoverProvider", .V: true},
149 {.K: "documentSymbolProvider", .V: true},
150 {.K: "inlayHintProvider", .V: true},
151 };
152
153 llvm::json::Object result{
154 {{.K: "serverInfo", .V: llvm::json::Object{{.K: "name", .V: "mlir-pdll-lsp-server"},
155 {.K: "version", .V: "0.0.1"}}},
156 {.K: "capabilities", .V: std::move(serverCaps)}}};
157 reply(std::move(result));
158}
159void LSPServer::onInitialized(const InitializedParams &) {}
160void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {
161 shutdownRequestReceived = true;
162 reply(nullptr);
163}
164
165//===----------------------------------------------------------------------===//
166// Document Change
167
168void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
169 PublishDiagnosticsParams diagParams(params.textDocument.uri,
170 params.textDocument.version);
171 server.addDocument(uri: params.textDocument.uri, contents: params.textDocument.text,
172 version: params.textDocument.version, diagnostics&: diagParams.diagnostics);
173
174 // Publish any recorded diagnostics.
175 publishDiagnostics(diagParams);
176}
177void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
178 std::optional<int64_t> version =
179 server.removeDocument(uri: 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}
189void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams &params) {
190 PublishDiagnosticsParams diagParams(params.textDocument.uri,
191 params.textDocument.version);
192 server.updateDocument(uri: params.textDocument.uri, changes: params.contentChanges,
193 version: params.textDocument.version, diagnostics&: diagParams.diagnostics);
194
195 // Publish any recorded diagnostics.
196 publishDiagnostics(diagParams);
197}
198
199//===----------------------------------------------------------------------===//
200// Definitions and References
201
202void LSPServer::onGoToDefinition(const TextDocumentPositionParams &params,
203 Callback<std::vector<Location>> reply) {
204 std::vector<Location> locations;
205 server.getLocationsOf(uri: params.textDocument.uri, defPos: params.position, locations);
206 reply(std::move(locations));
207}
208
209void LSPServer::onReference(const ReferenceParams &params,
210 Callback<std::vector<Location>> reply) {
211 std::vector<Location> locations;
212 server.findReferencesOf(uri: params.textDocument.uri, pos: params.position, references&: locations);
213 reply(std::move(locations));
214}
215
216//===----------------------------------------------------------------------===//
217// DocumentLink
218
219void LSPServer::onDocumentLink(const DocumentLinkParams &params,
220 Callback<std::vector<DocumentLink>> reply) {
221 std::vector<DocumentLink> links;
222 server.getDocumentLinks(uri: params.textDocument.uri, documentLinks&: links);
223 reply(std::move(links));
224}
225
226//===----------------------------------------------------------------------===//
227// Hover
228
229void LSPServer::onHover(const TextDocumentPositionParams &params,
230 Callback<std::optional<Hover>> reply) {
231 reply(server.findHover(uri: params.textDocument.uri, hoverPos: params.position));
232}
233
234//===----------------------------------------------------------------------===//
235// Document Symbols
236
237void LSPServer::onDocumentSymbol(const DocumentSymbolParams &params,
238 Callback<std::vector<DocumentSymbol>> reply) {
239 std::vector<DocumentSymbol> symbols;
240 server.findDocumentSymbols(uri: params.textDocument.uri, symbols);
241 reply(std::move(symbols));
242}
243
244//===----------------------------------------------------------------------===//
245// Code Completion
246
247void LSPServer::onCompletion(const CompletionParams &params,
248 Callback<CompletionList> reply) {
249 reply(server.getCodeCompletion(uri: params.textDocument.uri, completePos: params.position));
250}
251
252//===----------------------------------------------------------------------===//
253// Signature Help
254
255void LSPServer::onSignatureHelp(const TextDocumentPositionParams &params,
256 Callback<SignatureHelp> reply) {
257 reply(server.getSignatureHelp(uri: params.textDocument.uri, helpPos: params.position));
258}
259
260//===----------------------------------------------------------------------===//
261// Inlay Hints
262
263void LSPServer::onInlayHint(const InlayHintsParams &params,
264 Callback<std::vector<InlayHint>> reply) {
265 std::vector<InlayHint> hints;
266 server.getInlayHints(uri: params.textDocument.uri, range: params.range, inlayHints&: hints);
267 reply(std::move(hints));
268}
269
270//===----------------------------------------------------------------------===//
271// PDLL ViewOutput
272
273void LSPServer::onPDLLViewOutput(
274 const PDLLViewOutputParams &params,
275 Callback<std::optional<PDLLViewOutputResult>> reply) {
276 reply(server.getPDLLViewOutput(uri: params.uri, kind: params.kind));
277}
278
279//===----------------------------------------------------------------------===//
280// Entry Point
281//===----------------------------------------------------------------------===//
282
283LogicalResult mlir::lsp::runPdllLSPServer(PDLLServer &server,
284 JSONTransport &transport) {
285 LSPServer lspServer(server, transport);
286 MessageHandler messageHandler(transport);
287
288 // Initialization
289 messageHandler.method(method: "initialize", thisPtr: &lspServer, handler: &LSPServer::onInitialize);
290 messageHandler.notification(method: "initialized", thisPtr: &lspServer,
291 handler: &LSPServer::onInitialized);
292 messageHandler.method(method: "shutdown", thisPtr: &lspServer, handler: &LSPServer::onShutdown);
293
294 // Document Changes
295 messageHandler.notification(method: "textDocument/didOpen", thisPtr: &lspServer,
296 handler: &LSPServer::onDocumentDidOpen);
297 messageHandler.notification(method: "textDocument/didClose", thisPtr: &lspServer,
298 handler: &LSPServer::onDocumentDidClose);
299 messageHandler.notification(method: "textDocument/didChange", thisPtr: &lspServer,
300 handler: &LSPServer::onDocumentDidChange);
301
302 // Definitions and References
303 messageHandler.method(method: "textDocument/definition", thisPtr: &lspServer,
304 handler: &LSPServer::onGoToDefinition);
305 messageHandler.method(method: "textDocument/references", thisPtr: &lspServer,
306 handler: &LSPServer::onReference);
307
308 // Document Link
309 messageHandler.method(method: "textDocument/documentLink", thisPtr: &lspServer,
310 handler: &LSPServer::onDocumentLink);
311
312 // Hover
313 messageHandler.method(method: "textDocument/hover", thisPtr: &lspServer, handler: &LSPServer::onHover);
314
315 // Document Symbols
316 messageHandler.method(method: "textDocument/documentSymbol", thisPtr: &lspServer,
317 handler: &LSPServer::onDocumentSymbol);
318
319 // Code Completion
320 messageHandler.method(method: "textDocument/completion", thisPtr: &lspServer,
321 handler: &LSPServer::onCompletion);
322
323 // Signature Help
324 messageHandler.method(method: "textDocument/signatureHelp", thisPtr: &lspServer,
325 handler: &LSPServer::onSignatureHelp);
326
327 // Inlay Hints
328 messageHandler.method(method: "textDocument/inlayHint", thisPtr: &lspServer,
329 handler: &LSPServer::onInlayHint);
330
331 // PDLL ViewOutput
332 messageHandler.method(method: "pdll/viewOutput", thisPtr: &lspServer,
333 handler: &LSPServer::onPDLLViewOutput);
334
335 // Diagnostics
336 lspServer.publishDiagnostics =
337 messageHandler.outgoingNotification<PublishDiagnosticsParams>(
338 method: "textDocument/publishDiagnostics");
339
340 // Run the main loop of the transport.
341 if (llvm::Error error = transport.run(handler&: messageHandler)) {
342 Logger::error(fmt: "Transport error: {0}", vals&: error);
343 llvm::consumeError(Err: std::move(error));
344 return failure();
345 }
346 return success(isSuccess: lspServer.shutdownRequestReceived);
347}
348

source code of mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp