MLIR  22.0.0git
LSPServer.cpp
Go to the documentation of this file.
1 //===- LSPServer.cpp - MLIR 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 #include "MLIRServer.h"
11 #include "Protocol.h"
14 #include <optional>
15 
16 #define DEBUG_TYPE "mlir-lsp-server"
17 
18 using namespace mlir;
19 using namespace mlir::lsp;
20 
21 //===----------------------------------------------------------------------===//
22 // LSPServer
23 //===----------------------------------------------------------------------===//
24 
25 namespace {
26 struct LSPServer {
27  LSPServer(MLIRServer &server) : server(server) {}
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  // Hover
54 
55  void onHover(const TextDocumentPositionParams &params,
56  Callback<std::optional<Hover>> reply);
57 
58  //===--------------------------------------------------------------------===//
59  // Document Symbols
60 
61  void onDocumentSymbol(const DocumentSymbolParams &params,
62  Callback<std::vector<DocumentSymbol>> reply);
63 
64  //===--------------------------------------------------------------------===//
65  // Code Completion
66 
67  void onCompletion(const CompletionParams &params,
69 
70  //===--------------------------------------------------------------------===//
71  // Code Action
72 
73  void onCodeAction(const CodeActionParams &params,
75 
76  //===--------------------------------------------------------------------===//
77  // Bytecode
78 
79  void onConvertFromBytecode(const MLIRConvertBytecodeParams &params,
81  void onConvertToBytecode(const MLIRConvertBytecodeParams &params,
83 
84  //===--------------------------------------------------------------------===//
85  // Fields
86  //===--------------------------------------------------------------------===//
87 
88  MLIRServer &server;
89 
90  /// An outgoing notification used to send diagnostics to the client when they
91  /// are ready to be processed.
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,
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::Full},
112  {"save", true},
113  }},
114  {"completionProvider",
115  llvm::json::Object{
116  {"allCommitCharacters",
117  {
118  "\t",
119  ";",
120  ",",
121  ".",
122  "=",
123  }},
124  {"resolveProvider", false},
125  {"triggerCharacters",
126  {".", "%", "^", "!", "#", "(", ",", "<", ":", "[", " ", "\"", "/"}},
127  }},
128  {"definitionProvider", true},
129  {"referencesProvider", true},
130  {"hoverProvider", true},
131 
132  // For now we only support documenting symbols when the client supports
133  // hierarchical symbols.
134  {"documentSymbolProvider",
136  };
137 
138  // Per LSP, codeActionProvider can be either boolean or CodeActionOptions.
139  // CodeActionOptions is only valid if the client supports action literal
140  // via textDocument.codeAction.codeActionLiteralSupport.
141  serverCaps["codeActionProvider"] =
143  ? llvm::json::Object{{"codeActionKinds",
146  : llvm::json::Value(true);
147 
148  llvm::json::Object result{
149  {{"serverInfo",
150  llvm::json::Object{{"name", "mlir-lsp-server"}, {"version", "0.0.0"}}},
151  {"capabilities", std::move(serverCaps)}}};
152  reply(std::move(result));
153 }
154 void LSPServer::onInitialized(const InitializedParams &) {}
155 void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) {
156  shutdownRequestReceived = true;
157  reply(nullptr);
158 }
159 
160 //===----------------------------------------------------------------------===//
161 // Document Change
162 //===----------------------------------------------------------------------===//
163 
164 void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
165  PublishDiagnosticsParams diagParams(params.textDocument.uri,
166  params.textDocument.version);
167  server.addOrUpdateDocument(params.textDocument.uri, params.textDocument.text,
168  params.textDocument.version,
169  diagParams.diagnostics);
170 
171  // Publish any recorded diagnostics.
172  publishDiagnostics(diagParams);
173 }
174 void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
175  std::optional<int64_t> version =
176  server.removeDocument(params.textDocument.uri);
177  if (!version)
178  return;
179 
180  // Empty out the diagnostics shown for this document. This will clear out
181  // anything currently displayed by the client for this document (e.g. in the
182  // "Problems" pane of VSCode).
183  publishDiagnostics(
184  PublishDiagnosticsParams(params.textDocument.uri, *version));
185 }
186 void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams &params) {
187  // TODO: We currently only support full document updates, we should refactor
188  // to avoid this.
189  if (params.contentChanges.size() != 1)
190  return;
191  PublishDiagnosticsParams diagParams(params.textDocument.uri,
192  params.textDocument.version);
193  server.addOrUpdateDocument(
194  params.textDocument.uri, params.contentChanges.front().text,
195  params.textDocument.version, diagParams.diagnostics);
196 
197  // Publish any recorded diagnostics.
198  publishDiagnostics(diagParams);
199 }
200 
201 //===----------------------------------------------------------------------===//
202 // Definitions and References
203 //===----------------------------------------------------------------------===//
204 
205 void LSPServer::onGoToDefinition(const TextDocumentPositionParams &params,
206  Callback<std::vector<Location>> reply) {
207  std::vector<Location> locations;
208  server.getLocationsOf(params.textDocument.uri, params.position, locations);
209  reply(std::move(locations));
210 }
211 
212 void LSPServer::onReference(const ReferenceParams &params,
213  Callback<std::vector<Location>> reply) {
214  std::vector<Location> locations;
215  server.findReferencesOf(params.textDocument.uri, params.position, locations);
216  reply(std::move(locations));
217 }
218 
219 //===----------------------------------------------------------------------===//
220 // Hover
221 //===----------------------------------------------------------------------===//
222 
223 void LSPServer::onHover(const TextDocumentPositionParams &params,
224  Callback<std::optional<Hover>> reply) {
225  reply(server.findHover(params.textDocument.uri, params.position));
226 }
227 
228 //===----------------------------------------------------------------------===//
229 // Document Symbols
230 //===----------------------------------------------------------------------===//
231 
232 void LSPServer::onDocumentSymbol(const DocumentSymbolParams &params,
233  Callback<std::vector<DocumentSymbol>> reply) {
234  std::vector<DocumentSymbol> symbols;
235  server.findDocumentSymbols(params.textDocument.uri, symbols);
236  reply(std::move(symbols));
237 }
238 
239 //===----------------------------------------------------------------------===//
240 // Code Completion
241 //===----------------------------------------------------------------------===//
242 
243 void LSPServer::onCompletion(const CompletionParams &params,
244  Callback<CompletionList> reply) {
245  reply(server.getCodeCompletion(params.textDocument.uri, params.position));
246 }
247 
248 //===----------------------------------------------------------------------===//
249 // Code Action
250 //===----------------------------------------------------------------------===//
251 
252 void LSPServer::onCodeAction(const CodeActionParams &params,
254  URIForFile uri = params.textDocument.uri;
255 
256  // Check whether a particular CodeActionKind is included in the response.
257  auto isKindAllowed = [only(params.context.only)](StringRef kind) {
258  if (only.empty())
259  return true;
260  return llvm::any_of(only, [&](StringRef base) {
261  return kind.consume_front(base) &&
262  (kind.empty() || kind.starts_with("."));
263  });
264  };
265 
266  // We provide a code action for fixes on the specified diagnostics.
267  std::vector<CodeAction> actions;
268  if (isKindAllowed(CodeAction::kQuickFix))
269  server.getCodeActions(uri, params.range.start, params.context, actions);
270  reply(std::move(actions));
271 }
272 
273 //===----------------------------------------------------------------------===//
274 // Bytecode
275 //===----------------------------------------------------------------------===//
276 
277 void LSPServer::onConvertFromBytecode(
278  const MLIRConvertBytecodeParams &params,
280  reply(server.convertFromBytecode(params.uri));
281 }
282 
283 void LSPServer::onConvertToBytecode(const MLIRConvertBytecodeParams &params,
285  reply(server.convertToBytecode(params.uri));
286 }
287 
288 //===----------------------------------------------------------------------===//
289 // Entry point
290 //===----------------------------------------------------------------------===//
291 
292 LogicalResult lsp::runMlirLSPServer(MLIRServer &server,
293  JSONTransport &transport) {
294  LSPServer lspServer(server);
295  MessageHandler messageHandler(transport);
296 
297  // Initialization
298  messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize);
299  messageHandler.notification("initialized", &lspServer,
300  &LSPServer::onInitialized);
301  messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown);
302 
303  // Document Changes
304  messageHandler.notification("textDocument/didOpen", &lspServer,
305  &LSPServer::onDocumentDidOpen);
306  messageHandler.notification("textDocument/didClose", &lspServer,
307  &LSPServer::onDocumentDidClose);
308  messageHandler.notification("textDocument/didChange", &lspServer,
309  &LSPServer::onDocumentDidChange);
310 
311  // Definitions and References
312  messageHandler.method("textDocument/definition", &lspServer,
313  &LSPServer::onGoToDefinition);
314  messageHandler.method("textDocument/references", &lspServer,
315  &LSPServer::onReference);
316 
317  // Hover
318  messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);
319 
320  // Document Symbols
321  messageHandler.method("textDocument/documentSymbol", &lspServer,
322  &LSPServer::onDocumentSymbol);
323 
324  // Code Completion
325  messageHandler.method("textDocument/completion", &lspServer,
326  &LSPServer::onCompletion);
327 
328  // Code Action
329  messageHandler.method("textDocument/codeAction", &lspServer,
330  &LSPServer::onCodeAction);
331 
332  // Bytecode
333  messageHandler.method("mlir/convertFromBytecode", &lspServer,
334  &LSPServer::onConvertFromBytecode);
335  messageHandler.method("mlir/convertToBytecode", &lspServer,
336  &LSPServer::onConvertToBytecode);
337 
338  // Diagnostics
339  lspServer.publishDiagnostics =
341  "textDocument/publishDiagnostics");
342 
343  // Run the main loop of the transport.
344  LogicalResult result = success();
345  if (llvm::Error error = transport.run(messageHandler)) {
346  Logger::error("Transport error: {0}", error);
347  llvm::consumeError(std::move(error));
348  result = failure();
349  } else {
350  result = success(lspServer.shutdownRequestReceived);
351  }
352  return result;
353 }
union mlir::linalg::@1244::ArityGroupAndKind::Kind kind
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
This class implements all of the MLIR related functionality necessary for a language server.
Definition: MLIRServer.h:36
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
URI in "file" scheme for a file.
Definition: Protocol.h:97
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
@ Full
Documents are synced by always sending the full content of the document.
llvm::LogicalResult runMlirLSPServer(MLIRServer &server, JSONTransport &transport)
Run the main loop of the LSP server using the given MLIR server and transport.
Definition: LSPServer.cpp:292
Include the generated interface declarations.
bool codeActionStructure
Client supports CodeAction return value for textDocument/codeAction.
Definition: Protocol.h:160
bool hierarchicalDocumentSymbol
Client supports hierarchical document symbols.
Definition: Protocol.h:156
std::vector< std::string > only
Requested kind of actions to return.
Definition: Protocol.h:1163
TextDocumentIdentifier textDocument
The document in which the command was invoked.
Definition: Protocol.h:1176
Range range
The range for which the command was invoked.
Definition: Protocol.h:1179
CodeActionContext context
Context carrying additional information.
Definition: Protocol.h:1182
static const llvm::StringLiteral kRefactor
Definition: Protocol.h:1223
static const llvm::StringLiteral kInfo
Definition: Protocol.h:1224
static const llvm::StringLiteral kQuickFix
Definition: Protocol.h:1222
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
TextDocumentIdentifier textDocument
Definition: Protocol.h:639
ClientCapabilities capabilities
The capabilities provided by the client (editor or tool).
Definition: Protocol.h:205
This class represents the parameters used when converting between MLIR's bytecode and textual format.
Definition: Protocol.h:33
URIForFile uri
The input file containing the bytecode or textual format.
Definition: Protocol.h:35
Position start
The range's start position.
Definition: Protocol.h:345
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