https://github.com/dzbarsky updated https://github.com/llvm/llvm-project/pull/203121
>From a7565f229055522e375f732f8c007f136885c163 Mon Sep 17 00:00:00 2001 From: David Zbarsky <[email protected]> Date: Wed, 10 Jun 2026 19:15:23 -0400 Subject: [PATCH] [clangd][Support] Outline LSP payload decode errors Move failed payload handling from clangd::LSPBinder::parse<T> and llvm::lsp::MessageHandler::parse<T> into their non-inline handleParseError functions. Successful payload conversion remains specialized in each parse<T> instantiation. In a matched Release assertions-off Darwin arm64 build, clangd decreases by 33,584 bytes unstripped and 32,848 bytes stripped, with 25,180 fewer bytes in __TEXT,__text. Linked fixups are unchanged. A 16-pair successful-parse benchmark measured -4.4% CPU time with a 95% confidence interval of [-5.2%, -3.7%]. ClangdTests --gtest_filter=LSPBinderTest.* passes. llvm/lib/Support/LSP/Transport.cpp passes a standalone syntax compile. Co-authored-by: OpenAI Codex <[email protected]> --- clang-tools-extra/clangd/CMakeLists.txt | 1 + clang-tools-extra/clangd/LSPBinder.cpp | 36 +++++++++++++++++++ clang-tools-extra/clangd/LSPBinder.h | 20 ++++------- llvm/include/llvm/Support/LSP/Transport.h | 20 ++++------- llvm/lib/Support/LSP/Transport.cpp | 17 +++++++++ .../clang-tools-extra/clangd/BUILD.gn | 1 + .../clang-tools-extra/clangd/BUILD.bazel | 1 + 7 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 clang-tools-extra/clangd/LSPBinder.cpp 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", _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
