10
10
#include " Config.h"
11
11
#include " HeuristicResolver.h"
12
12
#include " ParsedAST.h"
13
+ #include " SourceCode.h"
13
14
#include " clang/AST/Decl.h"
14
15
#include " clang/AST/DeclarationName.h"
15
16
#include " clang/AST/ExprCXX.h"
@@ -192,8 +193,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
192
193
public:
193
194
InlayHintVisitor (std::vector<InlayHint> &Results, ParsedAST &AST,
194
195
const Config &Cfg, llvm::Optional<Range> RestrictRange)
195
- : Results(Results), AST(AST.getASTContext()), Cfg(Cfg ),
196
- RestrictRange (std::move(RestrictRange)),
196
+ : Results(Results), AST(AST.getASTContext()), Tokens(AST.getTokens() ),
197
+ Cfg (Cfg), RestrictRange(std::move(RestrictRange)),
197
198
MainFileID(AST.getSourceManager().getMainFileID()),
198
199
Resolver(AST.getHeuristicResolver()),
199
200
TypeHintPolicy(this ->AST.getPrintingPolicy()),
@@ -227,8 +228,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
227
228
return true ;
228
229
}
229
230
230
- processCall (E->getParenOrBraceRange ().getBegin (), E->getConstructor (),
231
- {E->getArgs (), E->getNumArgs ()});
231
+ processCall (E->getConstructor (), {E->getArgs (), E->getNumArgs ()});
232
232
return true ;
233
233
}
234
234
@@ -254,7 +254,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
254
254
if (!Callee)
255
255
return true ;
256
256
257
- processCall (E-> getRParenLoc (), Callee, {E->getArgs (), E->getNumArgs ()});
257
+ processCall (Callee, {E->getArgs (), E->getNumArgs ()});
258
258
return true ;
259
259
}
260
260
@@ -278,11 +278,11 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
278
278
return true ;
279
279
}
280
280
281
- void addReturnTypeHint (FunctionDecl *D, SourceLocation Loc ) {
281
+ void addReturnTypeHint (FunctionDecl *D, SourceRange Range ) {
282
282
auto *AT = D->getReturnType ()->getContainedAutoType ();
283
283
if (!AT || AT->getDeducedType ().isNull ())
284
284
return ;
285
- addTypeHint (Loc , D->getReturnType (), /* Prefix=*/ " -> " );
285
+ addTypeHint (Range , D->getReturnType (), /* Prefix=*/ " -> " );
286
286
}
287
287
288
288
bool VisitVarDecl (VarDecl *D) {
@@ -375,21 +375,11 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
375
375
private:
376
376
using NameVec = SmallVector<StringRef, 8 >;
377
377
378
- // The purpose of Anchor is to deal with macros. It should be the call's
379
- // opening or closing parenthesis or brace. (Always using the opening would
380
- // make more sense but CallExpr only exposes the closing.) We heuristically
381
- // assume that if this location does not come from a macro definition, then
382
- // the entire argument list likely appears in the main file and can be hinted.
383
- void processCall (SourceLocation Anchor, const FunctionDecl *Callee,
378
+ void processCall (const FunctionDecl *Callee,
384
379
llvm::ArrayRef<const Expr *> Args) {
385
380
if (!Cfg.InlayHints .Parameters || Args.size () == 0 || !Callee)
386
381
return ;
387
382
388
- // If the anchor location comes from a macro defintion, there's nowhere to
389
- // put hints.
390
- if (!AST.getSourceManager ().getTopMacroCallerLoc (Anchor).isFileID ())
391
- return ;
392
-
393
383
// The parameter name of a move or copy constructor is not very interesting.
394
384
if (auto *Ctor = dyn_cast<CXXConstructorDecl>(Callee))
395
385
if (Ctor->isCopyOrMoveConstructor ())
@@ -637,25 +627,33 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
637
627
#undef CHECK_KIND
638
628
}
639
629
640
- auto FileRange =
641
- toHalfOpenFileRange (AST.getSourceManager (), AST.getLangOpts (), R);
642
- if (!FileRange)
630
+ auto LSPRange = getHintRange (R);
631
+ if (!LSPRange)
643
632
return ;
644
- Range LSPRange{
645
- sourceLocToPosition (AST.getSourceManager (), FileRange->getBegin ()),
646
- sourceLocToPosition (AST.getSourceManager (), FileRange->getEnd ())};
647
- Position LSPPos = Side == HintSide::Left ? LSPRange.start : LSPRange.end ;
633
+ Position LSPPos = Side == HintSide::Left ? LSPRange->start : LSPRange->end ;
648
634
if (RestrictRange &&
649
635
(LSPPos < RestrictRange->start || !(LSPPos < RestrictRange->end )))
650
636
return ;
651
- // The hint may be in a file other than the main file (for example, a header
652
- // file that was included after the preamble), do not show in that case.
653
- if (!AST.getSourceManager ().isWrittenInMainFile (FileRange->getBegin ()))
654
- return ;
655
637
bool PadLeft = Prefix.consume_front (" " );
656
638
bool PadRight = Suffix.consume_back (" " );
657
639
Results.push_back (InlayHint{LSPPos, (Prefix + Label + Suffix).str (), Kind,
658
- PadLeft, PadRight, LSPRange});
640
+ PadLeft, PadRight, *LSPRange});
641
+ }
642
+
643
+ // Get the range of the main file that *exactly* corresponds to R.
644
+ llvm::Optional<Range> getHintRange (SourceRange R) {
645
+ const auto &SM = AST.getSourceManager ();
646
+ auto Spelled = Tokens.spelledForExpanded (Tokens.expandedTokens (R));
647
+ // TokenBuffer will return null if e.g. R corresponds to only part of a
648
+ // macro expansion.
649
+ if (!Spelled || Spelled->empty ())
650
+ return llvm::None;
651
+ // Hint must be within the main file, not e.g. a non-preamble include.
652
+ if (SM.getFileID (Spelled->front ().location ()) != SM.getMainFileID () ||
653
+ SM.getFileID (Spelled->back ().location ()) != SM.getMainFileID ())
654
+ return llvm::None;
655
+ return Range{sourceLocToPosition (SM, Spelled->front ().location ()),
656
+ sourceLocToPosition (SM, Spelled->back ().endLocation ())};
659
657
}
660
658
661
659
void addTypeHint (SourceRange R, QualType T, llvm::StringRef Prefix) {
@@ -680,6 +678,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
680
678
681
679
std::vector<InlayHint> &Results;
682
680
ASTContext &AST;
681
+ const syntax::TokenBuffer &Tokens;
683
682
const Config &Cfg;
684
683
llvm::Optional<Range> RestrictRange;
685
684
FileID MainFileID;
0 commit comments