@@ -32,6 +32,14 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
32
32
TypeHintPolicy.SuppressScope = true ; // keep type names short
33
33
TypeHintPolicy.AnonymousTagLocations =
34
34
false ; // do not print lambda locations
35
+ // Print canonical types. Otherwise, SuppressScope would result in
36
+ // things like "metafunction<args>::type" being shorted to just "type",
37
+ // which is useless. This is particularly important for structured
38
+ // bindings that use the tuple_element protocol, where the non-canonical
39
+ // types would be "tuple_element<I, A>::type".
40
+ // Note, for "auto", we would often prefer sugared types, but the AST
41
+ // doesn't currently retain them in DeducedType anyways.
42
+ TypeHintPolicy.PrintCanonicalTypes = true ;
35
43
}
36
44
37
45
bool VisitCXXConstructExpr (CXXConstructExpr *E) {
@@ -76,20 +84,23 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
76
84
if (auto *AT = D->getReturnType ()->getContainedAutoType ()) {
77
85
QualType Deduced = AT->getDeducedType ();
78
86
if (!Deduced.isNull ()) {
79
- addInlayHint (D->getFunctionTypeLoc ().getRParenLoc (),
80
- InlayHintKind::TypeHint,
81
- " -> " + D->getReturnType ().getAsString (TypeHintPolicy));
87
+ addTypeHint (D->getFunctionTypeLoc ().getRParenLoc (), D->getReturnType (),
88
+ " -> " );
82
89
}
83
90
}
84
91
85
92
return true ;
86
93
}
87
94
88
95
bool VisitVarDecl (VarDecl *D) {
89
- // Do not show hints for the aggregate in a structured binding.
90
- // In the future, we may show hints for the individual bindings.
91
- if (isa<DecompositionDecl>(D))
96
+ // Do not show hints for the aggregate in a structured binding,
97
+ // but show hints for the individual bindings.
98
+ if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
99
+ for (auto *Binding : DD->bindings ()) {
100
+ addTypeHint (Binding->getLocation (), Binding->getType (), " : " );
101
+ }
92
102
return true ;
103
+ }
93
104
94
105
if (D->getType ()->getContainedAutoType ()) {
95
106
if (!D->getType ()->isDependentType ()) {
@@ -98,8 +109,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
98
109
// (e.g. for `const auto& x = 42`, print `const int&`).
99
110
// Alternatively, we could place the hint on the `auto`
100
111
// (and then just print the type deduced for the `auto`).
101
- addInlayHint (D->getLocation (), InlayHintKind::TypeHint,
102
- " : " + D->getType ().getAsString (TypeHintPolicy));
112
+ addTypeHint (D->getLocation (), D->getType (), " : " );
103
113
}
104
114
}
105
115
return true ;
@@ -311,6 +321,15 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
311
321
Kind, Label.str ()});
312
322
}
313
323
324
+ void addTypeHint (SourceRange R, QualType T, llvm::StringRef Prefix) {
325
+ // Do not print useless "NULL TYPE" hint.
326
+ if (!T.getTypePtrOrNull ())
327
+ return ;
328
+
329
+ addInlayHint (R, InlayHintKind::TypeHint,
330
+ std::string (Prefix) + T.getAsString (TypeHintPolicy));
331
+ }
332
+
314
333
std::vector<InlayHint> &Results;
315
334
ASTContext &AST;
316
335
FileID MainFileID;
0 commit comments