diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 06b949bc4a2b5..c3c5cf2732486 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -136,6 +136,15 @@ std::string getNamespaceScope(const Decl *D) { return ""; } +/// Compute the number of child statements in this statement. Includes the +/// statement itself. +size_t totalChildrenInStmt(const Stmt *Statement) { + size_t Count = 1; + for (const auto &Child : Statement->children()) + Count += totalChildrenInStmt(Child); + return Count; +} + std::string printDefinition(const Decl *D, PrintingPolicy PP, const syntax::TokenBuffer &TB) { if (auto *VD = llvm::dyn_cast(D)) { @@ -143,8 +152,9 @@ std::string printDefinition(const Decl *D, PrintingPolicy PP, // Initializers might be huge and result in lots of memory allocations in // some catostrophic cases. Such long lists are not useful in hover cards // anyway. - if (200 < TB.expandedTokens(IE->getSourceRange()).size()) - PP.SuppressInitializers = true; + PP.SuppressInitializers = + 200 < TB.expandedTokens(IE->getSourceRange()).size() || + 100 < totalChildrenInStmt(IE); } } std::string Definition; diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 35db757b9c15b..9b213da9ec844 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -3956,6 +3956,57 @@ TEST(Hover, HideBigInitializers) { EXPECT_EQ(H->Definition, "int arr[]"); } +TEST(Hover, HideBigInitializersIncludedFromThePreamble) { + Annotations T(R"cpp( + #include "hugearray.h" + auto x = a^rr; + )cpp"); + TestTU TU = TestTU::withCode(T.code()); + TU.AdditionalFiles["hugearray.h"] = R"cpp( + #define A(x) x, x, x, x + #define B(x) A(A(A(A(x)))) + int arr[256] = {B(0)}; + )cpp"; + auto AST = TU.build(); + auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); + ASSERT_TRUE(H); + EXPECT_EQ(H->Definition, "int arr[256]"); +} + +TEST(Hover, HideBigNestedInitializersIncludedFromThePreamble) { + Annotations T(R"cpp( + #include "hugearray.h" + auto x = a^rr; + )cpp"); + TestTU TU = TestTU::withCode(T.code()); + TU.AdditionalFiles["hugearray.h"] = R"cpp( + #define A(x) x, x, x, x + #define B(x) A(A(A(A(x)))) + int arr[1][1][256] = {{{B(0)}}}; + )cpp"; + auto AST = TU.build(); + auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); + ASSERT_TRUE(H); + EXPECT_EQ(H->Definition, "int arr[1][1][256]"); +} + +TEST(Hover, DoNotHideSmallInitializersIncludedFromThePreamble) { + Annotations T(R"cpp( + #include "smallarray.h" + auto x = a^rr; + )cpp"); + TestTU TU = TestTU::withCode(T.code()); + TU.AdditionalFiles["smallarray.h"] = R"cpp( + #define A(x) x, x + #define B(x) A(A(x)) + int arr[4] = {B(0)}; + )cpp"; + auto AST = TU.build(); + auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); + ASSERT_TRUE(H); + EXPECT_EQ(H->Definition, "int arr[4] = {0, 0, 0, 0}"); +} + #if defined(__aarch64__) // FIXME: AARCH64 sanitizer buildbots are broken after 72142fbac4. #define PREDEFINEMACROS_TEST(x) DISABLED_##x