Author: Ilya Golovenko Date: 2020-08-03T11:34:56+02:00 New Revision: d76057c1fe6a368e9e422cf586e09fba827c96e1
URL: https://github.com/llvm/llvm-project/commit/d76057c1fe6a368e9e422cf586e09fba827c96e1 DIFF: https://github.com/llvm/llvm-project/commit/d76057c1fe6a368e9e422cf586e09fba827c96e1.diff LOG: Add document outline symbols from unnamed contexts, e.g. extern "C". It is necessary to traverse children of unnamed declaration contexts to get symbols which are currently missing in document outline, e.g.: extern "C" { void foo(); } Reviewed By: kadircet Differential Revision: https://reviews.llvm.org/D84839 Added: Modified: clang-tools-extra/clangd/FindSymbols.cpp clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp index f5d6a95aa713..247165698825 100644 --- a/clang-tools-extra/clangd/FindSymbols.cpp +++ b/clang-tools-extra/clangd/FindSymbols.cpp @@ -188,7 +188,7 @@ class DocumentOutline { } private: - enum class VisitKind { No, OnlyDecl, DeclAndChildren }; + enum class VisitKind { No, OnlyDecl, OnlyChildren, DeclAndChildren }; void traverseDecl(Decl *D, std::vector<DocumentSymbol> &Results) { if (auto *Templ = llvm::dyn_cast<TemplateDecl>(D)) { @@ -196,18 +196,25 @@ class DocumentOutline { if (auto *TD = Templ->getTemplatedDecl()) D = TD; } - auto *ND = llvm::dyn_cast<NamedDecl>(D); - if (!ND) - return; - VisitKind Visit = shouldVisit(ND); + + VisitKind Visit = shouldVisit(D); if (Visit == VisitKind::No) return; - llvm::Optional<DocumentSymbol> Sym = declToSym(AST.getASTContext(), *ND); + + if (Visit == VisitKind::OnlyChildren) + return traverseChildren(D, Results); + + auto *ND = llvm::cast<NamedDecl>(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<DocumentSymbol> &Results) { @@ -218,10 +225,16 @@ class DocumentOutline { traverseDecl(C, Results); } - VisitKind shouldVisit(NamedDecl *D) { + VisitKind shouldVisit(Decl *D) { if (D->isImplicit()) return VisitKind::No; + if (llvm::isa<LinkageSpecDecl>(D) || llvm::isa<ExportDecl>(D)) + return VisitKind::OnlyChildren; + + if (!llvm::isa<NamedDecl>(D)) + return VisitKind::No; + if (auto Func = llvm::dyn_cast<FunctionDecl>(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 index 07c42fcf2030..8576e11a5f21 100644 --- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp @@ -429,6 +429,40 @@ TEST(DocumentSymbols, ExternSymbol) { 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( _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits