13#include "llvm/Support/JSON.h"
14#include "llvm/Support/LSP/Protocol.h"
15#include "llvm/Support/LSP/Transport.h"
21#define DEBUG_TYPE "circt-verilog-lsp-server"
24using namespace llvm::lsp;
36 : server(server), transport(transport),
43 void onInitialize(
const InitializeParams ¶ms,
44 Callback<json::Value> reply);
45 void onInitialized(
const InitializedParams ¶ms);
46 void onShutdown(
const NoParams ¶ms, Callback<std::nullptr_t> reply);
52 void onDocumentDidOpen(
const DidOpenTextDocumentParams ¶ms);
53 void onDocumentDidClose(
const DidCloseTextDocumentParams ¶ms);
54 void onDocumentDidChange(
const DidChangeTextDocumentParams ¶ms);
60 void onGoToDefinition(
const TextDocumentPositionParams ¶ms,
61 Callback<std::vector<Location>> reply);
62 void onReference(
const ReferenceParams ¶ms,
63 Callback<std::vector<Location>> reply);
70 JSONTransport &transport;
73 void sendDiagnostics(
const PublishDiagnosticsParams &p) {
74 std::scoped_lock lk(diagnosticsMutex);
75 publishDiagnostics(p);
79 setPublishDiagnostics(OutgoingNotification<PublishDiagnosticsParams> diag) {
80 std::scoped_lock lk(diagnosticsMutex);
81 publishDiagnostics = std::move(diag);
86 bool shutdownRequestReceived =
false;
90 std::mutex diagnosticsMutex;
93 OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics;
104void LSPServer::onInitialize(
const InitializeParams ¶ms,
105 Callback<json::Value> reply) {
107 json::Object serverCaps{
112 {
"change", (int)TextDocumentSyncKind::Incremental},
118 {
"definitionProvider",
true},
119 {
"referencesProvider",
true},
123 {{
"serverInfo", json::Object{{
"name",
"circt-verilog-lsp-server"},
124 {
"version",
"0.0.1"}}},
125 {
"capabilities", std::move(serverCaps)}}};
126 reply(std::move(result));
128void LSPServer::onInitialized(
const InitializedParams &) {}
129void LSPServer::onShutdown(
const NoParams &, Callback<std::nullptr_t> reply) {
130 shutdownRequestReceived =
true;
131 pendingChanges.abort();
139void LSPServer::onDocumentDidOpen(
const DidOpenTextDocumentParams ¶ms) {
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);
146 sendDiagnostics(diagParams);
149void LSPServer::onDocumentDidClose(
const DidCloseTextDocumentParams ¶ms) {
150 pendingChanges.erase(params.textDocument.uri);
151 std::optional<int64_t> version =
152 server.removeDocument(params.textDocument.uri);
159 sendDiagnostics(PublishDiagnosticsParams(params.textDocument.uri, *version));
162void LSPServer::onDocumentDidChange(
const DidChangeTextDocumentParams ¶ms) {
163 pendingChanges.debounceAndUpdate(
164 params, debounceOptions,
165 [
this, params](std::unique_ptr<circt::lsp::PendingChanges> result) {
169 PublishDiagnosticsParams diagParams(params.textDocument.uri,
171 server.updateDocument(params.textDocument.uri, result->changes,
172 result->version, diagParams.diagnostics);
174 sendDiagnostics(diagParams);
182void LSPServer::onGoToDefinition(
const TextDocumentPositionParams ¶ms,
183 Callback<std::vector<Location>> reply) {
184 std::vector<Location> locations;
185 server.getLocationsOf(params.textDocument.uri, params.position, locations);
186 reply(std::move(locations));
189void LSPServer::onReference(
const ReferenceParams ¶ms,
190 Callback<std::vector<Location>> reply) {
191 std::vector<Location> locations;
192 server.findReferencesOf(params.textDocument.uri, params.position, locations);
193 reply(std::move(locations));
203 JSONTransport &transport) {
204 LSPServer lspServer(options,
server, transport);
205 MessageHandler messageHandler(transport);
208 lspServer.setPublishDiagnostics(
209 messageHandler.outgoingNotification<PublishDiagnosticsParams>(
210 "textDocument/publishDiagnostics"));
213 messageHandler.method(
"initialize", &lspServer, &LSPServer::onInitialize);
214 messageHandler.notification(
"initialized", &lspServer,
215 &LSPServer::onInitialized);
216 messageHandler.method(
"shutdown", &lspServer, &LSPServer::onShutdown);
219 messageHandler.notification(
"textDocument/didOpen", &lspServer,
220 &LSPServer::onDocumentDidOpen);
221 messageHandler.notification(
"textDocument/didClose", &lspServer,
222 &LSPServer::onDocumentDidClose);
224 messageHandler.notification(
"textDocument/didChange", &lspServer,
225 &LSPServer::onDocumentDidChange);
227 messageHandler.method(
"textDocument/definition", &lspServer,
228 &LSPServer::onGoToDefinition);
229 messageHandler.method(
"textDocument/references", &lspServer,
230 &LSPServer::onReference);
233 if (Error error = transport.run(messageHandler)) {
234 Logger::error(
"Transport error: {0}", error);
235 consumeError(std::move(error));
239 return success(lspServer.shutdownRequestReceived);
static std::unique_ptr< RpcServer > server
Thread-safe accumulator + debouncer for text document changes.
This class implements all of the Verilog related functionality necessary for a language server.
llvm::LogicalResult runVerilogLSPServer(const LSPServerOptions &lspOptions, VerilogServer &server, llvm::lsp::JSONTransport &transport)
Run the main loop of the LSP server using the given Verilog server and transport.
Debounce tuning for document-change bursts.
static DebounceOptions fromLSPOptions(const circt::lsp::LSPServerOptions &opts)
Factory: build from server options. Keep mapping 1:1 for clarity.