Skip to content

Commit a0cc776

Browse files
authored
[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 #153355
1 parent 8c3daed commit a0cc776

File tree

7 files changed

+63
-2
lines changed

7 files changed

+63
-2
lines changed

clang-tools-extra/clangd/Config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ struct Config {
174174
struct {
175175
/// Whether hover show a.k.a type.
176176
bool ShowAKA = true;
177+
/// Limit the number of characters returned when hovering a macro;
178+
/// 0 is no limit.
179+
uint32_t MacroContentsLimit = 2048;
177180
} Hover;
178181

179182
struct {

clang-tools-extra/clangd/ConfigCompile.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,12 @@ struct FragmentCompiler {
727727
C.Hover.ShowAKA = ShowAKA;
728728
});
729729
}
730+
if (F.MacroContentsLimit) {
731+
Out.Apply.push_back(
732+
[Limit(**F.MacroContentsLimit)](const Params &, Config &C) {
733+
C.Hover.MacroContentsLimit = Limit;
734+
});
735+
}
730736
}
731737

732738
void compile(Fragment::InlayHintsBlock &&F) {

clang-tools-extra/clangd/ConfigFragment.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ struct Fragment {
361361
struct HoverBlock {
362362
/// Whether hover show a.k.a type.
363363
std::optional<Located<bool>> ShowAKA;
364+
/// Limit the number of characters returned when hovering a macro.
365+
std::optional<Located<uint32_t>> MacroContentsLimit;
364366
};
365367
HoverBlock Hover;
366368

clang-tools-extra/clangd/ConfigYAML.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,10 @@ class Parser {
264264
if (auto ShowAKA = boolValue(N, "ShowAKA"))
265265
F.ShowAKA = *ShowAKA;
266266
});
267+
Dict.handle("MacroContentsLimit", [&](Node &N) {
268+
if (auto MacroContentsLimit = uint32Value(N, "MacroContentsLimit"))
269+
F.MacroContentsLimit = *MacroContentsLimit;
270+
});
267271
Dict.parse(N);
268272
}
269273

clang-tools-extra/clangd/Hover.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,9 @@ HoverInfo getHoverContents(const DefinedMacro &Macro, const syntax::Token &Tok,
794794
for (const auto &ExpandedTok : Expansion->Expanded) {
795795
ExpansionText += ExpandedTok.text(SM);
796796
ExpansionText += " ";
797-
if (ExpansionText.size() > 2048) {
797+
const Config &Cfg = Config::current();
798+
const size_t Limit = static_cast<size_t>(Cfg.Hover.MacroContentsLimit);
799+
if (Limit && ExpansionText.size() > Limit) {
798800
ExpansionText.clear();
799801
break;
800802
}

clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,17 +230,19 @@ TEST(ParseYAML, CodePatterns) {
230230
EXPECT_THAT(Results[0].Completion.CodePatterns, llvm::ValueIs(val("None")));
231231
}
232232

233-
TEST(ParseYAML, ShowAKA) {
233+
TEST(ParseYAML, Hover) {
234234
CapturedDiags Diags;
235235
Annotations YAML(R"yaml(
236236
Hover:
237237
ShowAKA: True
238+
MacroContentsLimit: 4096
238239
)yaml");
239240
auto Results =
240241
Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
241242
ASSERT_THAT(Diags.Diagnostics, IsEmpty());
242243
ASSERT_EQ(Results.size(), 1u);
243244
EXPECT_THAT(Results[0].Hover.ShowAKA, llvm::ValueIs(val(true)));
245+
EXPECT_THAT(Results[0].Hover.MacroContentsLimit, llvm::ValueIs(val(4096U)));
244246
}
245247

246248
TEST(ParseYAML, InlayHints) {

clang-tools-extra/clangd/unittests/HoverTests.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4767,6 +4767,48 @@ constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) {
47674767
EXPECT_TRUE(H->Type);
47684768
}
47694769

4770+
TEST(Hover, HoverMacroContentsLimit) {
4771+
const char *const Code =
4772+
R"cpp(
4773+
#define C(A) A##A // Concatenate
4774+
#define E(A) C(A) // Expand
4775+
#define Z0032 00000000000000000000000000000000
4776+
#define Z0064 E(Z0032)
4777+
#define Z0128 E(Z0064)
4778+
#define Z0256 E(Z0128)
4779+
#define Z0512 E(Z0256)
4780+
#define Z1024 E(Z0512)
4781+
#define Z2048 E(Z1024)
4782+
#define Z4096 E(Z2048) // 4096 zeroes
4783+
int main() { return [[^Z4096]]; }
4784+
)cpp";
4785+
4786+
struct {
4787+
uint32_t MacroContentsLimit;
4788+
const std::string ExpectedDefinition;
4789+
} Cases[] = {
4790+
// With a limit of 2048, the macro expansion should get dropped.
4791+
{2048, "#define Z4096 E(Z2048)"},
4792+
// With a limit of 8192, the macro expansion should be fully expanded.
4793+
{8192, std::string("#define Z4096 E(Z2048)\n\n") +
4794+
std::string("// Expands to\n") + std::string(4096, '0')},
4795+
};
4796+
for (const auto &Case : Cases) {
4797+
SCOPED_TRACE(Code);
4798+
4799+
Annotations T(Code);
4800+
TestTU TU = TestTU::withCode(T.code());
4801+
auto AST = TU.build();
4802+
Config Cfg;
4803+
Cfg.Hover.MacroContentsLimit = Case.MacroContentsLimit;
4804+
WithContextValue WithCfg(Config::Key, std::move(Cfg));
4805+
auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
4806+
ASSERT_TRUE(H);
4807+
4808+
EXPECT_EQ(H->Definition, Case.ExpectedDefinition);
4809+
}
4810+
};
4811+
47704812
TEST(Hover, FunctionParameters) {
47714813
struct {
47724814
const char *const Code;

0 commit comments

Comments
 (0)