12#include "llvm/Support/LSP/Logging.h"
13#include "llvm/Support/LSP/Transport.h"
16#define DEBUG_TYPE "mlir-lsp-server"
21using llvm::lsp::Callback;
22using llvm::lsp::CodeAction;
23using llvm::lsp::CodeActionParams;
24using llvm::lsp::CompletionList;
25using llvm::lsp::CompletionParams;
26using llvm::lsp::DidChangeTextDocumentParams;
27using llvm::lsp::DidCloseTextDocumentParams;
28using llvm::lsp::DidOpenTextDocumentParams;
29using llvm::lsp::DocumentSymbol;
30using llvm::lsp::DocumentSymbolParams;
31using llvm::lsp::Hover;
32using llvm::lsp::InitializedParams;
33using llvm::lsp::InitializeParams;
34using llvm::lsp::JSONTransport;
35using llvm::lsp::Location;
36using llvm::lsp::Logger;
37using llvm::lsp::MessageHandler;
40using llvm::lsp::NoParams;
41using llvm::lsp::OutgoingNotification;
42using llvm::lsp::PublishDiagnosticsParams;
43using llvm::lsp::ReferenceParams;
44using llvm::lsp::TextDocumentPositionParams;
45using llvm::lsp::TextDocumentSyncKind;
46using llvm::lsp::URIForFile;
54 LSPServer(
MLIRServer &server) : server(server) {}
59 void onInitialize(
const InitializeParams ¶ms,
60 Callback<llvm::json::Value> reply);
61 void onInitialized(
const InitializedParams ¶ms);
62 void onShutdown(
const NoParams ¶ms, Callback<std::nullptr_t> reply);
67 void onDocumentDidOpen(
const DidOpenTextDocumentParams ¶ms);
68 void onDocumentDidClose(
const DidCloseTextDocumentParams ¶ms);
69 void onDocumentDidChange(
const DidChangeTextDocumentParams ¶ms);
74 void onGoToDefinition(
const TextDocumentPositionParams ¶ms,
75 Callback<std::vector<Location>> reply);
76 void onReference(
const ReferenceParams ¶ms,
77 Callback<std::vector<Location>> reply);
82 void onHover(
const TextDocumentPositionParams ¶ms,
83 Callback<std::optional<Hover>> reply);
88 void onDocumentSymbol(
const DocumentSymbolParams ¶ms,
89 Callback<std::vector<DocumentSymbol>> reply);
94 void onCompletion(
const CompletionParams ¶ms,
95 Callback<CompletionList> reply);
100 void onCodeAction(
const CodeActionParams ¶ms,
101 Callback<llvm::json::Value> reply);
107 Callback<MLIRConvertBytecodeResult> reply);
109 Callback<MLIRConvertBytecodeResult> reply);
119 OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;
123 bool shutdownRequestReceived =
false;
131void LSPServer::onInitialize(
const InitializeParams ¶ms,
132 Callback<llvm::json::Value> reply) {
134 llvm::json::Object serverCaps{
138 {
"change", (int)TextDocumentSyncKind::Full},
141 {
"completionProvider",
143 {
"allCommitCharacters",
151 {
"resolveProvider",
false},
152 {
"triggerCharacters",
153 {
".",
"%",
"^",
"!",
"#",
"(",
",",
"<",
":",
"[",
" ",
"\"",
"/"}},
155 {
"definitionProvider",
true},
156 {
"referencesProvider",
true},
157 {
"hoverProvider",
true},
161 {
"documentSymbolProvider",
162 params.capabilities.hierarchicalDocumentSymbol},
168 serverCaps[
"codeActionProvider"] =
169 params.capabilities.codeActionStructure
170 ? llvm::json::Object{{
"codeActionKinds",
171 {CodeAction::kQuickFix, CodeAction::kRefactor,
173 : llvm::json::Value(
true);
175 llvm::json::Object
result{
177 llvm::json::Object{{
"name",
"mlir-lsp-server"}, {
"version",
"0.0.0"}}},
178 {
"capabilities", std::move(serverCaps)}}};
181void LSPServer::onInitialized(
const InitializedParams &) {}
182void LSPServer::onShutdown(
const NoParams &, Callback<std::nullptr_t> reply) {
183 shutdownRequestReceived =
true;
191void LSPServer::onDocumentDidOpen(
const DidOpenTextDocumentParams ¶ms) {
192 PublishDiagnosticsParams diagParams(params.textDocument.uri,
193 params.textDocument.version);
195 params.textDocument.version,
196 diagParams.diagnostics);
199 publishDiagnostics(diagParams);
201void LSPServer::onDocumentDidClose(
const DidCloseTextDocumentParams ¶ms) {
202 std::optional<int64_t> version =
211 PublishDiagnosticsParams(params.textDocument.uri, *version));
213void LSPServer::onDocumentDidChange(
const DidChangeTextDocumentParams ¶ms) {
216 if (params.contentChanges.size() != 1)
218 PublishDiagnosticsParams diagParams(params.textDocument.uri,
219 params.textDocument.version);
221 params.textDocument.uri, params.contentChanges.front().text,
222 params.textDocument.version, diagParams.diagnostics);
225 publishDiagnostics(diagParams);
232void LSPServer::onGoToDefinition(
const TextDocumentPositionParams ¶ms,
233 Callback<std::vector<Location>> reply) {
234 std::vector<Location> locations;
235 server.
getLocationsOf(params.textDocument.uri, params.position, locations);
236 reply(std::move(locations));
239void LSPServer::onReference(
const ReferenceParams ¶ms,
240 Callback<std::vector<Location>> reply) {
241 std::vector<Location> locations;
242 server.
findReferencesOf(params.textDocument.uri, params.position, locations);
243 reply(std::move(locations));
250void LSPServer::onHover(
const TextDocumentPositionParams ¶ms,
251 Callback<std::optional<Hover>> reply) {
252 reply(server.
findHover(params.textDocument.uri, params.position));
259void LSPServer::onDocumentSymbol(
const DocumentSymbolParams ¶ms,
260 Callback<std::vector<DocumentSymbol>> reply) {
261 std::vector<DocumentSymbol> symbols;
263 reply(std::move(symbols));
270void LSPServer::onCompletion(
const CompletionParams ¶ms,
271 Callback<CompletionList> reply) {
279void LSPServer::onCodeAction(
const CodeActionParams ¶ms,
280 Callback<llvm::json::Value> reply) {
281 URIForFile uri = params.textDocument.uri;
284 auto isKindAllowed = [only(params.context.only)](StringRef kind) {
287 return llvm::any_of(only, [&](StringRef base) {
288 return kind.consume_front(base) &&
289 (kind.empty() || kind.starts_with(
"."));
294 std::vector<CodeAction> actions;
295 if (isKindAllowed(CodeAction::kQuickFix))
296 server.
getCodeActions(uri, params.range.start, params.context, actions);
297 reply(std::move(actions));
304void LSPServer::onConvertFromBytecode(
305 const MLIRConvertBytecodeParams ¶ms,
306 Callback<MLIRConvertBytecodeResult> reply) {
310void LSPServer::onConvertToBytecode(
const MLIRConvertBytecodeParams ¶ms,
311 Callback<MLIRConvertBytecodeResult> reply) {
320 JSONTransport &transport) {
321 LSPServer lspServer(server);
322 MessageHandler messageHandler(transport);
325 messageHandler.method(
"initialize", &lspServer, &LSPServer::onInitialize);
326 messageHandler.notification(
"initialized", &lspServer,
327 &LSPServer::onInitialized);
328 messageHandler.method(
"shutdown", &lspServer, &LSPServer::onShutdown);
331 messageHandler.notification(
"textDocument/didOpen", &lspServer,
332 &LSPServer::onDocumentDidOpen);
333 messageHandler.notification(
"textDocument/didClose", &lspServer,
334 &LSPServer::onDocumentDidClose);
335 messageHandler.notification(
"textDocument/didChange", &lspServer,
336 &LSPServer::onDocumentDidChange);
339 messageHandler.method(
"textDocument/definition", &lspServer,
340 &LSPServer::onGoToDefinition);
341 messageHandler.method(
"textDocument/references", &lspServer,
342 &LSPServer::onReference);
345 messageHandler.method(
"textDocument/hover", &lspServer, &LSPServer::onHover);
348 messageHandler.method(
"textDocument/documentSymbol", &lspServer,
349 &LSPServer::onDocumentSymbol);
352 messageHandler.method(
"textDocument/completion", &lspServer,
353 &LSPServer::onCompletion);
356 messageHandler.method(
"textDocument/codeAction", &lspServer,
357 &LSPServer::onCodeAction);
360 messageHandler.method(
"mlir/convertFromBytecode", &lspServer,
361 &LSPServer::onConvertFromBytecode);
362 messageHandler.method(
"mlir/convertToBytecode", &lspServer,
363 &LSPServer::onConvertToBytecode);
366 lspServer.publishDiagnostics =
367 messageHandler.outgoingNotification<PublishDiagnosticsParams>(
368 "textDocument/publishDiagnostics");
372 if (llvm::Error error = transport.run(messageHandler)) {
373 Logger::error(
"Transport error: {0}", error);
374 llvm::consumeError(std::move(error));
This class implements all of the MLIR related functionality necessary for a language server.
void addOrUpdateDocument(const URIForFile &uri, StringRef contents, int64_t version, std::vector< Diagnostic > &diagnostics)
Add or update the document, with the provided version, at the given URI.
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::Expected< MLIRConvertBytecodeResult > convertFromBytecode(const URIForFile &uri)
Convert the given bytecode file to the textual format.
llvm::Expected< MLIRConvertBytecodeResult > convertToBytecode(const URIForFile &uri)
Convert the given textual file to the bytecode format.
CompletionList getCodeCompletion(const URIForFile &uri, const Position &completePos)
Get the code completion list for the position within the given file.
void findDocumentSymbols(const URIForFile &uri, std::vector< DocumentSymbol > &symbols)
Find all of the document symbols within the given file.
void getCodeActions(const URIForFile &uri, const Range &pos, const CodeActionContext &context, std::vector< CodeAction > &actions)
Get the set of code actions within the file.
llvm::LogicalResult runMlirLSPServer(MLIRServer &server, llvm::lsp::JSONTransport &transport)
Run the main loop of the LSP server using the given MLIR server and transport.
Include the generated interface declarations.
This class represents the parameters used when converting between MLIR's bytecode and textual format.
URIForFile uri
The input file containing the bytecode or textual format.
This class represents the result of converting between MLIR's bytecode and textual format.