diff options
author | Kadir Cetinkaya <kadircet@google.com> | 2019-03-14 08:35:17 +0000 |
---|---|---|
committer | Kadir Cetinkaya <kadircet@google.com> | 2019-03-14 08:35:17 +0000 |
commit | d9c174648ed8219ad86a021bcccf149e860d3ef5 (patch) | |
tree | 3c973ab0cfaad5aa8269429fbc1d763e93f4b48d | |
parent | fec503acb667c80a0cbc8e998e2aa8bba99d8743 (diff) | |
download | bcm5719-llvm-d9c174648ed8219ad86a021bcccf149e860d3ef5.tar.gz bcm5719-llvm-d9c174648ed8219ad86a021bcccf149e860d3ef5.zip |
[clangd] Store explicit template specializations in index for code navigation purposes
Summary:
This introduces ~4k new symbols, and ~10k refs for LLVM. We need that
information for providing better code navigation support:
- When references for a class template is requested, we should return these specializations as well.
- When children of a specialization is requested, we should be able to query for those symbols(instead of just class template)
Number of symbols: 378574 -> 382784
Number of refs: 5098857 -> 5110689
Reviewers: hokein, gribozavr
Reviewed By: gribozavr
Subscribers: nridge, ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D59083
llvm-svn: 356125
-rw-r--r-- | clang-tools-extra/clangd/CodeComplete.cpp | 14 | ||||
-rw-r--r-- | clang-tools-extra/clangd/index/MemIndex.cpp | 10 | ||||
-rw-r--r-- | clang-tools-extra/clangd/index/SymbolCollector.cpp | 11 | ||||
-rw-r--r-- | clang-tools-extra/clangd/index/dex/Dex.cpp | 9 | ||||
-rw-r--r-- | clang-tools-extra/unittests/clangd/DexTests.cpp | 35 | ||||
-rw-r--r-- | clang-tools-extra/unittests/clangd/IndexTests.cpp | 37 | ||||
-rw-r--r-- | clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp | 24 |
7 files changed, 121 insertions, 19 deletions
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 91a5dac595a..c9859b2fa25 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1510,6 +1510,13 @@ private: } }; +template <class T> bool isExplicitTemplateSpecialization(const NamedDecl &ND) { + if (const auto *TD = dyn_cast<T>(&ND)) + if (TD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return true; + return false; +} + } // namespace clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const { @@ -1603,6 +1610,13 @@ bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx) { }; return false; }; + // We only complete symbol's name, which is the same as the name of the + // *primary* template in case of template specializations. + if (isExplicitTemplateSpecialization<FunctionDecl>(ND) || + isExplicitTemplateSpecialization<CXXRecordDecl>(ND) || + isExplicitTemplateSpecialization<VarDecl>(ND)) + return false; + if (InTopLevelScope(ND)) return true; diff --git a/clang-tools-extra/clangd/index/MemIndex.cpp b/clang-tools-extra/clangd/index/MemIndex.cpp index 531d1f6dcae..ddd9a8670c1 100644 --- a/clang-tools-extra/clangd/index/MemIndex.cpp +++ b/clang-tools-extra/clangd/index/MemIndex.cpp @@ -11,6 +11,7 @@ #include "Logger.h" #include "Quality.h" #include "Trace.h" +#include "clang/Index/IndexSymbol.h" namespace clang { namespace clangd { @@ -37,6 +38,15 @@ bool MemIndex::fuzzyFind( 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::SymbolPropertySet>( + index::SymbolProperty::TemplateSpecialization) | + static_cast<index::SymbolPropertySet>( + 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/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index 7fae0795d17..eee3200421c 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -221,13 +221,6 @@ RefKind toRefKind(index::SymbolRoleSet Roles) { return static_cast<RefKind>(static_cast<unsigned>(RefKind::All) & Roles); } -template <class T> bool explicitTemplateSpecialization(const NamedDecl &ND) { - if (const auto *TD = dyn_cast<T>(&ND)) - if (TD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - return true; - return false; -} - } // namespace SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {} @@ -279,10 +272,6 @@ bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND, if (!isa<RecordDecl>(DeclCtx)) return false; } - if (explicitTemplateSpecialization<FunctionDecl>(ND) || - explicitTemplateSpecialization<CXXRecordDecl>(ND) || - explicitTemplateSpecialization<VarDecl>(ND)) - return false; // Avoid indexing internal symbols in protobuf generated headers. if (isPrivateProtoDecl(ND)) diff --git a/clang-tools-extra/clangd/index/dex/Dex.cpp b/clang-tools-extra/clangd/index/dex/Dex.cpp index d767bb517c2..dd004f5f42c 100644 --- a/clang-tools-extra/clangd/index/dex/Dex.cpp +++ b/clang-tools-extra/clangd/index/dex/Dex.cpp @@ -86,6 +86,15 @@ void Dex::buildIndex() { llvm::DenseMap<Token, std::vector<DocID>> 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::SymbolPropertySet>( + index::SymbolProperty::TemplateSpecialization) | + static_cast<index::SymbolPropertySet>( + 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 index cd52daaca29..bd757d08c8e 100644 --- a/clang-tools-extra/unittests/clangd/DexTests.cpp +++ b/clang-tools-extra/unittests/clangd/DexTests.cpp @@ -710,6 +710,41 @@ TEST(DexTest, PreferredTypesBoosting) { EXPECT_THAT(match(I, Req), ElementsAre("t2")); } +TEST(DexTest, TemplateSpecialization) { + SymbolSlab::Builder B; + + Symbol S = symbol("TempSpec"); + S.ID = SymbolID("0"); + B.insert(S); + + S = symbol("TempSpec"); + S.ID = SymbolID("1"); + S.SymInfo.Properties = static_cast<index::SymbolPropertySet>( + index::SymbolProperty::TemplateSpecialization); + B.insert(S); + + S = symbol("TempSpec"); + S.ID = SymbolID("2"); + S.SymInfo.Properties = static_cast<index::SymbolPropertySet>( + 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<Symbol> 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::SymbolPropertySet>( + index::SymbolProperty::TemplateSpecialization)); + EXPECT_FALSE(Symbols.front().SymInfo.Properties & + static_cast<index::SymbolPropertySet>( + index::SymbolProperty::TemplatePartialSpecialization)); +} + } // namespace } // namespace dex } // namespace clangd diff --git a/clang-tools-extra/unittests/clangd/IndexTests.cpp b/clang-tools-extra/unittests/clangd/IndexTests.cpp index 7d60ede1c38..3a159279733 100644 --- a/clang-tools-extra/unittests/clangd/IndexTests.cpp +++ b/clang-tools-extra/unittests/clangd/IndexTests.cpp @@ -13,6 +13,8 @@ #include "index/Index.h" #include "index/MemIndex.h" #include "index/Merge.h" +#include "index/Symbol.h" +#include "clang/Index/IndexSymbol.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -181,6 +183,41 @@ TEST(MemIndexTest, Lookup) { EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre()); } +TEST(MemIndexTest, TemplateSpecialization) { + SymbolSlab::Builder B; + + Symbol S = symbol("TempSpec"); + S.ID = SymbolID("0"); + B.insert(S); + + S = symbol("TempSpec"); + S.ID = SymbolID("1"); + S.SymInfo.Properties = static_cast<index::SymbolPropertySet>( + index::SymbolProperty::TemplateSpecialization); + B.insert(S); + + S = symbol("TempSpec"); + S.ID = SymbolID("2"); + S.SymInfo.Properties = static_cast<index::SymbolPropertySet>( + 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<Symbol> 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::SymbolPropertySet>( + index::SymbolProperty::TemplateSpecialization)); + EXPECT_FALSE(Symbols.front().SymInfo.Properties & + static_cast<index::SymbolPropertySet>( + index::SymbolProperty::TemplatePartialSpecialization)); +} + TEST(MergeIndexTest, Lookup) { auto I = MemIndex::build(generateSymbols({"ns::A", "ns::B"}), RefSlab()), J = MemIndex::build(generateSymbols({"ns::B", "ns::C"}), RefSlab()); diff --git a/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp b/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp index d795286fd79..f7b125b99ae 100644 --- a/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp +++ b/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp @@ -392,17 +392,25 @@ TEST_F(SymbolCollectorTest, FileLocal) { TEST_F(SymbolCollectorTest, Template) { Annotations Header(R"( - // Template is indexed, specialization and instantiation is not. - template <class T> struct [[Tmpl]] {T $xdecl[[x]] = 0;}; - template <> struct Tmpl<int> {}; - extern template struct Tmpl<float>; - template struct Tmpl<double>; + // Primary template and explicit specialization are indexed, instantiation + // is not. + template <class T, class U> struct [[Tmpl]] {T $xdecl[[x]] = 0;}; + template <> struct $specdecl[[Tmpl]]<int, bool> {}; + template <class U> struct $partspecdecl[[Tmpl]]<bool, U> {}; + extern template struct Tmpl<float, bool>; + template struct Tmpl<double, bool>; )"); runSymbolCollector(Header.code(), /*Main=*/""); EXPECT_THAT(Symbols, - UnorderedElementsAreArray( - {AllOf(QName("Tmpl"), DeclRange(Header.range())), - AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")))})); + UnorderedElementsAre( + AllOf(QName("Tmpl"), DeclRange(Header.range()), + ForCodeCompletion(true)), + AllOf(QName("Tmpl"), DeclRange(Header.range("specdecl")), + ForCodeCompletion(false)), + AllOf(QName("Tmpl"), DeclRange(Header.range("partspecdecl")), + ForCodeCompletion(false)), + AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")), + ForCodeCompletion(false)))); } TEST_F(SymbolCollectorTest, ObjCSymbols) { |