//===- LSPServer.cpp - PDLL Language Server -------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "LSPServer.h" #include "PDLLServer.h" #include "Protocol.h" #include "mlir/Tools/lsp-server-support/Logging.h" #include "mlir/Tools/lsp-server-support/Transport.h" #include "llvm/ADT/FunctionExtras.h" #include "llvm/ADT/StringMap.h" #include #define DEBUG_TYPE "pdll-lsp-server" using namespace mlir; using namespace mlir::lsp; //===----------------------------------------------------------------------===// // LSPServer //===----------------------------------------------------------------------===// namespace { struct LSPServer { LSPServer(PDLLServer &server, JSONTransport &transport) : server(server), transport(transport) {} //===--------------------------------------------------------------------===// // Initialization void onInitialize(const InitializeParams ¶ms, Callback reply); void onInitialized(const InitializedParams ¶ms); void onShutdown(const NoParams ¶ms, Callback reply); //===--------------------------------------------------------------------===// // Document Change void onDocumentDidOpen(const DidOpenTextDocumentParams ¶ms); void onDocumentDidClose(const DidCloseTextDocumentParams ¶ms); void onDocumentDidChange(const DidChangeTextDocumentParams ¶ms); //===--------------------------------------------------------------------===// // Definitions and References void onGoToDefinition(const TextDocumentPositionParams ¶ms, Callback> reply); void onReference(const ReferenceParams ¶ms, Callback> reply); //===----------------------------------------------------------------------===// // DocumentLink void onDocumentLink(const DocumentLinkParams ¶ms, Callback> reply); //===--------------------------------------------------------------------===// // Hover void onHover(const TextDocumentPositionParams ¶ms, Callback> reply); //===--------------------------------------------------------------------===// // Document Symbols void onDocumentSymbol(const DocumentSymbolParams ¶ms, Callback> reply); //===--------------------------------------------------------------------===// // Code Completion void onCompletion(const CompletionParams ¶ms, Callback reply); //===--------------------------------------------------------------------===// // Signature Help void onSignatureHelp(const TextDocumentPositionParams ¶ms, Callback reply); //===--------------------------------------------------------------------===// // Inlay Hints void onInlayHint(const InlayHintsParams ¶ms, Callback> reply); //===--------------------------------------------------------------------===// // PDLL View Output void onPDLLViewOutput(const PDLLViewOutputParams ¶ms, Callback> reply); //===--------------------------------------------------------------------===// // Fields //===--------------------------------------------------------------------===// PDLLServer &server; JSONTransport &transport; /// An outgoing notification used to send diagnostics to the client when they /// are ready to be processed. OutgoingNotification publishDiagnostics; /// Used to indicate that the 'shutdown' request was received from the /// Language Server client. bool shutdownRequestReceived = false; }; } // namespace //===----------------------------------------------------------------------===// // Initialization void LSPServer::onInitialize(const InitializeParams ¶ms, Callback reply) { // Send a response with the capabilities of this server. llvm::json::Object serverCaps{ {"textDocumentSync", llvm::json::Object{ {"openClose", true}, {"change", (int)TextDocumentSyncKind::Incremental}, {"save", true}, }}, {"completionProvider", llvm::json::Object{ {"allCommitCharacters", {"\t", "(", ")", "[", "]", "{", "}", "<", ">", ":", ";", ",", "+", "-", "/", "*", "%", "^", "&", "#", "?", ".", "=", "\"", "'", "|"}}, {"resolveProvider", false}, {"triggerCharacters", {".", ">", "(", "{", ",", "<", ":", "[", " ", "\"", "/"}}, }}, {"signatureHelpProvider", llvm::json::Object{ {"triggerCharacters", {"(", ","}}, }}, {"definitionProvider", true}, {"referencesProvider", true}, {"documentLinkProvider", llvm::json::Object{ {"resolveProvider", false}, }}, {"hoverProvider", true}, {"documentSymbolProvider", true}, {"inlayHintProvider", true}, }; llvm::json::Object result{ {{"serverInfo", llvm::json::Object{{"name", "mlir-pdll-lsp-server"}, {"version", "0.0.1"}}}, {"capabilities", std::move(serverCaps)}}}; reply(std::move(result)); } void LSPServer::onInitialized(const InitializedParams &) {} void LSPServer::onShutdown(const NoParams &, Callback reply) { shutdownRequestReceived = true; reply(nullptr); } //===----------------------------------------------------------------------===// // Document Change void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams ¶ms) { PublishDiagnosticsParams diagParams(params.textDocument.uri, params.textDocument.version); server.addDocument(params.textDocument.uri, params.textDocument.text, params.textDocument.version, diagParams.diagnostics); // Publish any recorded diagnostics. publishDiagnostics(diagParams); } void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams ¶ms) { std::optional version = server.removeDocument(params.textDocument.uri); if (!version) return; // Empty out the diagnostics shown for this document. This will clear out // anything currently displayed by the client for this document (e.g. in the // "Problems" pane of VSCode). publishDiagnostics( PublishDiagnosticsParams(params.textDocument.uri, *version)); } void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams ¶ms) { PublishDiagnosticsParams diagParams(params.textDocument.uri, params.textDocument.version); server.updateDocument(params.textDocument.uri, params.contentChanges, params.textDocument.version, diagParams.diagnostics); // Publish any recorded diagnostics. publishDiagnostics(diagParams); } //===----------------------------------------------------------------------===// // Definitions and References void LSPServer::onGoToDefinition(const TextDocumentPositionParams ¶ms, Callback> reply) { std::vector locations; server.getLocationsOf(params.textDocument.uri, params.position, locations); reply(std::move(locations)); } void LSPServer::onReference(const ReferenceParams ¶ms, Callback> reply) { std::vector locations; server.findReferencesOf(params.textDocument.uri, params.position, locations); reply(std::move(locations)); } //===----------------------------------------------------------------------===// // DocumentLink void LSPServer::onDocumentLink(const DocumentLinkParams ¶ms, Callback> reply) { std::vector links; server.getDocumentLinks(params.textDocument.uri, links); reply(std::move(links)); } //===----------------------------------------------------------------------===// // Hover void LSPServer::onHover(const TextDocumentPositionParams ¶ms, Callback> reply) { reply(server.findHover(params.textDocument.uri, params.position)); } //===----------------------------------------------------------------------===// // Document Symbols void LSPServer::onDocumentSymbol(const DocumentSymbolParams ¶ms, Callback> reply) { std::vector symbols; server.findDocumentSymbols(params.textDocument.uri, symbols); reply(std::move(symbols)); } //===----------------------------------------------------------------------===// // Code Completion void LSPServer::onCompletion(const CompletionParams ¶ms, Callback reply) { reply(server.getCodeCompletion(params.textDocument.uri, params.position)); } //===----------------------------------------------------------------------===// // Signature Help void LSPServer::onSignatureHelp(const TextDocumentPositionParams ¶ms, Callback reply) { reply(server.getSignatureHelp(params.textDocument.uri, params.position)); } //===----------------------------------------------------------------------===// // Inlay Hints void LSPServer::onInlayHint(const InlayHintsParams ¶ms, Callback> reply) { std::vector hints; server.getInlayHints(params.textDocument.uri, params.range, hints); reply(std::move(hints)); } //===----------------------------------------------------------------------===// // PDLL ViewOutput void LSPServer::onPDLLViewOutput( const PDLLViewOutputParams ¶ms, Callback> reply) { reply(server.getPDLLViewOutput(params.uri, params.kind)); } //===----------------------------------------------------------------------===// // Entry Point //===----------------------------------------------------------------------===// LogicalResult mlir::lsp::runPdllLSPServer(PDLLServer &server, JSONTransport &transport) { LSPServer lspServer(server, transport); MessageHandler messageHandler(transport); // Initialization messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize); messageHandler.notification("initialized", &lspServer, &LSPServer::onInitialized); messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown); // Document Changes messageHandler.notification("textDocument/didOpen", &lspServer, &LSPServer::onDocumentDidOpen); messageHandler.notification("textDocument/didClose", &lspServer, &LSPServer::onDocumentDidClose); messageHandler.notification("textDocument/didChange", &lspServer, &LSPServer::onDocumentDidChange); // Definitions and References messageHandler.method("textDocument/definition", &lspServer, &LSPServer::onGoToDefinition); messageHandler.method("textDocument/references", &lspServer, &LSPServer::onReference); // Document Link messageHandler.method("textDocument/documentLink", &lspServer, &LSPServer::onDocumentLink); // Hover messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover); // Document Symbols messageHandler.method("textDocument/documentSymbol", &lspServer, &LSPServer::onDocumentSymbol); // Code Completion messageHandler.method("textDocument/completion", &lspServer, &LSPServer::onCompletion); // Signature Help messageHandler.method("textDocument/signatureHelp", &lspServer, &LSPServer::onSignatureHelp); // Inlay Hints messageHandler.method("textDocument/inlayHint", &lspServer, &LSPServer::onInlayHint); // PDLL ViewOutput messageHandler.method("pdll/viewOutput", &lspServer, &LSPServer::onPDLLViewOutput); // Diagnostics lspServer.publishDiagnostics = messageHandler.outgoingNotification( "textDocument/publishDiagnostics"); // Run the main loop of the transport. if (llvm::Error error = transport.run(messageHandler)) { Logger::error("Transport error: {0}", error); llvm::consumeError(std::move(error)); return failure(); } return success(lspServer.shutdownRequestReceived); }