[llvm] [mlir] [LLVM][MLIR] Move LSP server support library from MLIR into LLVM (PR #157885)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 15 01:02:13 PDT 2025
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/157885 at github.com>
================
@@ -0,0 +1,369 @@
+//===--- JSONTransport.cpp - sending and receiving LSP messages over JSON -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LSP/Transport.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/LSP/Logging.h"
+#include "llvm/Support/LSP/Protocol.h"
+#include <atomic>
+#include <optional>
+#include <system_error>
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::lsp;
+
+//===----------------------------------------------------------------------===//
+// Reply
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// Function object to reply to an LSP call.
+/// Each instance must be called exactly once, otherwise:
+/// - if there was no reply, an error reply is sent
+/// - if there were multiple replies, only the first is sent
+class Reply {
+public:
+ Reply(const llvm::json::Value &Id, StringRef Method, JSONTransport &Transport,
+ std::mutex &TransportOutputMutex);
+ Reply(Reply &&Other);
+ Reply &operator=(Reply &&) = delete;
+ Reply(const Reply &) = delete;
+ Reply &operator=(const Reply &) = delete;
+
+ void operator()(llvm::Expected<llvm::json::Value> Reply);
+
+private:
+ std::string Method;
+ std::atomic<bool> Replied = {false};
+ llvm::json::Value Id;
+ JSONTransport *Transport;
+ std::mutex &TransportOutputMutex;
+};
+} // namespace
+
+Reply::Reply(const llvm::json::Value &Id, llvm::StringRef Method,
+ JSONTransport &Transport, std::mutex &TransportOutputMutex)
+ : Method(Method), Id(Id), Transport(&Transport),
+ TransportOutputMutex(TransportOutputMutex) {}
+
+Reply::Reply(Reply &&Other)
+ : Method(Other.Method), Replied(Other.Replied.load()),
+ Id(std::move(Other.Id)), Transport(Other.Transport),
+ TransportOutputMutex(Other.TransportOutputMutex) {
+ Other.Transport = nullptr;
+}
+
+void Reply::operator()(llvm::Expected<llvm::json::Value> Reply) {
+ if (Replied.exchange(true)) {
+ Logger::error("Replied twice to message {0}({1})", Method, Id);
+ assert(false && "must reply to each call only once!");
+ return;
+ }
+ assert(Transport && "expected valid transport to reply to");
+
+ std::lock_guard<std::mutex> TransportLock(TransportOutputMutex);
+ if (Reply) {
+ Logger::info("--> reply:{0}({1})", Method, Id);
+ Transport->reply(std::move(Id), std::move(Reply));
+ } else {
+ llvm::Error Error = Reply.takeError();
+ Logger::info("--> reply:{0}({1}): {2}", Method, Id, Error);
+ Transport->reply(std::move(Id), std::move(Error));
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// MessageHandler
+//===----------------------------------------------------------------------===//
+
+bool MessageHandler::onNotify(llvm::StringRef Method, llvm::json::Value Value) {
+ Logger::info("--> {0}", Method);
+
+ if (Method == "exit")
+ return false;
+ if (Method == "$cancel") {
+ // TODO: Add support for cancelling requests.
+ } else {
+ auto It = NotificationHandlers.find(Method);
+ if (It != NotificationHandlers.end())
+ It->second(std::move(Value));
+ }
+ return true;
+}
+
+bool MessageHandler::onCall(llvm::StringRef Method, llvm::json::Value Params,
+ llvm::json::Value Id) {
+ Logger::info("--> {0}({1})", Method, Id);
+
+ Reply Reply(Id, Method, Transport, TransportOutputMutex);
+
+ auto It = MethodHandlers.find(Method);
+ if (It != MethodHandlers.end()) {
+ It->second(std::move(Params), std::move(Reply));
+ } else {
+ Reply(llvm::make_error<LSPError>("method not found: " + Method.str(),
+ ErrorCode::MethodNotFound));
+ }
+ return true;
+}
+
+bool MessageHandler::onReply(llvm::json::Value Id,
+ llvm::Expected<llvm::json::Value> Result) {
+ // Find the response handler in the mapping. If it exists, move it out of the
+ // mapping and erase it.
+ ResponseHandlerTy ResponseHandler;
+ {
+ std::lock_guard<std::mutex> responseHandlersLock(ResponseHandlerTy);
----------------
RKSimon wrote:
@Bertik23 @nikic I'm seeing MSVC warnings from this line:
```
E:\llvm\llvm-project\llvm\lib\Support\LSP\Transport.cpp(123): warning C4930: 'std::lock_guard<std::mutex> responseHandlersLock(llvm::lsp::MessageHandler::ResponseHandlerTy)': prototyped function not called (was a variable definition intended?)
```
Should it be this instead?
```
std::lock_guard<std::mutex> responseHandlersLock(ResponseHandler);
```
https://github.com/llvm/llvm-project/pull/157885
More information about the llvm-commits
mailing list