1313#include " SourceCode.h"
1414#include " clang/AST/ASTDiagnostic.h"
1515#include " clang/AST/Decl.h"
16+ #include " clang/AST/DeclBase.h"
1617#include " clang/AST/DeclarationName.h"
1718#include " clang/AST/Expr.h"
1819#include " clang/AST/ExprCXX.h"
20+ #include " clang/AST/LambdaCapture.h"
1921#include " clang/AST/RecursiveASTVisitor.h"
2022#include " clang/AST/Stmt.h"
2123#include " clang/AST/StmtVisitor.h"
2224#include " clang/AST/Type.h"
2325#include " clang/Basic/Builtins.h"
26+ #include " clang/Basic/Lambda.h"
2427#include " clang/Basic/OperatorKinds.h"
28+ #include " clang/Basic/SourceLocation.h"
2529#include " clang/Basic/SourceManager.h"
2630#include " llvm/ADT/DenseSet.h"
31+ #include " llvm/ADT/STLExtras.h"
2732#include " llvm/ADT/ScopeExit.h"
33+ #include " llvm/ADT/SmallVector.h"
2834#include " llvm/ADT/StringExtras.h"
2935#include " llvm/ADT/StringRef.h"
3036#include " llvm/ADT/Twine.h"
3137#include " llvm/Support/Casting.h"
3238#include " llvm/Support/SaveAndRestore.h"
3339#include " llvm/Support/ScopedPrinter.h"
3440#include " llvm/Support/raw_ostream.h"
41+ #include < algorithm>
42+ #include < iterator>
3543#include < optional>
3644#include < string>
3745
@@ -535,6 +543,34 @@ maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) {
535543 return Params;
536544}
537545
546+ llvm::StringRef getLambdaCaptureName (const LambdaCapture &Capture) {
547+ if (Capture.capturesVariable ())
548+ return Capture.getCapturedVar ()->getName ();
549+ if (Capture.capturesThis ())
550+ return llvm::StringRef{" this" };
551+ return llvm::StringRef{" unknown" };
552+ }
553+
554+ template <typename R, typename P>
555+ std::string joinAndTruncate (R &&Range, size_t MaxLength,
556+ P &&GetAsStringFunction) {
557+ std::string Out;
558+ bool IsFirst = true ;
559+ for (auto &&Element : Range) {
560+ if (!IsFirst)
561+ Out.append (" , " );
562+ else
563+ IsFirst = false ;
564+ auto AsString = GetAsStringFunction (Element);
565+ if (Out.size () + AsString.size () >= MaxLength) {
566+ Out.append (" ..." );
567+ break ;
568+ }
569+ Out.append (AsString);
570+ }
571+ return Out;
572+ }
573+
538574struct Callee {
539575 // Only one of Decl or Loc is set.
540576 // Loc is for calls through function pointers.
@@ -585,7 +621,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
585621 Callee.Decl = E->getConstructor ();
586622 if (!Callee.Decl )
587623 return true ;
588- processCall (Callee, {E->getArgs (), E->getNumArgs ()});
624+ processCall (Callee, E->getParenOrBraceRange ().getEnd (),
625+ {E->getArgs (), E->getNumArgs ()});
589626 return true ;
590627 }
591628
@@ -614,6 +651,13 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
614651 return RecursiveASTVisitor<InlayHintVisitor>::TraversePseudoObjectExpr (E);
615652 }
616653
654+ bool VisitCXXThisExpr (CXXThisExpr *CTE) {
655+ if (Cfg.InlayHints .ImplicitThis && CTE->isImplicit ())
656+ addInlayHint (CTE->getLocation (), HintSide::Left,
657+ InlayHintKind::ImplicitThis, " " , " this->" , " " );
658+ return true ;
659+ }
660+
617661 bool VisitCallExpr (CallExpr *E) {
618662 if (!Cfg.InlayHints .Parameters )
619663 return true ;
@@ -658,7 +702,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
658702 dyn_cast_or_null<CXXMethodDecl>(Callee.Decl ))
659703 if (IsFunctor || Method->hasCXXExplicitFunctionObjectParameter ())
660704 Args = Args.drop_front (1 );
661- processCall (Callee, Args);
705+ processCall (Callee, E-> getRParenLoc (), Args);
662706 return true ;
663707 }
664708
@@ -761,6 +805,15 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
761805 }
762806
763807 bool VisitLambdaExpr (LambdaExpr *E) {
808+ if (Cfg.InlayHints .LambdaCaptures && E->getCaptureDefault () != LCD_None &&
809+ !E->implicit_captures ().empty ()) {
810+ std::string FormattedCaptureList =
811+ joinAndTruncate (E->implicit_captures (), Cfg.InlayHints .TypeNameLimit ,
812+ [](const LambdaCapture &ImplicitCapture) {
813+ return getLambdaCaptureName (ImplicitCapture);
814+ });
815+ addImplicitCaptureHint (E->getCaptureDefaultLoc (), FormattedCaptureList);
816+ }
764817 FunctionDecl *D = E->getCallOperator ();
765818 if (!E->hasExplicitResultType ())
766819 addReturnTypeHint (D, E->hasExplicitParameters ()
@@ -777,6 +830,14 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
777830 }
778831
779832 bool VisitVarDecl (VarDecl *D) {
833+ if (Cfg.InlayHints .DefaultInitializations && D->hasInit () &&
834+ isa<CXXConstructExpr>(D->getInit ()) &&
835+ !llvm::dyn_cast<CXXConstructExpr>(D->getInit ())
836+ ->getParenOrBraceRange ()
837+ .isValid ())
838+ addInlayHint (D->getEndLoc (), HintSide::Right, InlayHintKind::DefaultInit,
839+ " " , " {}" , " " );
840+
780841 // Do not show hints for the aggregate in a structured binding,
781842 // but show hints for the individual bindings.
782843 if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
@@ -871,7 +932,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
871932private:
872933 using NameVec = SmallVector<StringRef, 8 >;
873934
874- void processCall (Callee Callee, llvm::ArrayRef<const Expr *> Args) {
935+ void processCall (Callee Callee, SourceRange LParenOrBraceRange,
936+ llvm::ArrayRef<const Expr *> Args) {
875937 assert (Callee.Decl || Callee.Loc );
876938
877939 if (!Cfg.InlayHints .Parameters || Args.size () == 0 )
@@ -883,6 +945,9 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
883945 if (Ctor->isCopyOrMoveConstructor ())
884946 return ;
885947
948+ SmallVector<std::string> FormattedDefaultArgs;
949+ bool HasNonDefaultArgs = false ;
950+
886951 ArrayRef<const ParmVarDecl *> Params, ForwardedParams;
887952 // Resolve parameter packs to their forwarded parameter
888953 SmallVector<const ParmVarDecl *> ForwardedParamsStorage;
@@ -917,12 +982,34 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
917982 bool NameHint = shouldHintName (Args[I], Name);
918983 bool ReferenceHint = shouldHintReference (Params[I], ForwardedParams[I]);
919984
985+ bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]);
986+ HasNonDefaultArgs |= !IsDefault;
987+ if (Cfg.InlayHints .DefaultArguments && IsDefault) {
988+ auto SourceText = Lexer::getSourceText (
989+ CharSourceRange::getTokenRange (Params[I]->getDefaultArgRange ()),
990+ Callee.Decl ->getASTContext ().getSourceManager (),
991+ Callee.Decl ->getASTContext ().getLangOpts ());
992+ FormattedDefaultArgs.emplace_back (llvm::formatv (
993+ " {0} = {1}" , Name,
994+ SourceText.size () > Cfg.InlayHints .TypeNameLimit ? " ..."
995+ : SourceText));
996+ }
997+
920998 if (NameHint || ReferenceHint) {
921999 addInlayHint (Args[I]->getSourceRange (), HintSide::Left,
9221000 InlayHintKind::Parameter, ReferenceHint ? " &" : " " ,
9231001 NameHint ? Name : " " , " : " );
9241002 }
9251003 }
1004+
1005+ if (!FormattedDefaultArgs.empty ()) {
1006+ std::string Hint =
1007+ joinAndTruncate (FormattedDefaultArgs, Cfg.InlayHints .TypeNameLimit ,
1008+ [](const auto &E) { return E; });
1009+ addInlayHint (LParenOrBraceRange, HintSide::Left,
1010+ InlayHintKind::DefaultArgument,
1011+ HasNonDefaultArgs ? " , " : " " , Hint, " " );
1012+ }
9261013 }
9271014
9281015 static bool isSetter (const FunctionDecl *Callee, const NameVec &ParamNames) {
@@ -1130,6 +1217,10 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
11301217 CHECK_KIND (Type, DeducedTypes);
11311218 CHECK_KIND (Designator, Designators);
11321219 CHECK_KIND (BlockEnd, BlockEnd);
1220+ CHECK_KIND (LambdaCapture, LambdaCaptures);
1221+ CHECK_KIND (DefaultArgument, DefaultArguments);
1222+ CHECK_KIND (DefaultInit, DefaultInitializations);
1223+ CHECK_KIND (ImplicitThis, ImplicitThis);
11331224#undef CHECK_KIND
11341225 }
11351226
@@ -1182,6 +1273,11 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
11821273 /* Prefix=*/ " " , Text, /* Suffix=*/ " =" );
11831274 }
11841275
1276+ void addImplicitCaptureHint (SourceRange R, llvm::StringRef Text) {
1277+ addInlayHint (R, HintSide::Right, InlayHintKind::LambdaCapture,
1278+ /* Prefix=*/ " : " , Text, /* Suffix=*/ " " );
1279+ }
1280+
11851281 bool shouldPrintTypeHint (llvm::StringRef TypeName) const noexcept {
11861282 return Cfg.InlayHints .TypeNameLimit == 0 ||
11871283 TypeName.size () < Cfg.InlayHints .TypeNameLimit ;
0 commit comments