Author: Jaagup Averin
Date: 2025-08-28T00:19:08-04:00
New Revision: a0cc776732980e792b201e3848c1049dfc3b1836

URL: 
https://github.com/llvm/llvm-project/commit/a0cc776732980e792b201e3848c1049dfc3b1836
DIFF: 
https://github.com/llvm/llvm-project/commit/a0cc776732980e792b201e3848c1049dfc3b1836.diff

LOG: [clangd] Add Hover.MacroContentsLimit config option (#155105)

Currently macro expansions are hard capped at 2048. This PR adds
the `Hover.MacroContentsLimit` config option for overriding the default.

Fixes https://github.com/llvm/llvm-project/issues/153355

Added: 
    

Modified: 
    clang-tools-extra/clangd/Config.h
    clang-tools-extra/clangd/ConfigCompile.cpp
    clang-tools-extra/clangd/ConfigFragment.h
    clang-tools-extra/clangd/ConfigYAML.cpp
    clang-tools-extra/clangd/Hover.cpp
    clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
    clang-tools-extra/clangd/unittests/HoverTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/Config.h 
b/clang-tools-extra/clangd/Config.h
index 2e3e0a431ab1f..01997cee08515 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -174,6 +174,9 @@ struct Config {
   struct {
     /// Whether hover show a.k.a type.
     bool ShowAKA = true;
+    /// Limit the number of characters returned when hovering a macro;
+    /// 0 is no limit.
+    uint32_t MacroContentsLimit = 2048;
   } Hover;
 
   struct {

diff  --git a/clang-tools-extra/clangd/ConfigCompile.cpp 
b/clang-tools-extra/clangd/ConfigCompile.cpp
index 5dda6dd8bf712..962a48bcb7671 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -727,6 +727,12 @@ struct FragmentCompiler {
         C.Hover.ShowAKA = ShowAKA;
       });
     }
+    if (F.MacroContentsLimit) {
+      Out.Apply.push_back(
+          [Limit(**F.MacroContentsLimit)](const Params &, Config &C) {
+            C.Hover.MacroContentsLimit = Limit;
+          });
+    }
   }
 
   void compile(Fragment::InlayHintsBlock &&F) {

diff  --git a/clang-tools-extra/clangd/ConfigFragment.h 
b/clang-tools-extra/clangd/ConfigFragment.h
index 0f11f37e14698..2afeb36574b21 100644
--- a/clang-tools-extra/clangd/ConfigFragment.h
+++ b/clang-tools-extra/clangd/ConfigFragment.h
@@ -361,6 +361,8 @@ struct Fragment {
   struct HoverBlock {
     /// Whether hover show a.k.a type.
     std::optional<Located<bool>> ShowAKA;
+    /// Limit the number of characters returned when hovering a macro.
+    std::optional<Located<uint32_t>> MacroContentsLimit;
   };
   HoverBlock Hover;
 

diff  --git a/clang-tools-extra/clangd/ConfigYAML.cpp 
b/clang-tools-extra/clangd/ConfigYAML.cpp
index 289b7e8d1c49d..392cf19b05a55 100644
--- a/clang-tools-extra/clangd/ConfigYAML.cpp
+++ b/clang-tools-extra/clangd/ConfigYAML.cpp
@@ -264,6 +264,10 @@ class Parser {
       if (auto ShowAKA = boolValue(N, "ShowAKA"))
         F.ShowAKA = *ShowAKA;
     });
+    Dict.handle("MacroContentsLimit", [&](Node &N) {
+      if (auto MacroContentsLimit = uint32Value(N, "MacroContentsLimit"))
+        F.MacroContentsLimit = *MacroContentsLimit;
+    });
     Dict.parse(N);
   }
 

diff  --git a/clang-tools-extra/clangd/Hover.cpp 
b/clang-tools-extra/clangd/Hover.cpp
index 30c70ac02205b..9eec322fe5963 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -794,7 +794,9 @@ HoverInfo getHoverContents(const DefinedMacro &Macro, const 
syntax::Token &Tok,
     for (const auto &ExpandedTok : Expansion->Expanded) {
       ExpansionText += ExpandedTok.text(SM);
       ExpansionText += " ";
-      if (ExpansionText.size() > 2048) {
+      const Config &Cfg = Config::current();
+      const size_t Limit = static_cast<size_t>(Cfg.Hover.MacroContentsLimit);
+      if (Limit && ExpansionText.size() > Limit) {
         ExpansionText.clear();
         break;
       }

diff  --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp 
b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
index d71b8d5f9302a..d94e706ca05de 100644
--- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
@@ -230,17 +230,19 @@ TEST(ParseYAML, CodePatterns) {
   EXPECT_THAT(Results[0].Completion.CodePatterns, llvm::ValueIs(val("None")));
 }
 
-TEST(ParseYAML, ShowAKA) {
+TEST(ParseYAML, Hover) {
   CapturedDiags Diags;
   Annotations YAML(R"yaml(
 Hover:
   ShowAKA: True
+  MacroContentsLimit: 4096
   )yaml");
   auto Results =
       Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
   ASSERT_THAT(Diags.Diagnostics, IsEmpty());
   ASSERT_EQ(Results.size(), 1u);
   EXPECT_THAT(Results[0].Hover.ShowAKA, llvm::ValueIs(val(true)));
+  EXPECT_THAT(Results[0].Hover.MacroContentsLimit, llvm::ValueIs(val(4096U)));
 }
 
 TEST(ParseYAML, InlayHints) {

diff  --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp 
b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 537c061a1b04c..198102bbc9c29 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -4767,6 +4767,48 @@ constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) {
   EXPECT_TRUE(H->Type);
 }
 
+TEST(Hover, HoverMacroContentsLimit) {
+  const char *const Code =
+      R"cpp(
+          #define C(A) A##A // Concatenate
+          #define E(A) C(A) // Expand
+          #define Z0032 00000000000000000000000000000000
+          #define Z0064 E(Z0032)
+          #define Z0128 E(Z0064)
+          #define Z0256 E(Z0128)
+          #define Z0512 E(Z0256)
+          #define Z1024 E(Z0512)
+          #define Z2048 E(Z1024)
+          #define Z4096 E(Z2048) // 4096 zeroes
+          int main() { return [[^Z4096]]; }
+      )cpp";
+
+  struct {
+    uint32_t MacroContentsLimit;
+    const std::string ExpectedDefinition;
+  } Cases[] = {
+      // With a limit of 2048, the macro expansion should get dropped.
+      {2048, "#define Z4096 E(Z2048)"},
+      // With a limit of 8192, the macro expansion should be fully expanded.
+      {8192, std::string("#define Z4096 E(Z2048)\n\n") +
+                 std::string("// Expands to\n") + std::string(4096, '0')},
+  };
+  for (const auto &Case : Cases) {
+    SCOPED_TRACE(Code);
+
+    Annotations T(Code);
+    TestTU TU = TestTU::withCode(T.code());
+    auto AST = TU.build();
+    Config Cfg;
+    Cfg.Hover.MacroContentsLimit = Case.MacroContentsLimit;
+    WithContextValue WithCfg(Config::Key, std::move(Cfg));
+    auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
+    ASSERT_TRUE(H);
+
+    EXPECT_EQ(H->Definition, Case.ExpectedDefinition);
+  }
+};
+
 TEST(Hover, FunctionParameters) {
   struct {
     const char *const Code;


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to