381 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "LSPServer.h"10 11#include "PDLLServer.h"12#include "Protocol.h"13#include "llvm/Support/LSP/Logging.h"14#include "llvm/Support/LSP/Protocol.h"15#include "llvm/Support/LSP/Transport.h"16#include <optional>17 18#define DEBUG_TYPE "pdll-lsp-server"19 20using namespace mlir;21using namespace mlir::lsp;22 23using llvm::lsp::Callback;24using llvm::lsp::CompletionList;25using llvm::lsp::CompletionParams;26using llvm::lsp::DidChangeTextDocumentParams;27using llvm::lsp::DidCloseTextDocumentParams;28using llvm::lsp::DidOpenTextDocumentParams;29using llvm::lsp::DocumentLinkParams;30using llvm::lsp::DocumentSymbol;31using llvm::lsp::DocumentSymbolParams;32using llvm::lsp::Hover;33using llvm::lsp::InitializedParams;34using llvm::lsp::InitializeParams;35using llvm::lsp::InlayHintsParams;36using llvm::lsp::JSONTransport;37using llvm::lsp::Location;38using llvm::lsp::Logger;39using 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;46 47//===----------------------------------------------------------------------===//48// LSPServer49//===----------------------------------------------------------------------===//50 51namespace {52struct LSPServer {53 LSPServer(PDLLServer &server, JSONTransport &transport)54 : server(server), transport(transport) {}55 56 //===--------------------------------------------------------------------===//57 // Initialization58 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);63 64 //===--------------------------------------------------------------------===//65 // Document Change66 67 void onDocumentDidOpen(const DidOpenTextDocumentParams ¶ms);68 void onDocumentDidClose(const DidCloseTextDocumentParams ¶ms);69 void onDocumentDidChange(const DidChangeTextDocumentParams ¶ms);70 71 //===--------------------------------------------------------------------===//72 // Definitions and References73 74 void onGoToDefinition(const TextDocumentPositionParams ¶ms,75 Callback<std::vector<Location>> reply);76 void onReference(const ReferenceParams ¶ms,77 Callback<std::vector<Location>> reply);78 79 //===----------------------------------------------------------------------===//80 // DocumentLink81 82 void onDocumentLink(const DocumentLinkParams ¶ms,83 Callback<std::vector<DocumentLink>> reply);84 85 //===--------------------------------------------------------------------===//86 // Hover87 88 void onHover(const TextDocumentPositionParams ¶ms,89 Callback<std::optional<Hover>> reply);90 91 //===--------------------------------------------------------------------===//92 // Document Symbols93 94 void onDocumentSymbol(const DocumentSymbolParams ¶ms,95 Callback<std::vector<DocumentSymbol>> reply);96 97 //===--------------------------------------------------------------------===//98 // Code Completion99 100 void onCompletion(const CompletionParams ¶ms,101 Callback<CompletionList> reply);102 103 //===--------------------------------------------------------------------===//104 // Signature Help105 106 void onSignatureHelp(const TextDocumentPositionParams ¶ms,107 Callback<SignatureHelp> reply);108 109 //===--------------------------------------------------------------------===//110 // Inlay Hints111 112 void onInlayHint(const InlayHintsParams ¶ms,113 Callback<std::vector<InlayHint>> reply);114 115 //===--------------------------------------------------------------------===//116 // PDLL View Output117 118 void onPDLLViewOutput(const PDLLViewOutputParams ¶ms,119 Callback<std::optional<PDLLViewOutputResult>> reply);120 121 //===--------------------------------------------------------------------===//122 // Fields123 //===--------------------------------------------------------------------===//124 125 PDLLServer &server;126 JSONTransport &transport;127 128 /// An outgoing notification used to send diagnostics to the client when they129 /// are ready to be processed.130 OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;131 132 /// Used to indicate that the 'shutdown' request was received from the133 /// Language Server client.134 bool shutdownRequestReceived = false;135};136} // namespace137 138//===----------------------------------------------------------------------===//139// Initialization140//===----------------------------------------------------------------------===//141 142void LSPServer::onInitialize(const InitializeParams ¶ms,143 Callback<llvm::json::Value> reply) {144 // Send a response with the capabilities of this server.145 llvm::json::Object serverCaps{146 {"textDocumentSync",147 llvm::json::Object{148 {"openClose", true},149 {"change", (int)TextDocumentSyncKind::Incremental},150 {"save", true},151 }},152 {"completionProvider",153 llvm::json::Object{154 {"allCommitCharacters",155 {"\t", "(", ")", "[", "]", "{", "}", "<", ">",156 ":", ";", ",", "+", "-", "/", "*", "%", "^",157 "&", "#", "?", ".", "=", "\"", "'", "|"}},158 {"resolveProvider", false},159 {"triggerCharacters",160 {".", ">", "(", "{", ",", "<", ":", "[", " ", "\"", "/"}},161 }},162 {"signatureHelpProvider",163 llvm::json::Object{164 {"triggerCharacters", {"(", ","}},165 }},166 {"definitionProvider", true},167 {"referencesProvider", true},168 {"documentLinkProvider",169 llvm::json::Object{170 {"resolveProvider", false},171 }},172 {"hoverProvider", true},173 {"documentSymbolProvider", true},174 {"inlayHintProvider", true},175 };176 177 llvm::json::Object result{178 {{"serverInfo", llvm::json::Object{{"name", "mlir-pdll-lsp-server"},179 {"version", "0.0.1"}}},180 {"capabilities", std::move(serverCaps)}}};181 reply(std::move(result));182}183void LSPServer::onInitialized(const InitializedParams &) {}184void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {185 shutdownRequestReceived = true;186 reply(nullptr);187}188 189//===----------------------------------------------------------------------===//190// Document Change191//===----------------------------------------------------------------------===//192 193void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams ¶ms) {194 PublishDiagnosticsParams diagParams(params.textDocument.uri,195 params.textDocument.version);196 server.addDocument(params.textDocument.uri, params.textDocument.text,197 params.textDocument.version, diagParams.diagnostics);198 199 // Publish any recorded diagnostics.200 publishDiagnostics(diagParams);201}202void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams ¶ms) {203 std::optional<int64_t> version =204 server.removeDocument(params.textDocument.uri);205 if (!version)206 return;207 208 // Empty out the diagnostics shown for this document. This will clear out209 // anything currently displayed by the client for this document (e.g. in the210 // "Problems" pane of VSCode).211 publishDiagnostics(212 PublishDiagnosticsParams(params.textDocument.uri, *version));213}214void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams ¶ms) {215 PublishDiagnosticsParams diagParams(params.textDocument.uri,216 params.textDocument.version);217 server.updateDocument(params.textDocument.uri, params.contentChanges,218 params.textDocument.version, diagParams.diagnostics);219 220 // Publish any recorded diagnostics.221 publishDiagnostics(diagParams);222}223 224//===----------------------------------------------------------------------===//225// Definitions and References226//===----------------------------------------------------------------------===//227 228void LSPServer::onGoToDefinition(const TextDocumentPositionParams ¶ms,229 Callback<std::vector<Location>> reply) {230 std::vector<Location> locations;231 server.getLocationsOf(params.textDocument.uri, params.position, locations);232 reply(std::move(locations));233}234 235void LSPServer::onReference(const ReferenceParams ¶ms,236 Callback<std::vector<Location>> reply) {237 std::vector<Location> locations;238 server.findReferencesOf(params.textDocument.uri, params.position, locations);239 reply(std::move(locations));240}241 242//===----------------------------------------------------------------------===//243// DocumentLink244//===----------------------------------------------------------------------===//245 246void LSPServer::onDocumentLink(const DocumentLinkParams ¶ms,247 Callback<std::vector<DocumentLink>> reply) {248 std::vector<DocumentLink> links;249 server.getDocumentLinks(params.textDocument.uri, links);250 reply(std::move(links));251}252 253//===----------------------------------------------------------------------===//254// Hover255//===----------------------------------------------------------------------===//256 257void LSPServer::onHover(const TextDocumentPositionParams ¶ms,258 Callback<std::optional<Hover>> reply) {259 reply(server.findHover(params.textDocument.uri, params.position));260}261 262//===----------------------------------------------------------------------===//263// Document Symbols264//===----------------------------------------------------------------------===//265 266void LSPServer::onDocumentSymbol(const DocumentSymbolParams ¶ms,267 Callback<std::vector<DocumentSymbol>> reply) {268 std::vector<DocumentSymbol> symbols;269 server.findDocumentSymbols(params.textDocument.uri, symbols);270 reply(std::move(symbols));271}272 273//===----------------------------------------------------------------------===//274// Code Completion275//===----------------------------------------------------------------------===//276 277void LSPServer::onCompletion(const CompletionParams ¶ms,278 Callback<CompletionList> reply) {279 reply(server.getCodeCompletion(params.textDocument.uri, params.position));280}281 282//===----------------------------------------------------------------------===//283// Signature Help284//===----------------------------------------------------------------------===//285 286void LSPServer::onSignatureHelp(const TextDocumentPositionParams ¶ms,287 Callback<SignatureHelp> reply) {288 reply(server.getSignatureHelp(params.textDocument.uri, params.position));289}290 291//===----------------------------------------------------------------------===//292// Inlay Hints293//===----------------------------------------------------------------------===//294 295void LSPServer::onInlayHint(const InlayHintsParams ¶ms,296 Callback<std::vector<InlayHint>> reply) {297 std::vector<InlayHint> hints;298 server.getInlayHints(params.textDocument.uri, params.range, hints);299 reply(std::move(hints));300}301 302//===----------------------------------------------------------------------===//303// PDLL ViewOutput304//===----------------------------------------------------------------------===//305 306void LSPServer::onPDLLViewOutput(307 const PDLLViewOutputParams ¶ms,308 Callback<std::optional<PDLLViewOutputResult>> reply) {309 reply(server.getPDLLViewOutput(params.uri, params.kind));310}311 312//===----------------------------------------------------------------------===//313// Entry Point314//===----------------------------------------------------------------------===//315 316LogicalResult mlir::lsp::runPdllLSPServer(PDLLServer &server,317 JSONTransport &transport) {318 LSPServer lspServer(server, transport);319 MessageHandler messageHandler(transport);320 321 // Initialization322 messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);323 messageHandler.notification("initialized", &lspServer,324 &LSPServer::onInitialized);325 messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);326 327 // Document Changes328 messageHandler.notification("textDocument/didOpen", &lspServer,329 &LSPServer::onDocumentDidOpen);330 messageHandler.notification("textDocument/didClose", &lspServer,331 &LSPServer::onDocumentDidClose);332 messageHandler.notification("textDocument/didChange", &lspServer,333 &LSPServer::onDocumentDidChange);334 335 // Definitions and References336 messageHandler.method("textDocument/definition", &lspServer,337 &LSPServer::onGoToDefinition);338 messageHandler.method("textDocument/references", &lspServer,339 &LSPServer::onReference);340 341 // Document Link342 messageHandler.method("textDocument/documentLink", &lspServer,343 &LSPServer::onDocumentLink);344 345 // Hover346 messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);347 348 // Document Symbols349 messageHandler.method("textDocument/documentSymbol", &lspServer,350 &LSPServer::onDocumentSymbol);351 352 // Code Completion353 messageHandler.method("textDocument/completion", &lspServer,354 &LSPServer::onCompletion);355 356 // Signature Help357 messageHandler.method("textDocument/signatureHelp", &lspServer,358 &LSPServer::onSignatureHelp);359 360 // Inlay Hints361 messageHandler.method("textDocument/inlayHint", &lspServer,362 &LSPServer::onInlayHint);363 364 // PDLL ViewOutput365 messageHandler.method("pdll/viewOutput", &lspServer,366 &LSPServer::onPDLLViewOutput);367 368 // Diagnostics369 lspServer.publishDiagnostics =370 messageHandler.outgoingNotification<PublishDiagnosticsParams>(371 "textDocument/publishDiagnostics");372 373 // Run the main loop of the transport.374 if (llvm::Error error = transport.run(messageHandler)) {375 Logger::error("Transport error: {0}", error);376 llvm::consumeError(std::move(error));377 return failure();378 }379 return success(lspServer.shutdownRequestReceived);380}381