xref: /llvm-project/mlir/lib/Tools/tblgen-lsp-server/LSPServer.cpp (revision a8c88de0dff865d1969b654bb5c0df181aa2df6a)
15de12bb7SRiver Riddle //===- LSPServer.cpp - TableGen Language Server ---------------------------===//
25de12bb7SRiver Riddle //
35de12bb7SRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45de12bb7SRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
55de12bb7SRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65de12bb7SRiver Riddle //
75de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
85de12bb7SRiver Riddle 
95de12bb7SRiver Riddle #include "LSPServer.h"
105de12bb7SRiver Riddle 
115de12bb7SRiver Riddle #include "TableGenServer.h"
12305d7185SRiver Riddle #include "mlir/Tools/lsp-server-support/Logging.h"
13305d7185SRiver Riddle #include "mlir/Tools/lsp-server-support/Protocol.h"
14305d7185SRiver Riddle #include "mlir/Tools/lsp-server-support/Transport.h"
155de12bb7SRiver Riddle #include "llvm/ADT/FunctionExtras.h"
165de12bb7SRiver Riddle #include "llvm/ADT/StringMap.h"
17a1fe1f5fSKazu Hirata #include <optional>
185de12bb7SRiver Riddle 
195de12bb7SRiver Riddle using namespace mlir;
205de12bb7SRiver Riddle using namespace mlir::lsp;
215de12bb7SRiver Riddle 
225de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
235de12bb7SRiver Riddle // LSPServer
245de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
255de12bb7SRiver Riddle 
265de12bb7SRiver Riddle namespace {
275de12bb7SRiver Riddle struct LSPServer {
LSPServer__anonbf2586cd0111::LSPServer285de12bb7SRiver Riddle   LSPServer(TableGenServer &server, JSONTransport &transport)
295de12bb7SRiver Riddle       : server(server), transport(transport) {}
305de12bb7SRiver Riddle 
315de12bb7SRiver Riddle   //===--------------------------------------------------------------------===//
325de12bb7SRiver Riddle   // Initialization
335de12bb7SRiver Riddle 
345de12bb7SRiver Riddle   void onInitialize(const InitializeParams &params,
355de12bb7SRiver Riddle                     Callback<llvm::json::Value> reply);
365de12bb7SRiver Riddle   void onInitialized(const InitializedParams &params);
375de12bb7SRiver Riddle   void onShutdown(const NoParams &params, Callback<std::nullptr_t> reply);
385de12bb7SRiver Riddle 
395de12bb7SRiver Riddle   //===--------------------------------------------------------------------===//
405de12bb7SRiver Riddle   // Document Change
415de12bb7SRiver Riddle 
425de12bb7SRiver Riddle   void onDocumentDidOpen(const DidOpenTextDocumentParams &params);
435de12bb7SRiver Riddle   void onDocumentDidClose(const DidCloseTextDocumentParams &params);
445de12bb7SRiver Riddle   void onDocumentDidChange(const DidChangeTextDocumentParams &params);
455de12bb7SRiver Riddle 
468d021670SRiver Riddle   //===--------------------------------------------------------------------===//
478d021670SRiver Riddle   // Definitions and References
488d021670SRiver Riddle 
498d021670SRiver Riddle   void onGoToDefinition(const TextDocumentPositionParams &params,
508d021670SRiver Riddle                         Callback<std::vector<Location>> reply);
518d021670SRiver Riddle   void onReference(const ReferenceParams &params,
528d021670SRiver Riddle                    Callback<std::vector<Location>> reply);
538d021670SRiver Riddle 
54682ca00eSRiver Riddle   //===----------------------------------------------------------------------===//
55682ca00eSRiver Riddle   // DocumentLink
56682ca00eSRiver Riddle 
57682ca00eSRiver Riddle   void onDocumentLink(const DocumentLinkParams &params,
58682ca00eSRiver Riddle                       Callback<std::vector<DocumentLink>> reply);
59682ca00eSRiver Riddle 
60682ca00eSRiver Riddle   //===--------------------------------------------------------------------===//
61682ca00eSRiver Riddle   // Hover
62682ca00eSRiver Riddle 
63682ca00eSRiver Riddle   void onHover(const TextDocumentPositionParams &params,
641da3a795SFangrui Song                Callback<std::optional<Hover>> reply);
65682ca00eSRiver Riddle 
665de12bb7SRiver Riddle   //===--------------------------------------------------------------------===//
675de12bb7SRiver Riddle   // Fields
685de12bb7SRiver Riddle   //===--------------------------------------------------------------------===//
695de12bb7SRiver Riddle 
705de12bb7SRiver Riddle   TableGenServer &server;
715de12bb7SRiver Riddle   JSONTransport &transport;
725de12bb7SRiver Riddle 
735de12bb7SRiver Riddle   /// An outgoing notification used to send diagnostics to the client when they
745de12bb7SRiver Riddle   /// are ready to be processed.
75*a8c88de0SBrian Gesiak   OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;
765de12bb7SRiver Riddle 
775de12bb7SRiver Riddle   /// Used to indicate that the 'shutdown' request was received from the
785de12bb7SRiver Riddle   /// Language Server client.
795de12bb7SRiver Riddle   bool shutdownRequestReceived = false;
805de12bb7SRiver Riddle };
815de12bb7SRiver Riddle } // namespace
825de12bb7SRiver Riddle 
835de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
845de12bb7SRiver Riddle // Initialization
855de12bb7SRiver Riddle 
onInitialize(const InitializeParams & params,Callback<llvm::json::Value> reply)865de12bb7SRiver Riddle void LSPServer::onInitialize(const InitializeParams &params,
875de12bb7SRiver Riddle                              Callback<llvm::json::Value> reply) {
885de12bb7SRiver Riddle   // Send a response with the capabilities of this server.
895de12bb7SRiver Riddle   llvm::json::Object serverCaps{
905de12bb7SRiver Riddle       {"textDocumentSync",
915de12bb7SRiver Riddle        llvm::json::Object{
925de12bb7SRiver Riddle            {"openClose", true},
936187178eSRiver Riddle            {"change", (int)TextDocumentSyncKind::Incremental},
945de12bb7SRiver Riddle            {"save", true},
955de12bb7SRiver Riddle        }},
968d021670SRiver Riddle       {"definitionProvider", true},
978d021670SRiver Riddle       {"referencesProvider", true},
98682ca00eSRiver Riddle       {"documentLinkProvider",
99682ca00eSRiver Riddle        llvm::json::Object{
100682ca00eSRiver Riddle            {"resolveProvider", false},
101682ca00eSRiver Riddle        }},
102682ca00eSRiver Riddle       {"hoverProvider", true},
1035de12bb7SRiver Riddle   };
1045de12bb7SRiver Riddle 
1055de12bb7SRiver Riddle   llvm::json::Object result{
1065de12bb7SRiver Riddle       {{"serverInfo", llvm::json::Object{{"name", "tblgen-lsp-server"},
1075de12bb7SRiver Riddle                                          {"version", "0.0.1"}}},
1085de12bb7SRiver Riddle        {"capabilities", std::move(serverCaps)}}};
1095de12bb7SRiver Riddle   reply(std::move(result));
1105de12bb7SRiver Riddle }
onInitialized(const InitializedParams &)1115de12bb7SRiver Riddle void LSPServer::onInitialized(const InitializedParams &) {}
onShutdown(const NoParams &,Callback<std::nullptr_t> reply)1125de12bb7SRiver Riddle void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {
1135de12bb7SRiver Riddle   shutdownRequestReceived = true;
1145de12bb7SRiver Riddle   reply(nullptr);
1155de12bb7SRiver Riddle }
1165de12bb7SRiver Riddle 
1175de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
1185de12bb7SRiver Riddle // Document Change
1195de12bb7SRiver Riddle 
onDocumentDidOpen(const DidOpenTextDocumentParams & params)1205de12bb7SRiver Riddle void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
1215de12bb7SRiver Riddle   PublishDiagnosticsParams diagParams(params.textDocument.uri,
1225de12bb7SRiver Riddle                                       params.textDocument.version);
1236187178eSRiver Riddle   server.addDocument(params.textDocument.uri, params.textDocument.text,
1246187178eSRiver Riddle                      params.textDocument.version, diagParams.diagnostics);
1255de12bb7SRiver Riddle 
1265de12bb7SRiver Riddle   // Publish any recorded diagnostics.
1275de12bb7SRiver Riddle   publishDiagnostics(diagParams);
1285de12bb7SRiver Riddle }
onDocumentDidClose(const DidCloseTextDocumentParams & params)1295de12bb7SRiver Riddle void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
1300a81ace0SKazu Hirata   std::optional<int64_t> version =
1310a81ace0SKazu Hirata       server.removeDocument(params.textDocument.uri);
1325de12bb7SRiver Riddle   if (!version)
1335de12bb7SRiver Riddle     return;
1345de12bb7SRiver Riddle 
1355de12bb7SRiver Riddle   // Empty out the diagnostics shown for this document. This will clear out
1365de12bb7SRiver Riddle   // anything currently displayed by the client for this document (e.g. in the
1375de12bb7SRiver Riddle   // "Problems" pane of VSCode).
1385de12bb7SRiver Riddle   publishDiagnostics(
1395de12bb7SRiver Riddle       PublishDiagnosticsParams(params.textDocument.uri, *version));
1405de12bb7SRiver Riddle }
onDocumentDidChange(const DidChangeTextDocumentParams & params)1415de12bb7SRiver Riddle void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams &params) {
1425de12bb7SRiver Riddle   PublishDiagnosticsParams diagParams(params.textDocument.uri,
1435de12bb7SRiver Riddle                                       params.textDocument.version);
1446187178eSRiver Riddle   server.updateDocument(params.textDocument.uri, params.contentChanges,
1455de12bb7SRiver Riddle                         params.textDocument.version, diagParams.diagnostics);
1465de12bb7SRiver Riddle 
1475de12bb7SRiver Riddle   // Publish any recorded diagnostics.
1485de12bb7SRiver Riddle   publishDiagnostics(diagParams);
1495de12bb7SRiver Riddle }
1505de12bb7SRiver Riddle 
1515de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
1528d021670SRiver Riddle // Definitions and References
1538d021670SRiver Riddle 
onGoToDefinition(const TextDocumentPositionParams & params,Callback<std::vector<Location>> reply)1548d021670SRiver Riddle void LSPServer::onGoToDefinition(const TextDocumentPositionParams &params,
1558d021670SRiver Riddle                                  Callback<std::vector<Location>> reply) {
1568d021670SRiver Riddle   std::vector<Location> locations;
1578d021670SRiver Riddle   server.getLocationsOf(params.textDocument.uri, params.position, locations);
1588d021670SRiver Riddle   reply(std::move(locations));
1598d021670SRiver Riddle }
1608d021670SRiver Riddle 
onReference(const ReferenceParams & params,Callback<std::vector<Location>> reply)1618d021670SRiver Riddle void LSPServer::onReference(const ReferenceParams &params,
1628d021670SRiver Riddle                             Callback<std::vector<Location>> reply) {
1638d021670SRiver Riddle   std::vector<Location> locations;
1648d021670SRiver Riddle   server.findReferencesOf(params.textDocument.uri, params.position, locations);
1658d021670SRiver Riddle   reply(std::move(locations));
1668d021670SRiver Riddle }
1678d021670SRiver Riddle 
1688d021670SRiver Riddle //===----------------------------------------------------------------------===//
169682ca00eSRiver Riddle // DocumentLink
170682ca00eSRiver Riddle 
onDocumentLink(const DocumentLinkParams & params,Callback<std::vector<DocumentLink>> reply)171682ca00eSRiver Riddle void LSPServer::onDocumentLink(const DocumentLinkParams &params,
172682ca00eSRiver Riddle                                Callback<std::vector<DocumentLink>> reply) {
173682ca00eSRiver Riddle   std::vector<DocumentLink> links;
174682ca00eSRiver Riddle   server.getDocumentLinks(params.textDocument.uri, links);
175682ca00eSRiver Riddle   reply(std::move(links));
176682ca00eSRiver Riddle }
177682ca00eSRiver Riddle 
178682ca00eSRiver Riddle //===----------------------------------------------------------------------===//
179682ca00eSRiver Riddle // Hover
180682ca00eSRiver Riddle 
onHover(const TextDocumentPositionParams & params,Callback<std::optional<Hover>> reply)181682ca00eSRiver Riddle void LSPServer::onHover(const TextDocumentPositionParams &params,
1821da3a795SFangrui Song                         Callback<std::optional<Hover>> reply) {
183682ca00eSRiver Riddle   reply(server.findHover(params.textDocument.uri, params.position));
184682ca00eSRiver Riddle }
185682ca00eSRiver Riddle 
186682ca00eSRiver Riddle //===----------------------------------------------------------------------===//
1875de12bb7SRiver Riddle // Entry Point
1885de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
1895de12bb7SRiver Riddle 
runTableGenLSPServer(TableGenServer & server,JSONTransport & transport)1905de12bb7SRiver Riddle LogicalResult mlir::lsp::runTableGenLSPServer(TableGenServer &server,
1915de12bb7SRiver Riddle                                               JSONTransport &transport) {
1925de12bb7SRiver Riddle   LSPServer lspServer(server, transport);
1935de12bb7SRiver Riddle   MessageHandler messageHandler(transport);
1945de12bb7SRiver Riddle 
1955de12bb7SRiver Riddle   // Initialization
1965de12bb7SRiver Riddle   messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);
1975de12bb7SRiver Riddle   messageHandler.notification("initialized", &lspServer,
1985de12bb7SRiver Riddle                               &LSPServer::onInitialized);
1995de12bb7SRiver Riddle   messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);
2005de12bb7SRiver Riddle 
2015de12bb7SRiver Riddle   // Document Changes
2025de12bb7SRiver Riddle   messageHandler.notification("textDocument/didOpen", &lspServer,
2035de12bb7SRiver Riddle                               &LSPServer::onDocumentDidOpen);
2045de12bb7SRiver Riddle   messageHandler.notification("textDocument/didClose", &lspServer,
2055de12bb7SRiver Riddle                               &LSPServer::onDocumentDidClose);
2065de12bb7SRiver Riddle   messageHandler.notification("textDocument/didChange", &lspServer,
2075de12bb7SRiver Riddle                               &LSPServer::onDocumentDidChange);
2085de12bb7SRiver Riddle 
2098d021670SRiver Riddle   // Definitions and References
2108d021670SRiver Riddle   messageHandler.method("textDocument/definition", &lspServer,
2118d021670SRiver Riddle                         &LSPServer::onGoToDefinition);
2128d021670SRiver Riddle   messageHandler.method("textDocument/references", &lspServer,
2138d021670SRiver Riddle                         &LSPServer::onReference);
2148d021670SRiver Riddle 
215682ca00eSRiver Riddle   // Document Link
216682ca00eSRiver Riddle   messageHandler.method("textDocument/documentLink", &lspServer,
217682ca00eSRiver Riddle                         &LSPServer::onDocumentLink);
218682ca00eSRiver Riddle 
219682ca00eSRiver Riddle   // Hover
220682ca00eSRiver Riddle   messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);
221682ca00eSRiver Riddle 
2225de12bb7SRiver Riddle   // Diagnostics
2235de12bb7SRiver Riddle   lspServer.publishDiagnostics =
2245de12bb7SRiver Riddle       messageHandler.outgoingNotification<PublishDiagnosticsParams>(
2255de12bb7SRiver Riddle           "textDocument/publishDiagnostics");
2265de12bb7SRiver Riddle 
2275de12bb7SRiver Riddle   // Run the main loop of the transport.
2285de12bb7SRiver Riddle   if (llvm::Error error = transport.run(messageHandler)) {
2295de12bb7SRiver Riddle     Logger::error("Transport error: {0}", error);
2305de12bb7SRiver Riddle     llvm::consumeError(std::move(error));
2315de12bb7SRiver Riddle     return failure();
2325de12bb7SRiver Riddle   }
2335de12bb7SRiver Riddle   return success(lspServer.shutdownRequestReceived);
2345de12bb7SRiver Riddle }
235