summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKadir Cetinkaya <kadircet@google.com>2019-03-14 08:35:17 +0000
committerKadir Cetinkaya <kadircet@google.com>2019-03-14 08:35:17 +0000
commitd9c174648ed8219ad86a021bcccf149e860d3ef5 (patch)
tree3c973ab0cfaad5aa8269429fbc1d763e93f4b48d
parentfec503acb667c80a0cbc8e998e2aa8bba99d8743 (diff)
downloadbcm5719-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.cpp14
-rw-r--r--clang-tools-extra/clangd/index/MemIndex.cpp10
-rw-r--r--clang-tools-extra/clangd/index/SymbolCollector.cpp11
-rw-r--r--clang-tools-extra/clangd/index/dex/Dex.cpp9
-rw-r--r--clang-tools-extra/unittests/clangd/DexTests.cpp35
-rw-r--r--clang-tools-extra/unittests/clangd/IndexTests.cpp37
-rw-r--r--clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp24
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) {
OpenPOWER on IntegriCloud