MLIR 22.0.0git
LSPServer.cpp
Go to the documentation of this file.
1//===- LSPServer.cpp - TableGen 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 "TableGenServer.h"
12#include "llvm/Support/LSP/Logging.h"
13#include "llvm/Support/LSP/Protocol.h"
14#include "llvm/Support/LSP/Transport.h"
15#include <optional>
16
17using namespace mlir;
18using namespace mlir::lsp;
19
20using llvm::lsp::Callback;
21using llvm::lsp::DidChangeTextDocumentParams;
22using llvm::lsp::DidCloseTextDocumentParams;
23using llvm::lsp::DidOpenTextDocumentParams;
24using llvm::lsp::DocumentLinkParams;
25using llvm::lsp::Hover;
26using llvm::lsp::InitializedParams;
27using llvm::lsp::InitializeParams;
28using llvm::lsp::JSONTransport;
29using llvm::lsp::Location;
30using llvm::lsp::Logger;
31using llvm::lsp::MessageHandler;
32using llvm::lsp::NoParams;
33using llvm::lsp::OutgoingNotification;
34using llvm::lsp::PublishDiagnosticsParams;
35using llvm::lsp::ReferenceParams;
36using llvm::lsp::TextDocumentPositionParams;
37using llvm::lsp::TextDocumentSyncKind;
38
39//===----------------------------------------------------------------------===//
40// LSPServer
41//===----------------------------------------------------------------------===//
42
43namespace {
44struct LSPServer {
45 LSPServer(TableGenServer &server, JSONTransport &transport)
46 : server(server), transport(transport) {}
47
48 //===--------------------------------------------------------------------===//
49 // Initialization
50
51 void onInitialize(const InitializeParams &params,
52 Callback<llvm::json::Value> reply);
53 void onInitialized(const InitializedParams &params);
54 void onShutdown(const NoParams &params, Callback<std::nullptr_t> reply);
55
56 //===--------------------------------------------------------------------===//
57 // Document Change
58
59 void onDocumentDidOpen(const DidOpenTextDocumentParams &params);
60 void onDocumentDidClose(const DidCloseTextDocumentParams &params);
61 void onDocumentDidChange(const DidChangeTextDocumentParams &params);
62
63 //===--------------------------------------------------------------------===//
64 // Definitions and References
65
66 void onGoToDefinition(const TextDocumentPositionParams &params,
67 Callback<std::vector<Location>> reply);
68 void onReference(const ReferenceParams &params,
69 Callback<std::vector<Location>> reply);
70
71 //===----------------------------------------------------------------------===//
72 // DocumentLink
73
74 void onDocumentLink(const DocumentLinkParams &params,
75 Callback<std::vector<DocumentLink>> reply);
76
77 //===--------------------------------------------------------------------===//
78 // Hover
79
80 void onHover(const TextDocumentPositionParams &params,
81 Callback<std::optional<Hover>> reply);
82
83 //===--------------------------------------------------------------------===//
84 // Fields
85 //===--------------------------------------------------------------------===//
86
87 TableGenServer &server;
88 JSONTransport &transport;
89
90 /// An outgoing notification used to send diagnostics to the client when they
91 /// are ready to be processed.
92 OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;
93
94 /// Used to indicate that the 'shutdown' request was received from the
95 /// Language Server client.
96 bool shutdownRequestReceived = false;
97};
98} // namespace
99
100//===----------------------------------------------------------------------===//
101// Initialization
102//===----------------------------------------------------------------------===//
103
104void LSPServer::onInitialize(const InitializeParams &params,
105 Callback<llvm::json::Value> reply) {
106 // Send a response with the capabilities of this server.
107 llvm::json::Object serverCaps{
108 {"textDocumentSync",
109 llvm::json::Object{
110 {"openClose", true},
111 {"change", (int)TextDocumentSyncKind::Incremental},
112 {"save", true},
113 }},
114 {"definitionProvider", true},
115 {"referencesProvider", true},
116 {"documentLinkProvider",
117 llvm::json::Object{
118 {"resolveProvider", false},
119 }},
120 {"hoverProvider", true},
121 };
122
123 llvm::json::Object result{
124 {{"serverInfo", llvm::json::Object{{"name", "tblgen-lsp-server"},
125 {"version", "0.0.1"}}},
126 {"capabilities", std::move(serverCaps)}}};
127 reply(std::move(result));
128}
129void LSPServer::onInitialized(const InitializedParams &) {}
130void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {
131 shutdownRequestReceived = true;
132 reply(nullptr);
133}
134
135//===----------------------------------------------------------------------===//
136// Document Change
137//===----------------------------------------------------------------------===//
138
139void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
140 PublishDiagnosticsParams diagParams(params.textDocument.uri,
141 params.textDocument.version);
142 server.addDocument(params.textDocument.uri, params.textDocument.text,
143 params.textDocument.version, diagParams.diagnostics);
144
145 // Publish any recorded diagnostics.
146 publishDiagnostics(diagParams);
147}
148void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
149 std::optional<int64_t> version =
150 server.removeDocument(params.textDocument.uri);
151 if (!version)
152 return;
153
154 // Empty out the diagnostics shown for this document. This will clear out
155 // anything currently displayed by the client for this document (e.g. in the
156 // "Problems" pane of VSCode).
157 publishDiagnostics(
158 PublishDiagnosticsParams(params.textDocument.uri, *version));
159}
160void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams &params) {
161 PublishDiagnosticsParams diagParams(params.textDocument.uri,
162 params.textDocument.version);
163 server.updateDocument(params.textDocument.uri, params.contentChanges,
164 params.textDocument.version, diagParams.diagnostics);
165
166 // Publish any recorded diagnostics.
167 publishDiagnostics(diagParams);
168}
169
170//===----------------------------------------------------------------------===//
171// Definitions and References
172//===----------------------------------------------------------------------===//
173
174void LSPServer::onGoToDefinition(const TextDocumentPositionParams &params,
175 Callback<std::vector<Location>> reply) {
176 std::vector<Location> locations;
177 server.getLocationsOf(params.textDocument.uri, params.position, locations);
178 reply(std::move(locations));
179}
180
181void LSPServer::onReference(const ReferenceParams &params,
182 Callback<std::vector<Location>> reply) {
183 std::vector<Location> locations;
184 server.findReferencesOf(params.textDocument.uri, params.position, locations);
185 reply(std::move(locations));
186}
187
188//===----------------------------------------------------------------------===//
189// DocumentLink
190//===----------------------------------------------------------------------===//
191
192void LSPServer::onDocumentLink(const DocumentLinkParams &params,
193 Callback<std::vector<DocumentLink>> reply) {
194 std::vector<DocumentLink> links;
195 server.getDocumentLinks(params.textDocument.uri, links);
196 reply(std::move(links));
197}
198
199//===----------------------------------------------------------------------===//
200// Hover
201//===----------------------------------------------------------------------===//
202
203void LSPServer::onHover(const TextDocumentPositionParams &params,
204 Callback<std::optional<Hover>> reply) {
205 reply(server.findHover(params.textDocument.uri, params.position));
206}
207
208//===----------------------------------------------------------------------===//
209// Entry Point
210//===----------------------------------------------------------------------===//
211
212LogicalResult mlir::lsp::runTableGenLSPServer(TableGenServer &server,
213 JSONTransport &transport) {
214 LSPServer lspServer(server, transport);
215 MessageHandler messageHandler(transport);
216
217 // Initialization
218 messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);
219 messageHandler.notification("initialized", &lspServer,
220 &LSPServer::onInitialized);
221 messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);
222
223 // Document Changes
224 messageHandler.notification("textDocument/didOpen", &lspServer,
225 &LSPServer::onDocumentDidOpen);
226 messageHandler.notification("textDocument/didClose", &lspServer,
227 &LSPServer::onDocumentDidClose);
228 messageHandler.notification("textDocument/didChange", &lspServer,
229 &LSPServer::onDocumentDidChange);
230
231 // Definitions and References
232 messageHandler.method("textDocument/definition", &lspServer,
233 &LSPServer::onGoToDefinition);
234 messageHandler.method("textDocument/references", &lspServer,
235 &LSPServer::onReference);
236
237 // Document Link
238 messageHandler.method("textDocument/documentLink", &lspServer,
239 &LSPServer::onDocumentLink);
240
241 // Hover
242 messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);
243
244 // Diagnostics
245 lspServer.publishDiagnostics =
246 messageHandler.outgoingNotification<PublishDiagnosticsParams>(
247 "textDocument/publishDiagnostics");
248
249 // Run the main loop of the transport.
250 if (llvm::Error error = transport.run(messageHandler)) {
251 Logger::error("Transport error: {0}", error);
252 llvm::consumeError(std::move(error));
253 return failure();
254 }
255 return success(lspServer.shutdownRequestReceived);
256}
return success()
std::optional< int64_t > removeDocument(const URIForFile &uri)
Remove the document with the given uri.
void findReferencesOf(const URIForFile &uri, const Position &pos, std::vector< Location > &references)
Find all references of the object pointed at by the given position.
void getLocationsOf(const URIForFile &uri, const Position &defPos, std::vector< Location > &locations)
Return the locations of the object pointed at by the given position.
std::optional< Hover > findHover(const URIForFile &uri, const Position &hoverPos)
Find a hover description for the given hover position, or std::nullopt if one couldn't be found.
llvm::LogicalResult runTableGenLSPServer(TableGenServer &server, llvm::lsp::JSONTransport &transport)
Run the main loop of the LSP server using the given TableGen server and transport.
Include the generated interface declarations.