[clang-tools-extra] 15ae01d - [clangd][Support] Outline LSP payload decode errors (#203121)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 16 22:38:25 PDT 2026
Author: David Zbarsky
Date: 2026-07-17T08:38:19+03:00
New Revision: 15ae01dd24261bd70947aab884098e5dcd4096dd
URL: https://github.com/llvm/llvm-project/commit/15ae01dd24261bd70947aab884098e5dcd4096dd
DIFF: https://github.com/llvm/llvm-project/commit/15ae01dd24261bd70947aab884098e5dcd4096dd.diff
LOG: [clangd][Support] Outline LSP payload decode errors (#203121)
Move failed payload handling from `clangd::LSPBinder::parse<T>` and
`llvm::lsp::MessageHandler::parse<T>` into their non-inline
`handleParseError` functions, while keeping successful payload
conversion specialized in each `parse<T>` instantiation.
For a Darwin arm64 build, stripped clangd decreased by 32,848 bytes and
`__TEXT,__text` decreased by 25,180 bytes.
`ClangdTests --gtest_filter=LSPBinderTest.*` passes, and
`llvm/lib/Support/LSP/Transport.cpp` passes a standalone syntax compile.
Work towards #202616
AI tool disclosure: Co-authored with OpenAI Codex.
Co-authored-by: OpenAI Codex <noreply at openai.com>
Added:
clang-tools-extra/clangd/LSPBinder.cpp
Modified:
clang-tools-extra/clangd/CMakeLists.txt
clang-tools-extra/clangd/LSPBinder.h
llvm/include/llvm/Support/LSP/Transport.h
llvm/lib/Support/LSP/Transport.cpp
llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt
index 890562dde1792..9fa7d92d8374c 100644
--- a/clang-tools-extra/clangd/CMakeLists.txt
+++ b/clang-tools-extra/clangd/CMakeLists.txt
@@ -96,6 +96,7 @@ add_clang_library(clangDaemon STATIC
IncludeFixer.cpp
InlayHints.cpp
JSONTransport.cpp
+ LSPBinder.cpp
ModulesBuilder.cpp
PathMapping.cpp
ProjectModules.cpp
diff --git a/clang-tools-extra/clangd/LSPBinder.cpp b/clang-tools-extra/clangd/LSPBinder.cpp
new file mode 100644
index 0000000000000..8e997776f3763
--- /dev/null
+++ b/clang-tools-extra/clangd/LSPBinder.cpp
@@ -0,0 +1,36 @@
+//===--- LSPBinder.cpp - Tables of LSP handlers --------------------------===//
+//
+// 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 "LSPBinder.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace clangd {
+
+// Keep handleParseError out of every parse<T> instantiation.
+LLVM_ATTRIBUTE_NOINLINE llvm::Error LSPBinder::handleParseError(
+ const llvm::json::Value &Raw, llvm::StringRef PayloadName,
+ llvm::StringRef PayloadKind, const llvm::json::Path::Root &Root) {
+ elog("Failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
+ Root.getError());
+ // Dump the relevant parts of the broken message.
+ std::string Context;
+ llvm::raw_string_ostream OS(Context);
+ Root.printErrorContext(Raw, OS);
+ vlog("{0}", OS.str());
+ // Report the error (e.g. to the client).
+ return llvm::make_error<LSPError>(
+ llvm::formatv("failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
+ fmt_consume(Root.getError())),
+ ErrorCode::InvalidParams);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clang-tools-extra/clangd/LSPBinder.h b/clang-tools-extra/clangd/LSPBinder.h
index 8542112681375..74b4bd0f708ff 100644
--- a/clang-tools-extra/clangd/LSPBinder.h
+++ b/clang-tools-extra/clangd/LSPBinder.h
@@ -101,6 +101,10 @@ class LSPBinder {
static llvm::Expected<T> parse(const llvm::json::Value &Raw,
llvm::StringRef PayloadName,
llvm::StringRef PayloadKind);
+ static llvm::Error handleParseError(const llvm::json::Value &Raw,
+ llvm::StringRef PayloadName,
+ llvm::StringRef PayloadKind,
+ const llvm::json::Path::Root &Root);
RawHandlers &Raw;
RawOutgoing &Out;
@@ -112,20 +116,8 @@ llvm::Expected<T> LSPBinder::parse(const llvm::json::Value &Raw,
llvm::StringRef PayloadKind) {
T Result;
llvm::json::Path::Root Root;
- if (!fromJSON(Raw, Result, Root)) {
- elog("Failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
- Root.getError());
- // Dump the relevant parts of the broken message.
- std::string Context;
- llvm::raw_string_ostream OS(Context);
- Root.printErrorContext(Raw, OS);
- vlog("{0}", OS.str());
- // Report the error (e.g. to the client).
- return llvm::make_error<LSPError>(
- llvm::formatv("failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
- fmt_consume(Root.getError())),
- ErrorCode::InvalidParams);
- }
+ if (!fromJSON(Raw, Result, Root))
+ return handleParseError(Raw, PayloadName, PayloadKind, Root);
return std::move(Result);
}
diff --git a/llvm/include/llvm/Support/LSP/Transport.h b/llvm/include/llvm/Support/LSP/Transport.h
index 6a0dd51d946bd..eee4a4e525fde 100644
--- a/llvm/include/llvm/Support/LSP/Transport.h
+++ b/llvm/include/llvm/Support/LSP/Transport.h
@@ -172,19 +172,9 @@ class MessageHandler {
StringRef PayloadName, StringRef PayloadKind) {
T Result;
llvm::json::Path::Root Root;
- if (fromJSON(Raw, Result, Root))
- return std::move(Result);
-
- // Dump the relevant parts of the broken message.
- std::string Context;
- llvm::raw_string_ostream Os(Context);
- Root.printErrorContext(Raw, Os);
-
- // Report the error (e.g. to the client).
- return llvm::make_error<LSPError>(
- llvm::formatv("failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
- fmt_consume(Root.getError())),
- ErrorCode::InvalidParams);
+ if (!fromJSON(Raw, Result, Root))
+ return handleParseError(Raw, PayloadName, PayloadKind, Root);
+ return std::move(Result);
}
template <typename Param, typename Result, typename ThisT>
@@ -266,6 +256,10 @@ class MessageHandler {
}
private:
+ LLVM_ABI static llvm::Error
+ handleParseError(const llvm::json::Value &Raw, StringRef PayloadName,
+ StringRef PayloadKind, const llvm::json::Path::Root &Root);
+
template <typename HandlerT>
using HandlerMap = llvm::StringMap<llvm::unique_function<HandlerT>>;
diff --git a/llvm/lib/Support/LSP/Transport.cpp b/llvm/lib/Support/LSP/Transport.cpp
index 31b5a89f9b5e0..e79ca679878d0 100644
--- a/llvm/lib/Support/LSP/Transport.cpp
+++ b/llvm/lib/Support/LSP/Transport.cpp
@@ -83,6 +83,23 @@ void Reply::operator()(llvm::Expected<llvm::json::Value> Reply) {
// MessageHandler
//===----------------------------------------------------------------------===//
+// Keep handleParseError out of every parse<T> instantiation.
+LLVM_ATTRIBUTE_NOINLINE llvm::Error
+MessageHandler::handleParseError(const llvm::json::Value &Raw,
+ StringRef PayloadName, StringRef PayloadKind,
+ const llvm::json::Path::Root &Root) {
+ // Dump the relevant parts of the broken message.
+ std::string Context;
+ llvm::raw_string_ostream Os(Context);
+ Root.printErrorContext(Raw, Os);
+
+ // Report the error (e.g. to the client).
+ return llvm::make_error<LSPError>(
+ llvm::formatv("failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
+ fmt_consume(Root.getError())),
+ ErrorCode::InvalidParams);
+}
+
bool MessageHandler::onNotify(llvm::StringRef Method, llvm::json::Value Value) {
Logger::info("--> {0}", Method);
diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
index 86f959816f958..f30aac6add176 100644
--- a/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
@@ -112,6 +112,7 @@ static_library("clangd") {
"IncludeFixer.cpp",
"InlayHints.cpp",
"JSONTransport.cpp",
+ "LSPBinder.cpp",
"ModulesBuilder.cpp",
"ParsedAST.cpp",
"PathMapping.cpp",
diff --git a/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel
index 4151e55a938d9..34d44e8f63512 100644
--- a/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel
@@ -36,6 +36,7 @@ cc_library(
"Feature.cpp",
"Features.inc",
"JSONTransport.cpp",
+ "LSPBinder.cpp",
"Protocol.cpp",
"URI.cpp",
"index/SymbolID.cpp",
More information about the cfe-commits
mailing list