diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -84,17 +84,6 @@ return QName; } -static const TemplateArgumentList * -getTemplateSpecializationArgs(const NamedDecl &ND) { - if (auto *Func = llvm::dyn_cast(&ND)) - return Func->getTemplateSpecializationArgs(); - if (auto *Cls = llvm::dyn_cast(&ND)) - return &Cls->getTemplateInstantiationArgs(); - if (auto *Var = llvm::dyn_cast(&ND)) - return &Var->getTemplateInstantiationArgs(); - return nullptr; -} - std::string printName(const ASTContext &Ctx, const NamedDecl &ND) { std::string Name; llvm::raw_string_ostream Out(Name); @@ -109,9 +98,7 @@ } ND.getDeclName().print(Out, PP); if (!Out.str().empty()) { - // FIXME(ibiryukov): do not show args not explicitly written by the user. - if (auto *ArgList = getTemplateSpecializationArgs(ND)) - printTemplateArgumentList(Out, ArgList->asArray(), PP); + Out << printTemplateArgsAsWritten(ND); return Out.str(); } // The name was empty, so present an anonymous entity. 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 @@ -94,7 +94,8 @@ std::string Scope = Sym.Scope; llvm::StringRef ScopeRef = Scope; ScopeRef.consume_back("::"); - SymbolInformation Info = {Sym.Name, SK, L, ScopeRef}; + SymbolInformation Info = {(Sym.Name + Sym.TemplateArgumentList).str(), SK, + L, ScopeRef}; SymbolQualitySignals Quality; Quality.merge(Sym); diff --git a/clang-tools-extra/clangd/index/MemIndex.cpp b/clang-tools-extra/clangd/index/MemIndex.cpp --- a/clang-tools-extra/clangd/index/MemIndex.cpp +++ b/clang-tools-extra/clangd/index/MemIndex.cpp @@ -38,15 +38,6 @@ for (const auto Pair : Index) { const Symbol *Sym = Pair.second; - // FIXME: Enable fuzzy find on template specializations once we start - // storing template arguments in the name. Currently we only store name for - // class template, which would cause duplication in the results. - if (Sym->SymInfo.Properties & - (static_cast( - index::SymbolProperty::TemplateSpecialization) | - static_cast( - index::SymbolProperty::TemplatePartialSpecialization))) - continue; // Exact match against all possible scopes. if (!Req.AnyScope && !llvm::is_contained(Req.Scopes, Sym->Scope)) continue; diff --git a/clang-tools-extra/clangd/index/dex/Dex.cpp b/clang-tools-extra/clangd/index/dex/Dex.cpp --- a/clang-tools-extra/clangd/index/dex/Dex.cpp +++ b/clang-tools-extra/clangd/index/dex/Dex.cpp @@ -86,15 +86,6 @@ llvm::DenseMap> TempInvertedIndex; for (DocID SymbolRank = 0; SymbolRank < Symbols.size(); ++SymbolRank) { const auto *Sym = Symbols[SymbolRank]; - // FIXME: Enable fuzzy find on template specializations once we start - // storing template arguments in the name. Currently we only store name for - // class template, which would cause duplication in the results. - if (Sym->SymInfo.Properties & - (static_cast( - index::SymbolProperty::TemplateSpecialization) | - static_cast( - index::SymbolProperty::TemplatePartialSpecialization))) - continue; for (const auto &Token : generateSearchTokens(*Sym)) TempInvertedIndex[Token].push_back(SymbolRank); } diff --git a/clang-tools-extra/unittests/clangd/DexTests.cpp b/clang-tools-extra/unittests/clangd/DexTests.cpp --- a/clang-tools-extra/unittests/clangd/DexTests.cpp +++ b/clang-tools-extra/unittests/clangd/DexTests.cpp @@ -11,6 +11,7 @@ #include "TestIndex.h" #include "index/Index.h" #include "index/Merge.h" +#include "index/SymbolID.h" #include "index/dex/Dex.h" #include "index/dex/Iterator.h" #include "index/dex/Token.h" @@ -24,6 +25,7 @@ using ::testing::AnyOf; using ::testing::ElementsAre; +using ::testing::IsEmpty; using ::testing::UnorderedElementsAre; namespace clang { @@ -714,35 +716,35 @@ SymbolSlab::Builder B; Symbol S = symbol("TempSpec"); - S.ID = SymbolID("0"); + S.ID = SymbolID("1"); B.insert(S); S = symbol("TempSpec"); - S.ID = SymbolID("1"); + S.ID = SymbolID("2"); + S.TemplateArgumentList = ""; S.SymInfo.Properties = static_cast( index::SymbolProperty::TemplateSpecialization); B.insert(S); S = symbol("TempSpec"); - S.ID = SymbolID("2"); + S.ID = SymbolID("3"); + S.TemplateArgumentList = ""; S.SymInfo.Properties = static_cast( index::SymbolProperty::TemplatePartialSpecialization); B.insert(S); auto I = dex::Dex::build(std::move(B).build(), RefSlab()); FuzzyFindRequest Req; - Req.Query = "TempSpec"; Req.AnyScope = true; - std::vector Symbols; - I->fuzzyFind(Req, [&Symbols](const Symbol &Sym) { Symbols.push_back(Sym); }); - EXPECT_EQ(Symbols.size(), 1U); - EXPECT_FALSE(Symbols.front().SymInfo.Properties & - static_cast( - index::SymbolProperty::TemplateSpecialization)); - EXPECT_FALSE(Symbols.front().SymInfo.Properties & - static_cast( - index::SymbolProperty::TemplatePartialSpecialization)); + Req.Query = "TempSpec"; + EXPECT_THAT(match(*I, Req), + UnorderedElementsAre("TempSpec", "TempSpec", + "TempSpec")); + + // FIXME: Add filtering for template argument list. + Req.Query = "TempSpec class Foo {}; + template class Foo {}; + template <> class Foo {}; + template <> class Foo {}; + )cpp"); + // Foo is higher ranked because of exact name match. + EXPECT_THAT( + getSymbols("Foo"), + UnorderedElementsAre( + AllOf(QName("Foo"), WithKind(SymbolKind::Class)), + AllOf(QName("Foo"), WithKind(SymbolKind::Class)), + AllOf(QName("Foo"), WithKind(SymbolKind::Class)), + AllOf(QName("Foo"), WithKind(SymbolKind::Class)))); +} + namespace { class DocumentSymbolsTest : public ::testing::Test { public: @@ -525,11 +541,9 @@ AllOf(WithName("Tmpl"), WithKind(SymbolKind::Struct), Children()), AllOf(WithName("funcTmpl"), Children()), - // FIXME(ibiryukov): template args should be to match the code. - AllOf(WithName("funcTmpl"), Children()), + AllOf(WithName("funcTmpl"), Children()), AllOf(WithName("varTmpl"), Children()), - // FIXME(ibiryukov): template args should be to match the code. - AllOf(WithName("varTmpl"), Children()))); + AllOf(WithName("varTmpl"), Children()))); } TEST_F(DocumentSymbolsTest, Namespaces) { @@ -653,5 +667,22 @@ WithName("using namespace ns_alias"))); } +TEST_F(DocumentSymbolsTest, TempSpecs) { + addFile("foo.cpp", R"cpp( + template class Foo {}; + template class Foo {}; + template <> class Foo {}; + template <> class Foo {}; + )cpp"); + // Foo is higher ranked because of exact name match. + EXPECT_THAT( + getSymbols("foo.cpp"), + UnorderedElementsAre( + AllOf(WithName("Foo"), WithKind(SymbolKind::Class)), + AllOf(WithName("Foo"), WithKind(SymbolKind::Class)), + AllOf(WithName("Foo"), WithKind(SymbolKind::Class)), + AllOf(WithName("Foo"), WithKind(SymbolKind::Class)))); +} + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/unittests/clangd/IndexTests.cpp b/clang-tools-extra/unittests/clangd/IndexTests.cpp --- a/clang-tools-extra/unittests/clangd/IndexTests.cpp +++ b/clang-tools-extra/unittests/clangd/IndexTests.cpp @@ -22,6 +22,7 @@ using testing::AllOf; using testing::AnyOf; using testing::ElementsAre; +using testing::IsEmpty; using testing::Pair; using testing::Pointee; using testing::UnorderedElementsAre; @@ -187,35 +188,35 @@ SymbolSlab::Builder B; Symbol S = symbol("TempSpec"); - S.ID = SymbolID("0"); + S.ID = SymbolID("1"); B.insert(S); S = symbol("TempSpec"); - S.ID = SymbolID("1"); + S.ID = SymbolID("2"); + S.TemplateArgumentList = ""; S.SymInfo.Properties = static_cast( index::SymbolProperty::TemplateSpecialization); B.insert(S); S = symbol("TempSpec"); - S.ID = SymbolID("2"); + S.ID = SymbolID("3"); + S.TemplateArgumentList = ""; S.SymInfo.Properties = static_cast( index::SymbolProperty::TemplatePartialSpecialization); B.insert(S); auto I = MemIndex::build(std::move(B).build(), RefSlab()); FuzzyFindRequest Req; - Req.Query = "TempSpec"; Req.AnyScope = true; - std::vector Symbols; - I->fuzzyFind(Req, [&Symbols](const Symbol &Sym) { Symbols.push_back(Sym); }); - EXPECT_EQ(Symbols.size(), 1U); - EXPECT_FALSE(Symbols.front().SymInfo.Properties & - static_cast( - index::SymbolProperty::TemplateSpecialization)); - EXPECT_FALSE(Symbols.front().SymInfo.Properties & - static_cast( - index::SymbolProperty::TemplatePartialSpecialization)); + Req.Query = "TempSpec"; + EXPECT_THAT(match(*I, Req), + UnorderedElementsAre("TempSpec", "TempSpec", + "TempSpec")); + + // FIXME: Add filtering for template argument list. + Req.Query = "TempSpec match(const SymbolIndex &I,