diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -574,7 +574,7 @@ // FIXME: All MacroRefs are marked as Spelled now, but this should be checked. for (const auto &IDAndRefs : MacroRefs) for (const auto &LocAndRole : IDAndRefs.second) - CollectRef(IDAndRefs.first, LocAndRole); + CollectRef(IDAndRefs.first, LocAndRole, /*Spelled=*/true); // Populate Refs slab from DeclRefs. llvm::DenseMap> FilesToTokensCache; for (auto &DeclAndRef : DeclRefs) { @@ -592,7 +592,10 @@ const auto *IdentifierToken = spelledIdentifierTouching(LocAndRole.first, Tokens); DeclarationName Name = DeclAndRef.first->getDeclName(); - bool Spelled = IdentifierToken && Name.isIdentifier() && + const auto NameKind = Name.getNameKind(); + bool IsTargetKind = NameKind == DeclarationName::Identifier || + NameKind == DeclarationName::CXXConstructorName; + bool Spelled = IdentifierToken && IsTargetKind && Name.getAsString() == IdentifierToken->text(SM); CollectRef(*ID, LocAndRole, Spelled); } diff --git a/clang-tools-extra/clangd/index/SymbolID.h b/clang-tools-extra/clangd/index/SymbolID.h --- a/clang-tools-extra/clangd/index/SymbolID.h +++ b/clang-tools-extra/clangd/index/SymbolID.h @@ -36,6 +36,9 @@ bool operator==(const SymbolID &Sym) const { return HashValue == Sym.HashValue; } + bool operator!=(const SymbolID &Sym) const { + return !(*this == Sym); + } bool operator<(const SymbolID &Sym) const { return HashValue < Sym.HashValue; } diff --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp --- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp +++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp @@ -700,39 +700,70 @@ EXPECT_THAT(Refs, IsEmpty()); } -TEST_F(SymbolCollectorTest, SpelledReference) { - Annotations Header(R"cpp( - struct Foo; - #define MACRO Foo - )cpp"); - Annotations Main(R"cpp( - struct $spelled[[Foo]] { - $spelled[[Foo]](); - ~$spelled[[Foo]](); +TEST_F(SymbolCollectorTest, SpelledReferences) { + struct { + llvm::StringRef Header; + llvm::StringRef Main; + llvm::StringRef TargetSymbolName; + } TestCases[] = { + { + R"cpp( + struct Foo; + #define MACRO Foo + )cpp", + R"cpp( + struct $spelled[[Foo]] { + $spelled[[Foo]](); + ~$spelled[[Foo]](); + }; + $spelled[[Foo]] Variable1; + $implicit[[MACRO]] Variable2; + )cpp", + "Foo", + }, + { + R"cpp( + class Foo { + public: + Foo() = default; + }; + )cpp", + R"cpp( + void f() { Foo $implicit[[f]]; f = $spelled[[Foo]]();} + )cpp", + "Foo::Foo" /// constructor. + }, }; - $spelled[[Foo]] Variable1; - $implicit[[MACRO]] Variable2; - )cpp"); CollectorOpts.RefFilter = RefKind::All; CollectorOpts.RefsInHeaders = false; - runSymbolCollector(Header.code(), Main.code()); - const auto SpelledRanges = Main.ranges("spelled"); - const auto ImplicitRanges = Main.ranges("implicit"); - RefSlab::Builder SpelledSlabBuilder, ImplicitSlabBuilder; - for (const auto &SymbolAndRefs : Refs) { - const auto Symbol = SymbolAndRefs.first; - for (const auto &Ref : SymbolAndRefs.second) - if ((Ref.Kind & RefKind::Spelled) != RefKind::Unknown) - SpelledSlabBuilder.insert(Symbol, Ref); - else - ImplicitSlabBuilder.insert(Symbol, Ref); + for (const auto& T : TestCases) { + Annotations Header(T.Header); + Annotations Main(T.Main); + // Reset the file system. + InMemoryFileSystem = new llvm::vfs::InMemoryFileSystem; + runSymbolCollector(Header.code(), Main.code()); + + const auto SpelledRanges = Main.ranges("spelled"); + const auto ImplicitRanges = Main.ranges("implicit"); + RefSlab::Builder SpelledSlabBuilder, ImplicitSlabBuilder; + const auto TargetID = findSymbol(Symbols, T.TargetSymbolName).ID; + for (const auto &SymbolAndRefs : Refs) { + const auto ID = SymbolAndRefs.first; + if (ID != TargetID) + continue; + for (const auto &Ref : SymbolAndRefs.second) + if ((Ref.Kind & RefKind::Spelled) != RefKind::Unknown) + SpelledSlabBuilder.insert(ID, Ref); + else + ImplicitSlabBuilder.insert(ID, Ref); + } + const auto SpelledRefs = std::move(SpelledSlabBuilder).build(), + ImplicitRefs = std::move(ImplicitSlabBuilder).build(); + EXPECT_THAT(SpelledRefs, + Contains(Pair(TargetID, HaveRanges(SpelledRanges)))); + EXPECT_THAT(ImplicitRefs, + Contains(Pair(TargetID, HaveRanges(ImplicitRanges)))); } - const auto SpelledRefs = std::move(SpelledSlabBuilder).build(), - ImplicitRefs = std::move(ImplicitSlabBuilder).build(); - EXPECT_THAT(SpelledRefs, Contains(Pair(findSymbol(Symbols, "Foo").ID, - HaveRanges(SpelledRanges)))); - EXPECT_THAT(ImplicitRefs, Contains(Pair(findSymbol(Symbols, "Foo").ID, - HaveRanges(ImplicitRanges)))); } TEST_F(SymbolCollectorTest, NameReferences) {