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