MLIR  21.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"
15 #include "llvm/ADT/FunctionExtras.h"
16 #include "llvm/ADT/StringMap.h"
17 #include <optional>
18 
19 using namespace mlir;
20 using namespace mlir::lsp;
21 
22 //===----------------------------------------------------------------------===//
23 // LSPServer
24 //===----------------------------------------------------------------------===//
25 
26 namespace {
27 struct LSPServer {
28  LSPServer(TableGenServer &server, JSONTransport &transport)
29  : server(server), transport(transport) {}
30 
31  //===--------------------------------------------------------------------===//
32  // Initialization
33 
34  void onInitialize(const InitializeParams &params,
36  void onInitialized(const InitializedParams &params);
37  void onShutdown(const NoParams &params, Callback<std::nullptr_t> reply);
38 
39  //===--------------------------------------------------------------------===//
40  // Document Change
41 
42  void onDocumentDidOpen(const DidOpenTextDocumentParams &params);
43  void onDocumentDidClose(const DidCloseTextDocumentParams &params);
44  void onDocumentDidChange(const DidChangeTextDocumentParams &params);
45 
46  //===--------------------------------------------------------------------===//
47  // Definitions and References
48 
49  void onGoToDefinition(const TextDocumentPositionParams &params,
50  Callback<std::vector<Location>> reply);
51  void onReference(const ReferenceParams &params,
52  Callback<std::vector<Location>> reply);
53 
54  //===----------------------------------------------------------------------===//
55  // DocumentLink
56 
57  void onDocumentLink(const DocumentLinkParams &params,
58  Callback<std::vector<DocumentLink>> reply);
59 
60  //===--------------------------------------------------------------------===//
61  // Hover
62 
63  void onHover(const TextDocumentPositionParams &params,
64  Callback<std::optional<Hover>> reply);
65 
66  //===--------------------------------------------------------------------===//
67  // Fields
68  //===--------------------------------------------------------------------===//
69 
70  TableGenServer &server;
71  JSONTransport &transport;
72 
73  /// An outgoing notification used to send diagnostics to the client when they
74  /// are ready to be processed.
76 
77  /// Used to indicate that the 'shutdown' request was received from the
78  /// Language Server client.
79  bool shutdownRequestReceived = false;
80 };
81 } // namespace
82 
83 //===----------------------------------------------------------------------===//
84 // Initialization
85 //===----------------------------------------------------------------------===//
86 
87 void LSPServer::onInitialize(const InitializeParams &params,
89  // Send a response with the capabilities of this server.
90  llvm::json::Object serverCaps{
91  {"textDocumentSync",
92  llvm::json::Object{
93  {"openClose", true},
94  {"change", (int)TextDocumentSyncKind::Incremental},
95  {"save", true},
96  }},
97  {"definitionProvider", true},
98  {"referencesProvider", true},
99  {"documentLinkProvider",
100  llvm::json::Object{
101  {"resolveProvider", false},
102  }},
103  {"hoverProvider", true},
104  };
105 
106  llvm::json::Object result{
107  {{"serverInfo", llvm::json::Object{{"name", "tblgen-lsp-server"},
108  {"version", "0.0.1"}}},
109  {"capabilities", std::move(serverCaps)}}};
110  reply(std::move(result));
111 }
112 void LSPServer::onInitialized(const InitializedParams &) {}
113 void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {
114  shutdownRequestReceived = true;
115  reply(nullptr);
116 }
117 
118 //===----------------------------------------------------------------------===//
119 // Document Change
120 //===----------------------------------------------------------------------===//
121 
122 void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
123  PublishDiagnosticsParams diagParams(params.textDocument.uri,
124  params.textDocument.version);
125  server.addDocument(params.textDocument.uri, params.textDocument.text,
126  params.textDocument.version, diagParams.diagnostics);
127 
128  // Publish any recorded diagnostics.
129  publishDiagnostics(diagParams);
130 }
131 void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
132  std::optional<int64_t> version =
133  server.removeDocument(params.textDocument.uri);
134  if (!version)
135  return;
136 
137  // Empty out the diagnostics shown for this document. This will clear out
138  // anything currently displayed by the client for this document (e.g. in the
139  // "Problems" pane of VSCode).
140  publishDiagnostics(
141  PublishDiagnosticsParams(params.textDocument.uri, *version));
142 }
143 void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams &params) {
144  PublishDiagnosticsParams diagParams(params.textDocument.uri,
145  params.textDocument.version);
146  server.updateDocument(params.textDocument.uri, params.contentChanges,
147  params.textDocument.version, diagParams.diagnostics);
148 
149  // Publish any recorded diagnostics.
150  publishDiagnostics(diagParams);
151 }
152 
153 //===----------------------------------------------------------------------===//
154 // Definitions and References
155 //===----------------------------------------------------------------------===//
156 
157 void LSPServer::onGoToDefinition(const TextDocumentPositionParams &params,
158  Callback<std::vector<Location>> reply) {
159  std::vector<Location> locations;
160  server.getLocationsOf(params.textDocument.uri, params.position, locations);
161  reply(std::move(locations));
162 }
163 
164 void LSPServer::onReference(const ReferenceParams &params,
165  Callback<std::vector<Location>> reply) {
166  std::vector<Location> locations;
167  server.findReferencesOf(params.textDocument.uri, params.position, locations);
168  reply(std::move(locations));
169 }
170 
171 //===----------------------------------------------------------------------===//
172 // DocumentLink
173 //===----------------------------------------------------------------------===//
174 
175 void LSPServer::onDocumentLink(const DocumentLinkParams &params,
176  Callback<std::vector<DocumentLink>> reply) {
177  std::vector<DocumentLink> links;
178  server.getDocumentLinks(params.textDocument.uri, links);
179  reply(std::move(links));
180 }
181 
182 //===----------------------------------------------------------------------===//
183 // Hover
184 //===----------------------------------------------------------------------===//
185 
186 void LSPServer::onHover(const TextDocumentPositionParams &params,
187  Callback<std::optional<Hover>> reply) {
188  reply(server.findHover(params.textDocument.uri, params.position));
189 }
190 
191 //===----------------------------------------------------------------------===//
192 // Entry Point
193 //===----------------------------------------------------------------------===//
194 
196  JSONTransport &transport) {
197  LSPServer lspServer(server, transport);
198  MessageHandler messageHandler(transport);
199 
200  // Initialization
201  messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);
202  messageHandler.notification("initialized", &lspServer,
203  &LSPServer::onInitialized);
204  messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);
205 
206  // Document Changes
207  messageHandler.notification("textDocument/didOpen", &lspServer,
208  &LSPServer::onDocumentDidOpen);
209  messageHandler.notification("textDocument/didClose", &lspServer,
210  &LSPServer::onDocumentDidClose);
211  messageHandler.notification("textDocument/didChange", &lspServer,
212  &LSPServer::onDocumentDidChange);
213 
214  // Definitions and References
215  messageHandler.method("textDocument/definition", &lspServer,
216  &LSPServer::onGoToDefinition);
217  messageHandler.method("textDocument/references", &lspServer,
218  &LSPServer::onReference);
219 
220  // Document Link
221  messageHandler.method("textDocument/documentLink", &lspServer,
222  &LSPServer::onDocumentLink);
223 
224  // Hover
225  messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);
226 
227  // Diagnostics
228  lspServer.publishDiagnostics =
230  "textDocument/publishDiagnostics");
231 
232  // Run the main loop of the transport.
233  if (llvm::Error error = transport.run(messageHandler)) {
234  Logger::error("Transport error: {0}", error);
235  llvm::consumeError(std::move(error));
236  return failure();
237  }
238  return success(lspServer.shutdownRequestReceived);
239 }
A transport class that performs the JSON-RPC communication with the LSP client.
Definition: Transport.h:88
llvm::Error run(MessageHandler &handler)
Start executing the JSON-RPC transport.
Definition: Transport.cpp:210
static void error(const char *fmt, Ts &&...vals)
Definition: Logging.h:42
A handler used to process the incoming transport messages.
Definition: Transport.h:152
void notification(llvm::StringLiteral method, ThisT *thisPtr, void(ThisT::*handler)(const Param &))
Definition: Transport.h:194
void method(llvm::StringLiteral method, ThisT *thisPtr, void(ThisT::*handler)(const Param &, Callback< Result >))
Definition: Transport.h:181
OutgoingNotification< T > outgoingNotification(llvm::StringLiteral method)
Create an OutgoingNotification object used for the given method.
Definition: Transport.h:213
This class implements all of the TableGen related functionality necessary for a language server.
llvm::unique_function< void(const T &)> OutgoingNotification
An OutgoingNotification<T> is a function used for outgoing notifications send to the client.
Definition: Transport.h:136
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Transport.h:131
@ Incremental
Documents are synced by sending the full content on open.
llvm::LogicalResult runTableGenLSPServer(TableGenServer &server, JSONTransport &transport)
Run the main loop of the LSP server using the given TableGen server and transport.
Definition: LSPServer.cpp:195
Include the generated interface declarations.
VersionedTextDocumentIdentifier textDocument
The document that changed.
Definition: Protocol.h:503
std::vector< TextDocumentContentChangeEvent > contentChanges
The actual content changes.
Definition: Protocol.h:506
TextDocumentIdentifier textDocument
The document that was closed.
Definition: Protocol.h:469
TextDocumentItem textDocument
The document that was opened.
Definition: Protocol.h:456
Parameters for the document link request.
Definition: Protocol.h:1015
TextDocumentIdentifier textDocument
The document to provide document links for.
Definition: Protocol.h:1017
URIForFile uri
The text document's URI.
Definition: Protocol.h:250
int64_t version
The version number of this document.
Definition: Protocol.h:237
std::string text
The content of the opened text document.
Definition: Protocol.h:234
URIForFile uri
The text document's URI.
Definition: Protocol.h:228
TextDocumentIdentifier textDocument
The text document.
Definition: Protocol.h:419
Position position
The position inside the text document.
Definition: Protocol.h:422
int64_t version
The version number of this document.
Definition: Protocol.h:266
URIForFile uri
The text document's URI.
Definition: Protocol.h:264