257 lines · cpp
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-exception6//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// LSPServer41//===----------------------------------------------------------------------===//42 43namespace {44struct LSPServer {45 LSPServer(TableGenServer &server, JSONTransport &transport)46 : server(server), transport(transport) {}47 48 //===--------------------------------------------------------------------===//49 // Initialization50 51 void onInitialize(const InitializeParams ¶ms,52 Callback<llvm::json::Value> reply);53 void onInitialized(const InitializedParams ¶ms);54 void onShutdown(const NoParams ¶ms, Callback<std::nullptr_t> reply);55 56 //===--------------------------------------------------------------------===//57 // Document Change58 59 void onDocumentDidOpen(const DidOpenTextDocumentParams ¶ms);60 void onDocumentDidClose(const DidCloseTextDocumentParams ¶ms);61 void onDocumentDidChange(const DidChangeTextDocumentParams ¶ms);62 63 //===--------------------------------------------------------------------===//64 // Definitions and References65 66 void onGoToDefinition(const TextDocumentPositionParams ¶ms,67 Callback<std::vector<Location>> reply);68 void onReference(const ReferenceParams ¶ms,69 Callback<std::vector<Location>> reply);70 71 //===----------------------------------------------------------------------===//72 // DocumentLink73 74 void onDocumentLink(const DocumentLinkParams ¶ms,75 Callback<std::vector<DocumentLink>> reply);76 77 //===--------------------------------------------------------------------===//78 // Hover79 80 void onHover(const TextDocumentPositionParams ¶ms,81 Callback<std::optional<Hover>> reply);82 83 //===--------------------------------------------------------------------===//84 // Fields85 //===--------------------------------------------------------------------===//86 87 TableGenServer &server;88 JSONTransport &transport;89 90 /// An outgoing notification used to send diagnostics to the client when they91 /// are ready to be processed.92 OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;93 94 /// Used to indicate that the 'shutdown' request was received from the95 /// Language Server client.96 bool shutdownRequestReceived = false;97};98} // namespace99 100//===----------------------------------------------------------------------===//101// Initialization102//===----------------------------------------------------------------------===//103 104void LSPServer::onInitialize(const InitializeParams ¶ms,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 Change137//===----------------------------------------------------------------------===//138 139void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams ¶ms) {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 ¶ms) {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 out155 // anything currently displayed by the client for this document (e.g. in the156 // "Problems" pane of VSCode).157 publishDiagnostics(158 PublishDiagnosticsParams(params.textDocument.uri, *version));159}160void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams ¶ms) {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 References172//===----------------------------------------------------------------------===//173 174void LSPServer::onGoToDefinition(const TextDocumentPositionParams ¶ms,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 ¶ms,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// DocumentLink190//===----------------------------------------------------------------------===//191 192void LSPServer::onDocumentLink(const DocumentLinkParams ¶ms,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// Hover201//===----------------------------------------------------------------------===//202 203void LSPServer::onHover(const TextDocumentPositionParams ¶ms,204 Callback<std::optional<Hover>> reply) {205 reply(server.findHover(params.textDocument.uri, params.position));206}207 208//===----------------------------------------------------------------------===//209// Entry Point210//===----------------------------------------------------------------------===//211 212LogicalResult mlir::lsp::runTableGenLSPServer(TableGenServer &server,213 JSONTransport &transport) {214 LSPServer lspServer(server, transport);215 MessageHandler messageHandler(transport);216 217 // Initialization218 messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);219 messageHandler.notification("initialized", &lspServer,220 &LSPServer::onInitialized);221 messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);222 223 // Document Changes224 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 References232 messageHandler.method("textDocument/definition", &lspServer,233 &LSPServer::onGoToDefinition);234 messageHandler.method("textDocument/references", &lspServer,235 &LSPServer::onReference);236 237 // Document Link238 messageHandler.method("textDocument/documentLink", &lspServer,239 &LSPServer::onDocumentLink);240 241 // Hover242 messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);243 244 // Diagnostics245 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}257