Skip to content

Commit c46c7c9

Browse files
qchateausam-mccall
authored andcommitted
[clangd] Smarter hover on auto and decltype
Only show the keyword as the hover "Name". Show whether the type is deduced or undeduced as the hover "Documentation". Show the deduced type (if any) as the "Definition". Don't show any hover information for: - the "auto" word of "decltype(auto)" - "auto" in lambda parameters - "auto" in template arguments --------------- This diff is a suggestion based on what @sammccall suggested in https://reviews.llvm.org/D92977 about hover on "auto". It somehow "hacks" onto the "Documentation" and "Definition" fields of `HoverInfo`. It sure looks good on VSCode, let me know if this seem acceptable to you. Reviewed By: sammccall Differential Revision: https://reviews.llvm.org/D93227
1 parent 47aaa99 commit c46c7c9

File tree

5 files changed

+342
-130
lines changed

5 files changed

+342
-130
lines changed

clang-tools-extra/clangd/AST.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,7 @@ class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
350350
return true;
351351

352352
if (auto *AT = D->getType()->getContainedAutoType()) {
353-
if (!AT->getDeducedType().isNull())
354-
DeducedType = AT->getDeducedType();
353+
DeducedType = AT->desugar();
355354
}
356355
return true;
357356
}

clang-tools-extra/clangd/AST.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ QualType declaredType(const TypeDecl *D);
109109

110110
/// Retrieves the deduced type at a given location (auto, decltype).
111111
/// It will return the underlying type.
112+
/// If the type is an undeduced auto, returns the type itself.
112113
llvm::Optional<QualType> getDeducedType(ASTContext &, SourceLocation Loc);
113114

114115
/// Gets the nested name specifier necessary for spelling \p ND in \p

clang-tools-extra/clangd/Hover.cpp

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "clang/AST/ExprCXX.h"
2828
#include "clang/AST/OperationKinds.h"
2929
#include "clang/AST/PrettyPrinter.h"
30+
#include "clang/AST/RecursiveASTVisitor.h"
3031
#include "clang/AST/Type.h"
3132
#include "clang/Basic/SourceLocation.h"
3233
#include "clang/Basic/Specifiers.h"
@@ -550,29 +551,6 @@ HoverInfo getHoverContents(const NamedDecl *D, const SymbolIndex *Index) {
550551
return HI;
551552
}
552553

553-
/// Generate a \p Hover object given the type \p T.
554-
HoverInfo getHoverContents(QualType T, ASTContext &ASTCtx,
555-
const SymbolIndex *Index,
556-
bool SuppressScope = false) {
557-
HoverInfo HI;
558-
559-
if (const auto *D = T->getAsTagDecl()) {
560-
HI.Name = printName(ASTCtx, *D);
561-
HI.Kind = index::getSymbolInfo(D).Kind;
562-
563-
const auto *CommentD = getDeclForComment(D);
564-
HI.Documentation = getDeclComment(ASTCtx, *CommentD);
565-
enhanceFromIndex(HI, *CommentD, Index);
566-
} else {
567-
// Builtin types
568-
auto Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy());
569-
Policy.SuppressTagKeyword = true;
570-
Policy.SuppressScope = SuppressScope;
571-
HI.Name = T.getAsString(Policy);
572-
}
573-
return HI;
574-
}
575-
576554
/// Generate a \p Hover object given the macro \p MacroDecl.
577555
HoverInfo getHoverContents(const DefinedMacro &Macro, ParsedAST &AST) {
578556
HoverInfo HI;
@@ -608,6 +586,52 @@ HoverInfo getHoverContents(const DefinedMacro &Macro, ParsedAST &AST) {
608586
return HI;
609587
}
610588

589+
llvm::Optional<HoverInfo> getThisExprHoverContents(const CXXThisExpr *CTE,
590+
ASTContext &ASTCtx) {
591+
QualType OriginThisType = CTE->getType()->getPointeeType();
592+
QualType ClassType = declaredType(OriginThisType->getAsTagDecl());
593+
// For partial specialization class, origin `this` pointee type will be
594+
// parsed as `InjectedClassNameType`, which will ouput template arguments
595+
// like "type-parameter-0-0". So we retrieve user written class type in this
596+
// case.
597+
QualType PrettyThisType = ASTCtx.getPointerType(
598+
QualType(ClassType.getTypePtr(), OriginThisType.getCVRQualifiers()));
599+
600+
auto Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy());
601+
Policy.SuppressTagKeyword = true;
602+
Policy.SuppressScope = true;
603+
HoverInfo HI;
604+
HI.Name = "this";
605+
HI.Definition = PrettyThisType.getAsString(Policy);
606+
return HI;
607+
}
608+
609+
/// Generate a HoverInfo object given the deduced type \p QT
610+
HoverInfo getDeducedTypeHoverContents(QualType QT, const syntax::Token &Tok,
611+
ASTContext &ASTCtx,
612+
const SymbolIndex *Index) {
613+
HoverInfo HI;
614+
// FIXME: distinguish decltype(auto) vs decltype(expr)
615+
HI.Name = tok::getTokenName(Tok.kind());
616+
HI.Kind = index::SymbolKind::TypeAlias;
617+
618+
auto PP = printingPolicyForDecls(ASTCtx.getLangOpts());
619+
620+
if (QT->isUndeducedAutoType()) {
621+
HI.Definition = "/* not deduced */";
622+
} else {
623+
HI.Definition = QT.getAsString(PP);
624+
625+
if (const auto *D = QT->getAsTagDecl()) {
626+
const auto *CommentD = getDeclForComment(D);
627+
HI.Documentation = getDeclComment(ASTCtx, *CommentD);
628+
enhanceFromIndex(HI, *CommentD, Index);
629+
}
630+
}
631+
632+
return HI;
633+
}
634+
611635
bool isLiteral(const Expr *E) {
612636
// Unfortunately there's no common base Literal classes inherits from
613637
// (apart from Expr), therefore these exclusions.
@@ -641,18 +665,8 @@ llvm::Optional<HoverInfo> getHoverContents(const Expr *E, ParsedAST &AST,
641665

642666
HoverInfo HI;
643667
// For `this` expr we currently generate hover with pointee type.
644-
if (const CXXThisExpr *CTE = dyn_cast<CXXThisExpr>(E)) {
645-
QualType OriginThisType = CTE->getType()->getPointeeType();
646-
QualType ClassType = declaredType(OriginThisType->getAsTagDecl());
647-
// For partial specialization class, origin `this` pointee type will be
648-
// parsed as `InjectedClassNameType`, which will ouput template arguments
649-
// like "type-parameter-0-0". So we retrieve user written class type in this
650-
// case.
651-
QualType PrettyThisType = AST.getASTContext().getPointerType(
652-
QualType(ClassType.getTypePtr(), OriginThisType.getCVRQualifiers()));
653-
return getHoverContents(PrettyThisType, AST.getASTContext(), Index,
654-
/*SuppressScope=*/true);
655-
}
668+
if (const CXXThisExpr *CTE = dyn_cast<CXXThisExpr>(E))
669+
return getThisExprHoverContents(CTE, AST.getASTContext());
656670
// For expressions we currently print the type and the value, iff it is
657671
// evaluatable.
658672
if (auto Val = printExprValue(E, AST.getASTContext())) {
@@ -849,10 +863,16 @@ llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
849863
}
850864
} else if (Tok.kind() == tok::kw_auto || Tok.kind() == tok::kw_decltype) {
851865
if (auto Deduced = getDeducedType(AST.getASTContext(), Tok.location())) {
852-
HI = getHoverContents(*Deduced, AST.getASTContext(), Index);
866+
HI = getDeducedTypeHoverContents(*Deduced, Tok, AST.getASTContext(),
867+
Index);
853868
HighlightRange = Tok.range(SM).toCharRange(SM);
854869
break;
855870
}
871+
872+
// If we can't find interesting hover information for this
873+
// auto/decltype keyword, return nothing to avoid showing
874+
// irrelevant or incorrect informations.
875+
return llvm::None;
856876
}
857877
}
858878

clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Expected<Tweak::Effect> ExpandAutoType::apply(const Selection& Inputs) {
106106
Inputs.AST->getASTContext(), CachedLocation->getBeginLoc());
107107

108108
// if we can't resolve the type, return an error message
109-
if (DeducedType == llvm::None)
109+
if (DeducedType == llvm::None || (*DeducedType)->isUndeducedAutoType())
110110
return error("Could not deduce type for 'auto' type");
111111

112112
// if it's a lambda expression, return an error message

0 commit comments

Comments
 (0)