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::Logger;
36using llvm::lsp::MessageHandler;
39using llvm::lsp::NoParams;
40using llvm::lsp::OutgoingNotification;
41using llvm::lsp::PublishDiagnosticsParams;
42using llvm::lsp::ReferenceParams;
43using llvm::lsp::TextDocumentPositionParams;
44using llvm::lsp::TextDocumentSyncKind;
45using llvm::lsp::URIForFile;
53 LSPServer(
MLIRServer &server) : server(server) {}
58 void onInitialize(
const InitializeParams ¶ms,
59 Callback<llvm::json::Value> reply);
60 void onInitialized(
const InitializedParams ¶ms);
61 void onShutdown(
const NoParams ¶ms, Callback<std::nullptr_t> reply);
66 void onDocumentDidOpen(
const DidOpenTextDocumentParams ¶ms);
67 void onDocumentDidClose(
const DidCloseTextDocumentParams ¶ms);
68 void onDocumentDidChange(
const DidChangeTextDocumentParams ¶ms);
73 void onGoToDefinition(
const TextDocumentPositionParams ¶ms,
74 Callback<std::vector<llvm::lsp::Location>> reply);
75 void onReference(
const ReferenceParams ¶ms,
76 Callback<std::vector<llvm::lsp::Location>> reply);
81 void onHover(
const TextDocumentPositionParams ¶ms,
82 Callback<std::optional<Hover>> reply);
87 void onDocumentSymbol(
const DocumentSymbolParams ¶ms,
88 Callback<std::vector<DocumentSymbol>> reply);
93 void onCompletion(
const CompletionParams ¶ms,
94 Callback<CompletionList> reply);
99 void onCodeAction(
const CodeActionParams ¶ms,
100 Callback<llvm::json::Value> reply);
106 Callback<MLIRConvertBytecodeResult> reply);
108 Callback<MLIRConvertBytecodeResult> reply);
118 OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;
122 bool shutdownRequestReceived =
false;
130void LSPServer::onInitialize(
const InitializeParams ¶ms,
131 Callback<llvm::json::Value> reply) {
133 if (params.rootUri) {
134 llvm::Expected<URIForFile> rootURI = URIForFile::fromURI(*params.rootUri);
138 consumeError(rootURI.takeError());
139 }
else if (params.rootPath) {
144 llvm::json::Object serverCaps{
148 {
"change", (int)TextDocumentSyncKind::Full},
151 {
"completionProvider",
153 {
"allCommitCharacters",
161 {
"resolveProvider",
false},
162 {
"triggerCharacters",
163 {
".",
"%",
"^",
"!",
"#",
"(",
",",
"<",
":",
"[",
" ",
"\"",
"/"}},
165 {
"definitionProvider",
true},
166 {
"referencesProvider",
true},
167 {
"hoverProvider",
true},
171 {
"documentSymbolProvider",
172 params.capabilities.hierarchicalDocumentSymbol},
178 serverCaps[
"codeActionProvider"] =
179 params.capabilities.codeActionStructure
180 ? llvm::json::Object{{
"codeActionKinds",
181 {CodeAction::kQuickFix, CodeAction::kRefactor,
183 : llvm::json::Value(
true);
185 llvm::json::Object
result{
187 llvm::json::Object{{
"name",
"mlir-lsp-server"}, {
"version",
"0.0.0"}}},
188 {
"capabilities", std::move(serverCaps)}}};
191void LSPServer::onInitialized(
const InitializedParams &) {}
192void LSPServer::onShutdown(
const NoParams &, Callback<std::nullptr_t> reply) {
193 shutdownRequestReceived =
true;
201void LSPServer::onDocumentDidOpen(
const DidOpenTextDocumentParams ¶ms) {
202 PublishDiagnosticsParams diagParams(params.textDocument.uri,
203 params.textDocument.version);
205 params.textDocument.version,
206 diagParams.diagnostics);
209 publishDiagnostics(diagParams);
211void LSPServer::onDocumentDidClose(
const DidCloseTextDocumentParams ¶ms) {
212 std::optional<int64_t> version =
221 PublishDiagnosticsParams(params.textDocument.uri, *version));
223void LSPServer::onDocumentDidChange(
const DidChangeTextDocumentParams ¶ms) {
226 if (params.contentChanges.size() != 1)
228 PublishDiagnosticsParams diagParams(params.textDocument.uri,
229 params.textDocument.version);
231 params.textDocument.uri, params.contentChanges.front().text,
232 params.textDocument.version, diagParams.diagnostics);
235 publishDiagnostics(diagParams);
242void LSPServer::onGoToDefinition(
243 const TextDocumentPositionParams ¶ms,
244 Callback<std::vector<llvm::lsp::Location>> reply) {
245 std::vector<llvm::lsp::Location> locations;
246 server.
getLocationsOf(params.textDocument.uri, params.position, locations);
247 reply(std::move(locations));
250void LSPServer::onReference(
const ReferenceParams ¶ms,
251 Callback<std::vector<llvm::lsp::Location>> reply) {
252 std::vector<llvm::lsp::Location> locations;
253 server.
findReferencesOf(params.textDocument.uri, params.position, locations);
254 reply(std::move(locations));
261void LSPServer::onHover(
const TextDocumentPositionParams ¶ms,
262 Callback<std::optional<Hover>> reply) {
263 reply(server.
findHover(params.textDocument.uri, params.position));
270void LSPServer::onDocumentSymbol(
const DocumentSymbolParams ¶ms,
271 Callback<std::vector<DocumentSymbol>> reply) {
272 std::vector<DocumentSymbol> symbols;
274 reply(std::move(symbols));
281void LSPServer::onCompletion(
const CompletionParams ¶ms,
282 Callback<CompletionList> reply) {
290void LSPServer::onCodeAction(
const CodeActionParams ¶ms,
291 Callback<llvm::json::Value> reply) {
292 URIForFile uri = params.textDocument.uri;
295 auto isKindAllowed = [only(params.context.only)](StringRef kind) {
298 return llvm::any_of(only, [&](StringRef base) {
299 return kind.consume_front(base) &&
300 (kind.empty() || kind.starts_with(
"."));
305 std::vector<CodeAction> actions;
306 if (isKindAllowed(CodeAction::kQuickFix))
307 server.
getCodeActions(uri, params.range.start, params.context, actions);
308 reply(std::move(actions));
315void LSPServer::onConvertFromBytecode(
316 const MLIRConvertBytecodeParams ¶ms,
317 Callback<MLIRConvertBytecodeResult> reply) {
321void LSPServer::onConvertToBytecode(
const MLIRConvertBytecodeParams ¶ms,
322 Callback<MLIRConvertBytecodeResult> reply) {
331 JSONTransport &transport) {
332 LSPServer lspServer(server);
333 MessageHandler messageHandler(transport);
336 messageHandler.method(
"initialize", &lspServer, &LSPServer::onInitialize);
337 messageHandler.notification(
"initialized", &lspServer,
338 &LSPServer::onInitialized);
339 messageHandler.method(
"shutdown", &lspServer, &LSPServer::onShutdown);
342 messageHandler.notification(
"textDocument/didOpen", &lspServer,
343 &LSPServer::onDocumentDidOpen);
344 messageHandler.notification(
"textDocument/didClose", &lspServer,
345 &LSPServer::onDocumentDidClose);
346 messageHandler.notification(
"textDocument/didChange", &lspServer,
347 &LSPServer::onDocumentDidChange);
350 messageHandler.method(
"textDocument/definition", &lspServer,
351 &LSPServer::onGoToDefinition);
352 messageHandler.method(
"textDocument/references", &lspServer,
353 &LSPServer::onReference);
356 messageHandler.method(
"textDocument/hover", &lspServer, &LSPServer::onHover);
359 messageHandler.method(
"textDocument/documentSymbol", &lspServer,
360 &LSPServer::onDocumentSymbol);
363 messageHandler.method(
"textDocument/completion", &lspServer,
364 &LSPServer::onCompletion);
367 messageHandler.method(
"textDocument/codeAction", &lspServer,
368 &LSPServer::onCodeAction);
371 messageHandler.method(
"mlir/convertFromBytecode", &lspServer,
372 &LSPServer::onConvertFromBytecode);
373 messageHandler.method(
"mlir/convertToBytecode", &lspServer,
374 &LSPServer::onConvertToBytecode);
377 lspServer.publishDiagnostics =
378 messageHandler.outgoingNotification<PublishDiagnosticsParams>(
379 "textDocument/publishDiagnostics");
383 if (llvm::Error error = transport.run(messageHandler)) {
384 Logger::error(
"Transport error: {0}", error);
385 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.
void setWorkspaceRoot(StringRef root)
Set the workspace root for the server.
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.