[clangd] Add hover info for this expr

How about add hover information for `this` expr?
It seems useful to show related information about the class for `this` expr sometimes.

Reviewed By: sammccall

Differential Revision: https://reviews.llvm.org/D92041
This commit is contained in:
xndcn 2020-12-15 09:45:56 +01:00 committed by Sam McCall
parent a2eb07aa55
commit 9c328e7afa
2 changed files with 70 additions and 4 deletions

View File

@ -552,7 +552,8 @@ HoverInfo getHoverContents(const NamedDecl *D, const SymbolIndex *Index) {
/// Generate a \p Hover object given the type \p T.
HoverInfo getHoverContents(QualType T, ASTContext &ASTCtx,
const SymbolIndex *Index) {
const SymbolIndex *Index,
bool SuppressScope = false) {
HoverInfo HI;
if (const auto *D = T->getAsTagDecl()) {
@ -566,6 +567,7 @@ HoverInfo getHoverContents(QualType T, ASTContext &ASTCtx,
// Builtin types
auto Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy());
Policy.SuppressTagKeyword = true;
Policy.SuppressScope = SuppressScope;
HI.Name = T.getAsString(Policy);
}
return HI;
@ -628,15 +630,29 @@ llvm::StringLiteral getNameForExpr(const Expr *E) {
return llvm::StringLiteral("expression");
}
// Generates hover info for evaluatable expressions.
// Generates hover info for `this` and evaluatable expressions.
// FIXME: Support hover for literals (esp user-defined)
llvm::Optional<HoverInfo> getHoverContents(const Expr *E, ParsedAST &AST) {
llvm::Optional<HoverInfo> getHoverContents(const Expr *E, ParsedAST &AST,
const SymbolIndex *Index) {
// There's not much value in hovering over "42" and getting a hover card
// saying "42 is an int", similar for other literals.
if (isLiteral(E))
return llvm::None;
HoverInfo HI;
// For `this` expr we currently generate hover with pointee type.
if (const CXXThisExpr *CTE = dyn_cast<CXXThisExpr>(E)) {
QualType OriginThisType = CTE->getType()->getPointeeType();
QualType ClassType = declaredType(OriginThisType->getAsTagDecl());
// For partial specialization class, origin `this` pointee type will be
// parsed as `InjectedClassNameType`, which will ouput template arguments
// like "type-parameter-0-0". So we retrieve user written class type in this
// case.
QualType PrettyThisType = AST.getASTContext().getPointerType(
QualType(ClassType.getTypePtr(), OriginThisType.getCVRQualifiers()));
return getHoverContents(PrettyThisType, AST.getASTContext(), Index,
/*SuppressScope=*/true);
}
// For expressions we currently print the type and the value, iff it is
// evaluatable.
if (auto Val = printExprValue(E, AST.getASTContext())) {
@ -861,7 +877,7 @@ llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
HI->Value = printExprValue(N, AST.getASTContext());
maybeAddCalleeArgInfo(N, *HI, AST.getASTContext().getPrintingPolicy());
} else if (const Expr *E = N->ASTNode.get<Expr>()) {
HI = getHoverContents(E, AST);
HI = getHoverContents(E, AST, Index);
}
// FIXME: support hovers for other nodes?
// - built-in types

View File

@ -2019,6 +2019,56 @@ TEST(Hover, All) {
HI.NamespaceScope = "";
HI.Definition = "@interface MYObject\n@end";
}},
{
R"cpp(// this expr
// comment
namespace ns {
class Foo {
Foo* bar() {
return [[t^his]];
}
};
}
)cpp",
[](HoverInfo &HI) { HI.Name = "Foo *"; }},
{
R"cpp(// this expr for template class
namespace ns {
template <typename T>
class Foo {
Foo* bar() const {
return [[t^his]];
}
};
}
)cpp",
[](HoverInfo &HI) { HI.Name = "const Foo<T> *"; }},
{
R"cpp(// this expr for specialization class
namespace ns {
template <typename T> class Foo {};
template <>
struct Foo<int> {
Foo* bar() {
return [[thi^s]];
}
};
}
)cpp",
[](HoverInfo &HI) { HI.Name = "Foo<int> *"; }},
{
R"cpp(// this expr for partial specialization struct
namespace ns {
template <typename T, typename F> struct Foo {};
template <typename F>
struct Foo<int, F> {
Foo* bar() const {
return [[thi^s]];
}
};
}
)cpp",
[](HoverInfo &HI) { HI.Name = "const Foo<int, F> *"; }},
};
// Create a tiny index, so tests above can verify documentation is fetched.