1010#include " Config.h"
1111#include " HeuristicResolver.h"
1212#include " ParsedAST.h"
13+ #include " SourceCode.h"
1314#include " clang/AST/Decl.h"
1415#include " clang/AST/DeclarationName.h"
1516#include " clang/AST/ExprCXX.h"
@@ -192,8 +193,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
192193public:
193194 InlayHintVisitor (std::vector<InlayHint> &Results, ParsedAST &AST,
194195 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)),
197198 MainFileID(AST.getSourceManager().getMainFileID()),
198199 Resolver(AST.getHeuristicResolver()),
199200 TypeHintPolicy(this ->AST.getPrintingPolicy()),
@@ -227,8 +228,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
227228 return true ;
228229 }
229230
230- processCall (E->getParenOrBraceRange ().getBegin (), E->getConstructor (),
231- {E->getArgs (), E->getNumArgs ()});
231+ processCall (E->getConstructor (), {E->getArgs (), E->getNumArgs ()});
232232 return true ;
233233 }
234234
@@ -254,7 +254,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
254254 if (!Callee)
255255 return true ;
256256
257- processCall (E-> getRParenLoc (), Callee, {E->getArgs (), E->getNumArgs ()});
257+ processCall (Callee, {E->getArgs (), E->getNumArgs ()});
258258 return true ;
259259 }
260260
@@ -278,11 +278,11 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
278278 return true ;
279279 }
280280
281- void addReturnTypeHint (FunctionDecl *D, SourceLocation Loc ) {
281+ void addReturnTypeHint (FunctionDecl *D, SourceRange Range ) {
282282 auto *AT = D->getReturnType ()->getContainedAutoType ();
283283 if (!AT || AT->getDeducedType ().isNull ())
284284 return ;
285- addTypeHint (Loc , D->getReturnType (), /* Prefix=*/ " -> " );
285+ addTypeHint (Range , D->getReturnType (), /* Prefix=*/ " -> " );
286286 }
287287
288288 bool VisitVarDecl (VarDecl *D) {
@@ -375,21 +375,11 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
375375private:
376376 using NameVec = SmallVector<StringRef, 8 >;
377377
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,
384379 llvm::ArrayRef<const Expr *> Args) {
385380 if (!Cfg.InlayHints .Parameters || Args.size () == 0 || !Callee)
386381 return ;
387382
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-
393383 // The parameter name of a move or copy constructor is not very interesting.
394384 if (auto *Ctor = dyn_cast<CXXConstructorDecl>(Callee))
395385 if (Ctor->isCopyOrMoveConstructor ())
@@ -637,25 +627,33 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
637627#undef CHECK_KIND
638628 }
639629
640- auto FileRange =
641- toHalfOpenFileRange (AST.getSourceManager (), AST.getLangOpts (), R);
642- if (!FileRange)
630+ auto LSPRange = getHintRange (R);
631+ if (!LSPRange)
643632 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 ;
648634 if (RestrictRange &&
649635 (LSPPos < RestrictRange->start || !(LSPPos < RestrictRange->end )))
650636 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 ;
655637 bool PadLeft = Prefix.consume_front (" " );
656638 bool PadRight = Suffix.consume_back (" " );
657639 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 ())};
659657 }
660658
661659 void addTypeHint (SourceRange R, QualType T, llvm::StringRef Prefix) {
@@ -680,6 +678,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
680678
681679 std::vector<InlayHint> &Results;
682680 ASTContext &AST;
681+ const syntax::TokenBuffer &Tokens;
683682 const Config &Cfg;
684683 llvm::Optional<Range> RestrictRange;
685684 FileID MainFileID;
0 commit comments