[clang-tools-extra] d76057c - Add document outline symbols from unnamed contexts, e.g. extern "C".
Kadir Cetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 3 02:36:12 PDT 2020
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(
More information about the cfe-commits
mailing list