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 <[email protected]>

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",


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to