Skip to content

Commit 6ec0714

Browse files
committed
[clangd] More sensible output for constructors/destructors in hover.
Summary: Previously: both had type void() and return type void. Now: neither have a type. Constructors return T, destructors return void. Reviewers: hokein Subscribers: merge_guards_bot, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D70317
1 parent f0021f9 commit 6ec0714

File tree

4 files changed

+68
-41
lines changed

4 files changed

+68
-41
lines changed

clang-tools-extra/clangd/AST.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,12 @@ std::string printType(const QualType QT, const DeclContext & Context){
246246
printNamespaceScope(Context) );
247247
}
248248

249+
QualType declaredType(const TypeDecl *D) {
250+
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
251+
if (const auto *TSI = CTSD->getTypeAsWritten())
252+
return TSI->getType();
253+
return D->getASTContext().getTypeDeclType(D);
254+
}
249255

250256
} // namespace clangd
251257
} // namespace clang

clang-tools-extra/clangd/AST.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ bool isExplicitTemplateSpecialization(const NamedDecl *D);
111111
/// void foo() -> returns null
112112
NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND);
113113

114+
// Returns a type corresponding to a declaration of that type.
115+
// Unlike the method on ASTContext, attempts to preserve the type as-written
116+
// (i.e. vector<T*> rather than vector<type-parameter-0-0 *>.
117+
QualType declaredType(const TypeDecl *D);
118+
114119
} // namespace clangd
115120
} // namespace clang
116121

clang-tools-extra/clangd/XRefs.cpp

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,51 @@ static void enhanceFromIndex(HoverInfo &Hover, const Decl *D,
566566
Req, [&](const Symbol &S) { Hover.Documentation = S.Documentation; });
567567
}
568568

569+
// Populates Type, ReturnType, and Parameters for function-like decls.
570+
static void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D,
571+
const FunctionDecl *FD,
572+
const PrintingPolicy &Policy) {
573+
HI.Parameters.emplace();
574+
for (const ParmVarDecl *PVD : FD->parameters()) {
575+
HI.Parameters->emplace_back();
576+
auto &P = HI.Parameters->back();
577+
if (!PVD->getType().isNull()) {
578+
P.Type.emplace();
579+
llvm::raw_string_ostream OS(*P.Type);
580+
PVD->getType().print(OS, Policy);
581+
} else {
582+
std::string Param;
583+
llvm::raw_string_ostream OS(Param);
584+
PVD->dump(OS);
585+
OS.flush();
586+
elog("Got param with null type: {0}", Param);
587+
}
588+
if (!PVD->getName().empty())
589+
P.Name = PVD->getNameAsString();
590+
if (PVD->hasDefaultArg()) {
591+
P.Default.emplace();
592+
llvm::raw_string_ostream Out(*P.Default);
593+
PVD->getDefaultArg()->printPretty(Out, nullptr, Policy);
594+
}
595+
}
596+
597+
if (const auto* CCD = llvm::dyn_cast<CXXConstructorDecl>(FD)) {
598+
// Constructor's "return type" is the class type.
599+
HI.ReturnType = declaredType(CCD->getParent()).getAsString(Policy);
600+
// Don't provide any type for the constructor itself.
601+
} else if (const auto* CDD = llvm::dyn_cast<CXXDestructorDecl>(FD)){
602+
HI.ReturnType = "void";
603+
} else {
604+
HI.ReturnType = FD->getReturnType().getAsString(Policy);
605+
606+
QualType FunctionType = FD->getType();
607+
if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) // Lambdas
608+
FunctionType = VD->getType().getDesugaredType(D->getASTContext());
609+
HI.Type = FunctionType.getAsString(Policy);
610+
}
611+
// FIXME: handle variadics.
612+
}
613+
569614
/// Generate a \p Hover object given the declaration \p D.
570615
static HoverInfo getHoverContents(const Decl *D, const SymbolIndex *Index) {
571616
HoverInfo HI;
@@ -601,45 +646,7 @@ static HoverInfo getHoverContents(const Decl *D, const SymbolIndex *Index) {
601646

602647
// Fill in types and params.
603648
if (const FunctionDecl *FD = getUnderlyingFunction(D)) {
604-
HI.ReturnType.emplace();
605-
{
606-
llvm::raw_string_ostream OS(*HI.ReturnType);
607-
FD->getReturnType().print(OS, Policy);
608-
}
609-
610-
HI.Parameters.emplace();
611-
for (const ParmVarDecl *PVD : FD->parameters()) {
612-
HI.Parameters->emplace_back();
613-
auto &P = HI.Parameters->back();
614-
if (!PVD->getType().isNull()) {
615-
P.Type.emplace();
616-
llvm::raw_string_ostream OS(*P.Type);
617-
PVD->getType().print(OS, Policy);
618-
} else {
619-
std::string Param;
620-
llvm::raw_string_ostream OS(Param);
621-
PVD->dump(OS);
622-
OS.flush();
623-
elog("Got param with null type: {0}", Param);
624-
}
625-
if (!PVD->getName().empty())
626-
P.Name = PVD->getNameAsString();
627-
if (PVD->hasDefaultArg()) {
628-
P.Default.emplace();
629-
llvm::raw_string_ostream Out(*P.Default);
630-
PVD->getDefaultArg()->printPretty(Out, nullptr, Policy);
631-
}
632-
}
633-
634-
HI.Type.emplace();
635-
llvm::raw_string_ostream TypeOS(*HI.Type);
636-
// Lambdas
637-
if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
638-
VD->getType().getDesugaredType(D->getASTContext()).print(TypeOS, Policy);
639-
// Functions
640-
else
641-
FD->getType().print(TypeOS, Policy);
642-
// FIXME: handle variadics.
649+
fillFunctionTypeAndParams(HI, D, FD, Policy);
643650
} else if (const auto *VD = dyn_cast<ValueDecl>(D)) {
644651
HI.Type.emplace();
645652
llvm::raw_string_ostream OS(*HI.Type);

clang-tools-extra/clangd/unittests/XRefsTests.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -918,11 +918,20 @@ void foo())cpp";
918918
HI.Name = "X";
919919
HI.LocalScope = "X::"; // FIXME: Should be X<T *>::
920920
HI.Kind = SymbolKind::Constructor;
921-
HI.Type = "void ()"; // FIXME: Should be None
922-
HI.ReturnType = "void"; // FIXME: Should be None or X<T*>
921+
HI.ReturnType = "X<T *>";
923922
HI.Definition = "X()";
924923
HI.Parameters.emplace();
925924
}},
925+
{"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]()
926+
[](HoverInfo &HI) {
927+
HI.NamespaceScope = "";
928+
HI.Name = "~X";
929+
HI.LocalScope = "X::";
930+
HI.Kind = SymbolKind::Constructor;
931+
HI.ReturnType = "void";
932+
HI.Definition = "~X()";
933+
HI.Parameters.emplace();
934+
}},
926935

927936
// auto on lambda
928937
{R"cpp(

0 commit comments

Comments
 (0)