[clang-tools-extra] 0474fe4 - [clangd] Print underlying type for decltypes in hover
Kadir Cetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 16 10:57:23 PST 2020
Author: Kadir Cetinkaya
Date: 2020-01-16T19:56:54+01:00
New Revision: 0474fe465d8feebcfd54a16d93ad8518b5625972
URL: https://github.com/llvm/llvm-project/commit/0474fe465d8feebcfd54a16d93ad8518b5625972
DIFF: https://github.com/llvm/llvm-project/commit/0474fe465d8feebcfd54a16d93ad8518b5625972.diff
LOG: [clangd] Print underlying type for decltypes in hover
Summary: Fixes https://github.com/clangd/clangd/issues/249
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D72498
Added:
Modified:
clang-tools-extra/clangd/Hover.cpp
clang-tools-extra/clangd/unittests/HoverTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 0833a46f088e..cfa5e3bf93fb 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -123,6 +123,15 @@ void printParams(llvm::raw_ostream &OS,
}
}
+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.
+ // We should rather have a printing policy for that.
+ while (const auto *DT = QT->getAs<DecltypeType>())
+ QT = DT->getUnderlyingType();
+ return QT.getAsString(Policy);
+}
+
std::vector<HoverInfo::Param>
fetchTemplateParameters(const TemplateParameterList *Params,
const PrintingPolicy &PP) {
@@ -131,8 +140,7 @@ fetchTemplateParameters(const TemplateParameterList *Params,
for (const Decl *Param : *Params) {
HoverInfo::Param P;
- P.Type.emplace();
- if (const auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
P.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class";
if (TTP->isParameterPack())
*P.Type += "...";
@@ -141,21 +149,21 @@ fetchTemplateParameters(const TemplateParameterList *Params,
P.Name = TTP->getNameAsString();
if (TTP->hasDefaultArgument())
P.Default = TTP->getDefaultArgument().getAsString(PP);
- } else if (const auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
if (IdentifierInfo *II = NTTP->getIdentifier())
P.Name = II->getName().str();
- llvm::raw_string_ostream Out(*P.Type);
- NTTP->getType().print(Out, PP);
+ P.Type = printType(NTTP->getType(), PP);
if (NTTP->isParameterPack())
- Out << "...";
+ *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)) {
+ } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
+ P.Type.emplace();
llvm::raw_string_ostream OS(*P.Type);
OS << "template <";
printParams(OS,
@@ -241,7 +249,7 @@ void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D,
HI.Parameters->emplace_back();
auto &P = HI.Parameters->back();
if (!PVD->getType().isNull()) {
- P.Type = PVD->getType().getAsString(Policy);
+ P.Type = printType(PVD->getType(), Policy);
} else {
std::string Param;
llvm::raw_string_ostream OS(Param);
@@ -265,12 +273,12 @@ void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D,
} else if (llvm::isa<CXXDestructorDecl>(FD)) {
HI.ReturnType = "void";
} else {
- HI.ReturnType = FD->getReturnType().getAsString(Policy);
+ HI.ReturnType = printType(FD->getReturnType(), Policy);
- QualType FunctionType = FD->getType();
+ QualType QT = FD->getType();
if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) // Lambdas
- FunctionType = VD->getType().getDesugaredType(D->getASTContext());
- HI.Type = FunctionType.getAsString(Policy);
+ QT = VD->getType().getDesugaredType(D->getASTContext());
+ HI.Type = printType(QT, Policy);
}
// FIXME: handle variadics.
}
@@ -342,7 +350,7 @@ HoverInfo getHoverContents(const NamedDecl *D, const SymbolIndex *Index) {
fetchTemplateParameters(TD->getTemplateParameters(), Policy);
D = TD;
} else if (const FunctionDecl *FD = D->getAsFunction()) {
- if (const auto FTD = FD->getDescribedTemplate()) {
+ if (const auto *FTD = FD->getDescribedTemplate()) {
HI.TemplateParameters =
fetchTemplateParameters(FTD->getTemplateParameters(), Policy);
D = FTD;
@@ -353,7 +361,7 @@ HoverInfo getHoverContents(const NamedDecl *D, const SymbolIndex *Index) {
if (const FunctionDecl *FD = getUnderlyingFunction(D))
fillFunctionTypeAndParams(HI, D, FD, Policy);
else if (const auto *VD = dyn_cast<ValueDecl>(D))
- HI.Type = VD->getType().getAsString(Policy);
+ HI.Type = printType(VD->getType(), Policy);
// Fill in value with evaluated initializer if possible.
if (const auto *Var = dyn_cast<VarDecl>(D)) {
@@ -449,7 +457,7 @@ llvm::Optional<HoverInfo> getHoverContents(const Expr *E, ParsedAST &AST) {
auto Policy =
printingPolicyForDecls(AST.getASTContext().getPrintingPolicy());
Policy.SuppressTagKeyword = true;
- HI.Type = E->getType().getAsString(Policy);
+ HI.Type = printType(E->getType(), Policy);
HI.Value = *Val;
HI.Name = getNameForExpr(E);
return HI;
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 65d5e4a6c216..9b6f2b185bf4 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1514,6 +1514,56 @@ TEST(Hover, All) {
HI.Name = "cls<cls<cls<int> > >";
HI.Documentation = "type of nested templates.";
}},
+ {
+ R"cpp(// type with decltype
+ int a;
+ decltype(a) [[b^]] = a;)cpp",
+ [](HoverInfo &HI) {
+ HI.Definition = "decltype(a) b = a";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.Name = "b";
+ HI.Type = "int";
+ }},
+ {
+ R"cpp(// type with decltype
+ int a;
+ decltype(a) c;
+ decltype(c) [[b^]] = a;)cpp",
+ [](HoverInfo &HI) {
+ HI.Definition = "decltype(c) b = a";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.Name = "b";
+ HI.Type = "int";
+ }},
+ {
+ R"cpp(// type with decltype
+ int a;
+ const decltype(a) [[b^]] = a;)cpp",
+ [](HoverInfo &HI) {
+ HI.Definition = "const decltype(a) b = a";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.Name = "b";
+ HI.Type = "int";
+ }},
+ {
+ R"cpp(// type with decltype
+ int a;
+ auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
+ [](HoverInfo &HI) {
+ HI.Definition = "auto foo(decltype(a) x) -> decltype(a)";
+ HI.Kind = index::SymbolKind::Function;
+ HI.NamespaceScope = "";
+ HI.Name = "foo";
+ // FIXME: Handle composite types with decltype with a printing
+ // policy.
+ HI.Type = "auto (decltype(a)) -> decltype(a)";
+ HI.ReturnType = "int";
+ HI.Parameters = {
+ {std::string("int"), std::string("x"), llvm::None}};
+ }},
};
// Create a tiny index, so tests above can verify documentation is fetched.
@@ -1542,6 +1592,7 @@ TEST(Hover, All) {
Expected.SymRange = T.range();
Case.ExpectedBuilder(Expected);
+ SCOPED_TRACE(H->present().asPlainText());
EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
EXPECT_EQ(H->LocalScope, Expected.LocalScope);
EXPECT_EQ(H->Name, Expected.Name);
More information about the cfe-commits
mailing list