summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clangd/index/SymbolCollector.cpp17
-rw-r--r--clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp50
2 files changed, 62 insertions, 5 deletions
diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp
index b6673073d56..9f35380708b 100644
--- a/clang-tools-extra/clangd/index/SymbolCollector.cpp
+++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp
@@ -9,6 +9,7 @@
#include "SymbolCollector.h"
#include "../CodeCompletionStrings.h"
+#include "Logger.h"
#include "clang/AST/DeclCXX.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/SourceManager.h"
@@ -97,8 +98,8 @@ bool shouldFilterDecl(const NamedDecl *ND, ASTContext *ASTCtx,
// * symbols in namespaces or translation unit scopes (e.g. no class
// members)
// * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
- auto InTopLevelScope =
- hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()));
+ auto InTopLevelScope = hasDeclContext(
+ anyOf(namespaceDecl(), translationUnitDecl(), linkageSpecDecl()));
if (match(decl(allOf(Opts.IndexMainFiles
? decl()
: decl(unless(isExpansionInMainFile())),
@@ -180,7 +181,17 @@ bool SymbolCollector::handleDeclOccurence(
return true;
auto &SM = ND->getASTContext().getSourceManager();
- std::string QName = ND->getQualifiedNameAsString();
+
+ std::string QName;
+ llvm::raw_string_ostream OS(QName);
+ PrintingPolicy Policy(ASTCtx->getLangOpts());
+ // Note that inline namespaces are treated as transparent scopes. This
+ // reflects the way they're most commonly used for lookup. Ideally we'd
+ // include them, but at query time it's hard to find all the inline
+ // namespaces to query: the preamble doesn't have a dedicated list.
+ Policy.SuppressUnwrittenScope = true;
+ ND->printQualifiedName(OS, Policy);
+ OS.flush();
Symbol S;
S.ID = std::move(ID);
diff --git a/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp b/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp
index df55cb225e7..45dabf6d993 100644
--- a/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp
@@ -198,8 +198,7 @@ TEST_F(SymbolCollectorTest, IncludeEnums) {
runSymbolCollector(Header, /*Main=*/"");
EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Red"), QName("Color"),
QName("Green"), QName("Color2"),
- QName("ns"),
- QName("ns::Black")));
+ QName("ns"), QName("ns::Black")));
}
TEST_F(SymbolCollectorTest, IgnoreNamelessSymbols) {
@@ -321,6 +320,53 @@ TEST_F(SymbolCollectorTest, IgnoreClassMembers) {
EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Foo")));
}
+TEST_F(SymbolCollectorTest, Scopes) {
+ const std::string Header = R"(
+ namespace na {
+ class Foo {};
+ namespace nb {
+ class Bar {};
+ }
+ }
+ )";
+ runSymbolCollector(Header, /*Main=*/"");
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(QName("na"), QName("na::nb"),
+ QName("na::Foo"), QName("na::nb::Bar")));
+}
+
+TEST_F(SymbolCollectorTest, ExternC) {
+ const std::string Header = R"(
+ extern "C" { class Foo {}; }
+ namespace na {
+ extern "C" { class Bar {}; }
+ }
+ )";
+ runSymbolCollector(Header, /*Main=*/"");
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(QName("na"), QName("Foo"), QName("Bar")));
+}
+
+TEST_F(SymbolCollectorTest, SkipInlineNamespace) {
+ const std::string Header = R"(
+ namespace na {
+ inline namespace nb {
+ class Foo {};
+ }
+ }
+ namespace na {
+ // This is still inlined.
+ namespace nb {
+ class Bar {};
+ }
+ }
+ )";
+ runSymbolCollector(Header, /*Main=*/"");
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(QName("na"), QName("na::nb"),
+ QName("na::Foo"), QName("na::Bar")));
+}
+
TEST_F(SymbolCollectorTest, SymbolWithDocumentation) {
const std::string Header = R"(
namespace nx {
OpenPOWER on IntegriCloud