MLIR  22.0.0git
LSPServer.cpp
Go to the documentation of this file.
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-exception
6 //
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 
17 using namespace mlir;
18 using namespace mlir::lsp;
19 
20 using llvm::lsp::Callback;
21 using llvm::lsp::DidChangeTextDocumentParams;
22 using llvm::lsp::DidCloseTextDocumentParams;
23 using llvm::lsp::DidOpenTextDocumentParams;
24 using llvm::lsp::DocumentLinkParams;
25 using llvm::lsp::Hover;
26 using llvm::lsp::InitializedParams;
27 using llvm::lsp::InitializeParams;
28 using llvm::lsp::JSONTransport;
29 using llvm::lsp::Location;
30 using llvm::lsp::Logger;
31 using llvm::lsp::MessageHandler;
32 using llvm::lsp::NoParams;
33 using llvm::lsp::OutgoingNotification;
34 using llvm::lsp::PublishDiagnosticsParams;
35 using llvm::lsp::ReferenceParams;
36 using llvm::lsp::TextDocumentPositionParams;
37 using llvm::lsp::TextDocumentSyncKind;
38 
39 //===----------------------------------------------------------------------===//
40 // LSPServer
41 //===----------------------------------------------------------------------===//
42 
43 namespace {
44 struct LSPServer {
45  LSPServer(TableGenServer &server, JSONTransport &transport)
46  : server(server), transport(transport) {}
47 
48  //===--------------------------------------------------------------------===//
49  // Initialization
50 
51  void onInitialize(const InitializeParams &params,
52  Callback<llvm::json::Value> reply);
53  void onInitialized(const InitializedParams &params);
54  void onShutdown(const NoParams &params, Callback<std::nullptr_t> reply);
55 
56  //===--------------------------------------------------------------------===//
57  // Document Change
58 
59  void onDocumentDidOpen(const DidOpenTextDocumentParams &params);
60  void onDocumentDidClose(const DidCloseTextDocumentParams &params);
61  void onDocumentDidChange(const DidChangeTextDocumentParams &params);
62 
63  //===--------------------------------------------------------------------===//
64  // Definitions and References
65 
66  void onGoToDefinition(const TextDocumentPositionParams &params,
67  Callback<std::vector<Location>> reply);
68  void onReference(const ReferenceParams &params,
69  Callback<std::vector<Location>> reply);
70 
71  //===----------------------------------------------------------------------===//
72  // DocumentLink
73 
74  void onDocumentLink(const DocumentLinkParams &params,
75  Callback<std::vector<DocumentLink>> reply);
76 
77  //===--------------------------------------------------------------------===//
78  // Hover
79 
80  void onHover(const TextDocumentPositionParams &params,
81  Callback<std::optional<Hover>> reply);
82 
83  //===--------------------------------------------------------------------===//
84  // Fields
85  //===--------------------------------------------------------------------===//
86 
87  TableGenServer &server;
88  JSONTransport &transport;
89 
90  /// An outgoing notification used to send diagnostics to the client when they
91  /// are ready to be processed.
92  OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;
93 
94  /// Used to indicate that the 'shutdown' request was received from the
95  /// Language Server client.
96  bool shutdownRequestReceived = false;
97 };
98 } // namespace
99 
100 //===----------------------------------------------------------------------===//
101 // Initialization
102 //===----------------------------------------------------------------------===//
103 
104 void LSPServer::onInitialize(const InitializeParams &params,
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 }
129 void LSPServer::onInitialized(const InitializedParams &) {}
130 void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {
131  shutdownRequestReceived = true;
132  reply(nullptr);
133 }
134 
135 //===----------------------------------------------------------------------===//
136 // Document Change
137 //===----------------------------------------------------------------------===//
138 
139 void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
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 }
148 void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
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 out
155  // anything currently displayed by the client for this document (e.g. in the
156  // "Problems" pane of VSCode).
157  publishDiagnostics(
158  PublishDiagnosticsParams(params.textDocument.uri, *version));
159 }
160 void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams &params) {
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 References
172 //===----------------------------------------------------------------------===//
173 
174 void LSPServer::onGoToDefinition(const TextDocumentPositionParams &params,
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 
181 void LSPServer::onReference(const ReferenceParams &params,
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 // DocumentLink
190 //===----------------------------------------------------------------------===//
191 
192 void LSPServer::onDocumentLink(const DocumentLinkParams &params,
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 // Hover
201 //===----------------------------------------------------------------------===//
202 
203 void LSPServer::onHover(const TextDocumentPositionParams &params,
204  Callback<std::optional<Hover>> reply) {
205  reply(server.findHover(params.textDocument.uri, params.position));
206 }
207 
208 //===----------------------------------------------------------------------===//
209 // Entry Point
210 //===----------------------------------------------------------------------===//
211 
212 LogicalResult mlir::lsp::runTableGenLSPServer(TableGenServer &server,
213  JSONTransport &transport) {
214  LSPServer lspServer(server, transport);
215  MessageHandler messageHandler(transport);
216 
217  // Initialization
218  messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);
219  messageHandler.notification("initialized", &lspServer,
220  &LSPServer::onInitialized);
221  messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);
222 
223  // Document Changes
224  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 References
232  messageHandler.method("textDocument/definition", &lspServer,
233  &LSPServer::onGoToDefinition);
234  messageHandler.method("textDocument/references", &lspServer,
235  &LSPServer::onReference);
236 
237  // Document Link
238  messageHandler.method("textDocument/documentLink", &lspServer,
239  &LSPServer::onDocumentLink);
240 
241  // Hover
242  messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);
243 
244  // Diagnostics
245  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 }
This class implements all of the TableGen related functionality necessary for a language server.
llvm::LogicalResult runTableGenLSPServer(TableGenServer &server, llvm::lsp::JSONTransport &transport)
Run the main loop of the LSP server using the given TableGen server and transport.
Include the generated interface declarations.