diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp --- a/clang-tools-extra/clangd/FindSymbols.cpp +++ b/clang-tools-extra/clangd/FindSymbols.cpp @@ -188,7 +188,7 @@ } private: - enum class VisitKind { No, OnlyDecl, DeclAndChildren }; + enum class VisitKind { No, OnlyDecl, OnlyChildren, DeclAndChildren }; void traverseDecl(Decl *D, std::vector &Results) { if (auto *Templ = llvm::dyn_cast(D)) { @@ -196,18 +196,25 @@ if (auto *TD = Templ->getTemplatedDecl()) D = TD; } - auto *ND = llvm::dyn_cast(D); - if (!ND) - return; - VisitKind Visit = shouldVisit(ND); + + VisitKind Visit = shouldVisit(D); if (Visit == VisitKind::No) return; - llvm::Optional Sym = declToSym(AST.getASTContext(), *ND); + + if (Visit == VisitKind::OnlyChildren) + return traverseChildren(D, Results); + + auto *ND = llvm::cast(D); + auto Sym = declToSym(AST.getASTContext(), *ND); if (!Sym) return; - if (Visit == VisitKind::DeclAndChildren) - traverseChildren(D, Sym->children); Results.push_back(std::move(*Sym)); + + if (Visit == VisitKind::OnlyDecl) + return; + + assert(Visit == VisitKind::DeclAndChildren && "Unexpected VisitKind"); + traverseChildren(ND, Results.back().children); } void traverseChildren(Decl *D, std::vector &Results) { @@ -218,10 +225,16 @@ traverseDecl(C, Results); } - VisitKind shouldVisit(NamedDecl *D) { + VisitKind shouldVisit(Decl *D) { if (D->isImplicit()) return VisitKind::No; + if (llvm::isa(D) || llvm::isa(D)) + return VisitKind::OnlyChildren; + + if (!llvm::isa(D)) + return VisitKind::No; + if (auto Func = llvm::dyn_cast(D)) { // Some functions are implicit template instantiations, those should be // ignored. diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp --- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp @@ -429,6 +429,40 @@ EXPECT_THAT(getSymbols(TU.build()), IsEmpty()); } +TEST(DocumentSymbols, ExternContext) { + TestTU TU; + TU.Code = R"cpp( + extern "C" { + void foo(); + class Foo {}; + } + namespace ns { + extern "C" { + void bar(); + class Bar {}; + } + })cpp"; + + EXPECT_THAT(getSymbols(TU.build()), + ElementsAre(WithName("foo"), WithName("Foo"), + AllOf(WithName("ns"), + Children(WithName("bar"), WithName("Bar"))))); +} + +TEST(DocumentSymbols, ExportContext) { + TestTU TU; + TU.ExtraArgs = {"-std=c++20"}; + TU.Code = R"cpp( + export module test; + export { + void foo(); + class Foo {}; + })cpp"; + + EXPECT_THAT(getSymbols(TU.build()), + ElementsAre(WithName("foo"), WithName("Foo"))); +} + TEST(DocumentSymbols, NoLocals) { TestTU TU; TU.Code = R"cpp(