[clang-tools-extra] 84240e0 - [clang][Index] Introduce a TemplateParm SymbolKind
Kadir Cetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 14 04:24:20 PST 2020
Author: Kadir Cetinkaya
Date: 2020-02-14T13:20:34+01:00
New Revision: 84240e0db8ab85b56df11e6cee8fef5ac7ee8c33
URL: https://github.com/llvm/llvm-project/commit/84240e0db8ab85b56df11e6cee8fef5ac7ee8c33
DIFF: https://github.com/llvm/llvm-project/commit/84240e0db8ab85b56df11e6cee8fef5ac7ee8c33.diff
LOG: [clang][Index] Introduce a TemplateParm SymbolKind
Summary:
Currently template parameters has symbolkind `Unknown`. This patch
introduces a new kind `TemplateParm` for templatetemplate, templatetype and
nontypetemplate parameters.
Also adds tests in clangd hover feature.
Reviewers: sammccall
Subscribers: kristof.beyls, ilya-biryukov, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73696
Added:
Modified:
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/Hover.cpp
clang-tools-extra/clangd/Protocol.cpp
clang-tools-extra/clangd/Quality.cpp
clang-tools-extra/clangd/unittests/HoverTests.cpp
clang/include/clang/Index/IndexSymbol.h
clang/lib/Index/IndexSymbol.cpp
clang/tools/libclang/CXIndexDataConsumer.cpp
clang/unittests/Index/IndexTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 52c1ceef7425..f7c6f105cb9a 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -108,6 +108,7 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {
return CompletionItemKind::Function;
case SK::Variable:
case SK::Parameter:
+ case SK::NonTypeTemplateParm:
return CompletionItemKind::Variable;
case SK::Field:
return CompletionItemKind::Field;
@@ -125,6 +126,9 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {
return CompletionItemKind::Property;
case SK::Constructor:
return CompletionItemKind::Constructor;
+ case SK::TemplateTypeParm:
+ case SK::TemplateTemplateParm:
+ return CompletionItemKind::TypeParameter;
}
llvm_unreachable("Unhandled clang::index::SymbolKind.");
}
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index ae4c441a73b5..750df50c4777 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -115,15 +115,6 @@ std::string printDefinition(const Decl *D) {
return Definition;
}
-void printParams(llvm::raw_ostream &OS,
- const std::vector<HoverInfo::Param> &Params) {
- for (size_t I = 0, E = Params.size(); I != E; ++I) {
- if (I)
- OS << ", ";
- OS << Params.at(I);
- }
-}
-
std::string printType(QualType QT, const PrintingPolicy &Policy) {
// TypePrinter doesn't resolve decltypes, so resolve them here.
// FIXME: This doesn't handle composite types that contain a decltype in them.
@@ -133,6 +124,43 @@ std::string printType(QualType QT, const PrintingPolicy &Policy) {
return QT.getAsString(Policy);
}
+std::string printType(const TemplateTypeParmDecl *TTP) {
+ std::string Res = TTP->wasDeclaredWithTypename() ? "typename" : "class";
+ if (TTP->isParameterPack())
+ Res += "...";
+ return Res;
+}
+
+std::string printType(const NonTypeTemplateParmDecl *NTTP,
+ const PrintingPolicy &PP) {
+ std::string Res = printType(NTTP->getType(), PP);
+ if (NTTP->isParameterPack())
+ Res += "...";
+ return Res;
+}
+
+std::string printType(const TemplateTemplateParmDecl *TTP,
+ const PrintingPolicy &PP) {
+ std::string Res;
+ llvm::raw_string_ostream OS(Res);
+ OS << "template <";
+ llvm::StringRef Sep = "";
+ for (const Decl *Param : *TTP->getTemplateParameters()) {
+ OS << Sep;
+ Sep = ", ";
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ OS << printType(TTP);
+ else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ OS << printType(NTTP, PP);
+ else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param))
+ OS << printType(TTPD, PP);
+ }
+ // FIXME: TemplateTemplateParameter doesn't store the info on whether this
+ // param was a "typename" or "class".
+ OS << "> class";
+ return OS.str();
+}
+
std::vector<HoverInfo::Param>
fetchTemplateParameters(const TemplateParameterList *Params,
const PrintingPolicy &PP) {
@@ -142,38 +170,30 @@ fetchTemplateParameters(const TemplateParameterList *Params,
for (const Decl *Param : *Params) {
HoverInfo::Param P;
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
- P.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class";
- if (TTP->isParameterPack())
- *P.Type += "...";
+ P.Type = printType(TTP);
if (!TTP->getName().empty())
P.Name = TTP->getNameAsString();
+
if (TTP->hasDefaultArgument())
P.Default = TTP->getDefaultArgument().getAsString(PP);
} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ P.Type = printType(NTTP, PP);
+
if (IdentifierInfo *II = NTTP->getIdentifier())
P.Name = II->getName().str();
- P.Type = printType(NTTP->getType(), PP);
- if (NTTP->isParameterPack())
- *P.Type += "...";
-
if (NTTP->hasDefaultArgument()) {
P.Default.emplace();
llvm::raw_string_ostream Out(*P.Default);
NTTP->getDefaultArgument()->printPretty(Out, nullptr, PP);
}
} else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
- P.Type.emplace();
- llvm::raw_string_ostream OS(*P.Type);
- OS << "template <";
- printParams(OS,
- fetchTemplateParameters(TTPD->getTemplateParameters(), PP));
- OS << "> class"; // FIXME: TemplateTemplateParameter doesn't store the
- // info on whether this param was a "typename" or
- // "class".
+ P.Type = printType(TTPD, PP);
+
if (!TTPD->getName().empty())
P.Name = TTPD->getNameAsString();
+
if (TTPD->hasDefaultArgument()) {
P.Default.emplace();
llvm::raw_string_ostream Out(*P.Default);
@@ -385,6 +405,10 @@ HoverInfo getHoverContents(const NamedDecl *D, const SymbolIndex *Index) {
fillFunctionTypeAndParams(HI, D, FD, Policy);
else if (const auto *VD = dyn_cast<ValueDecl>(D))
HI.Type = printType(VD->getType(), Policy);
+ else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D))
+ HI.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class";
+ else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(D))
+ HI.Type = printType(TTP, Policy);
// Fill in value with evaluated initializer if possible.
if (const auto *Var = dyn_cast<VarDecl>(D)) {
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index 1e71c2ab37f5..8e89c1f45f3a 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -14,6 +14,7 @@
#include "Logger.h"
#include "URI.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Index/IndexSymbol.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
@@ -261,9 +262,13 @@ SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
case index::SymbolKind::ConversionFunction:
return SymbolKind::Function;
case index::SymbolKind::Parameter:
+ case index::SymbolKind::NonTypeTemplateParm:
return SymbolKind::Variable;
case index::SymbolKind::Using:
return SymbolKind::Namespace;
+ case index::SymbolKind::TemplateTemplateParm:
+ case index::SymbolKind::TemplateTypeParm:
+ return SymbolKind::TypeParameter;
}
llvm_unreachable("invalid symbol kind");
}
diff --git a/clang-tools-extra/clangd/Quality.cpp b/clang-tools-extra/clangd/Quality.cpp
index d80790fc9808..2261ff61e499 100644
--- a/clang-tools-extra/clangd/Quality.cpp
+++ b/clang-tools-extra/clangd/Quality.cpp
@@ -129,6 +129,8 @@ categorize(const index::SymbolInfo &D) {
case index::SymbolKind::Extension:
case index::SymbolKind::Union:
case index::SymbolKind::TypeAlias:
+ case index::SymbolKind::TemplateTypeParm:
+ case index::SymbolKind::TemplateTemplateParm:
return SymbolQualitySignals::Type;
case index::SymbolKind::Function:
case index::SymbolKind::ClassMethod:
@@ -147,6 +149,7 @@ categorize(const index::SymbolInfo &D) {
case index::SymbolKind::Field:
case index::SymbolKind::EnumConstant:
case index::SymbolKind::Parameter:
+ case index::SymbolKind::NonTypeTemplateParm:
return SymbolQualitySignals::Variable;
case index::SymbolKind::Using:
case index::SymbolKind::Module:
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 2876e2f31c13..503b4d2afa42 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -573,6 +573,42 @@ class Foo {})cpp";
// pattern.
HI.Documentation = "comment from primary";
}},
+ {// Template Type Parameter
+ R"cpp(
+ template <typename [[^T]] = int> void foo();
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "T";
+ HI.Kind = index::SymbolKind::TemplateTypeParm;
+ HI.NamespaceScope = "";
+ HI.Definition = "typename T = int";
+ HI.LocalScope = "foo::";
+ HI.Type = "typename";
+ }},
+ {// TemplateTemplate Type Parameter
+ R"cpp(
+ template <template<typename> class [[^T]]> void foo();
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "T";
+ HI.Kind = index::SymbolKind::TemplateTemplateParm;
+ HI.NamespaceScope = "";
+ HI.Definition = "template <typename> class T";
+ HI.LocalScope = "foo::";
+ HI.Type = "template <typename> class";
+ }},
+ {// NonType Template Parameter
+ R"cpp(
+ template <int [[^T]] = 5> void foo();
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "T";
+ HI.Kind = index::SymbolKind::NonTypeTemplateParm;
+ HI.NamespaceScope = "";
+ HI.Definition = "int T = 5";
+ HI.LocalScope = "foo::";
+ HI.Type = "int";
+ }},
};
for (const auto &Case : Cases) {
SCOPED_TRACE(Case.Code);
diff --git a/clang/include/clang/Index/IndexSymbol.h b/clang/include/clang/Index/IndexSymbol.h
index 2e1e6005d68a..de98b8147e8a 100644
--- a/clang/include/clang/Index/IndexSymbol.h
+++ b/clang/include/clang/Index/IndexSymbol.h
@@ -54,6 +54,9 @@ enum class SymbolKind : uint8_t {
Parameter,
Using,
+ TemplateTypeParm,
+ TemplateTemplateParm,
+ NonTypeTemplateParm,
};
enum class SymbolLanguage : uint8_t {
diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp
index ae9134bf1182..0d2e557cdd36 100644
--- a/clang/lib/Index/IndexSymbol.cpp
+++ b/clang/lib/Index/IndexSymbol.cpp
@@ -357,6 +357,15 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
case Decl::VarTemplate:
llvm_unreachable("variables handled before");
break;
+ case Decl::TemplateTypeParm:
+ Info.Kind = SymbolKind::TemplateTypeParm;
+ break;
+ case Decl::TemplateTemplateParm:
+ Info.Kind = SymbolKind::TemplateTemplateParm;
+ break;
+ case Decl::NonTypeTemplateParm:
+ Info.Kind = SymbolKind::NonTypeTemplateParm;
+ break;
// Other decls get the 'unknown' kind.
default:
break;
@@ -517,6 +526,9 @@ StringRef index::getSymbolKindString(SymbolKind K) {
case SymbolKind::ConversionFunction: return "conversion-func";
case SymbolKind::Parameter: return "param";
case SymbolKind::Using: return "using";
+ case SymbolKind::TemplateTypeParm: return "template-type-param";
+ case SymbolKind::TemplateTemplateParm: return "template-template-param";
+ case SymbolKind::NonTypeTemplateParm: return "non-type-template-param";
}
llvm_unreachable("invalid symbol kind");
}
diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp
index ad871228ccdf..fb04a06f8ae7 100644
--- a/clang/tools/libclang/CXIndexDataConsumer.cpp
+++ b/clang/tools/libclang/CXIndexDataConsumer.cpp
@@ -1245,6 +1245,9 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage
case SymbolKind::Macro:
case SymbolKind::ClassProperty:
case SymbolKind::Using:
+ case SymbolKind::TemplateTypeParm:
+ case SymbolKind::TemplateTemplateParm:
+ case SymbolKind::NonTypeTemplateParm:
return CXIdxEntity_Unexposed;
case SymbolKind::Enum: return CXIdxEntity_Enum;
diff --git a/clang/unittests/Index/IndexTests.cpp b/clang/unittests/Index/IndexTests.cpp
index a279f48fbb37..068b30ebfa8a 100644
--- a/clang/unittests/Index/IndexTests.cpp
+++ b/clang/unittests/Index/IndexTests.cpp
@@ -249,8 +249,13 @@ TEST(IndexTest, IndexTypeParmDecls) {
Index->Symbols.clear();
tooling::runToolOnCode(std::make_unique<IndexAction>(Index, Opts), Code);
EXPECT_THAT(Index->Symbols,
- AllOf(Contains(QName("Foo::T")), Contains(QName("Foo::I")),
- Contains(QName("Foo::C")), Contains(QName("Foo::NoRef"))));
+ AllOf(Contains(AllOf(QName("Foo::T"),
+ Kind(SymbolKind::TemplateTypeParm))),
+ Contains(AllOf(QName("Foo::I"),
+ Kind(SymbolKind::NonTypeTemplateParm))),
+ Contains(AllOf(QName("Foo::C"),
+ Kind(SymbolKind::TemplateTemplateParm))),
+ Contains(QName("Foo::NoRef"))));
}
TEST(IndexTest, UsingDecls) {
More information about the cfe-commits
mailing list