1111#include " Config.h"
1212#include " HeuristicResolver.h"
1313#include " ParsedAST.h"
14+ #include " Protocol.h"
1415#include " SourceCode.h"
1516#include " clang/AST/ASTDiagnostic.h"
1617#include " clang/AST/Decl.h"
18+ #include " clang/AST/DeclBase.h"
1719#include " clang/AST/DeclarationName.h"
1820#include " clang/AST/Expr.h"
1921#include " clang/AST/ExprCXX.h"
2325#include " clang/AST/Type.h"
2426#include " clang/Basic/Builtins.h"
2527#include " clang/Basic/OperatorKinds.h"
28+ #include " clang/Basic/SourceLocation.h"
2629#include " clang/Basic/SourceManager.h"
2730#include " llvm/ADT/DenseSet.h"
31+ #include " llvm/ADT/STLExtras.h"
32+ #include " llvm/ADT/SmallVector.h"
2833#include " llvm/ADT/StringExtras.h"
2934#include " llvm/ADT/StringRef.h"
3035#include " llvm/ADT/Twine.h"
3136#include " llvm/Support/Casting.h"
37+ #include " llvm/Support/ErrorHandling.h"
38+ #include " llvm/Support/FormatVariadic.h"
3239#include " llvm/Support/SaveAndRestore.h"
3340#include " llvm/Support/ScopedPrinter.h"
3441#include " llvm/Support/raw_ostream.h"
42+ #include < algorithm>
43+ #include < iterator>
3544#include < optional>
3645#include < string>
3746
@@ -372,6 +381,23 @@ maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) {
372381 return Params;
373382}
374383
384+ template <typename R>
385+ std::string joinAndTruncate (const R &Range, size_t MaxLength) {
386+ std::string Out;
387+ llvm::raw_string_ostream OS (Out);
388+ llvm::ListSeparator Sep (" , " );
389+ for (auto &&Element : Range) {
390+ OS << Sep;
391+ if (Out.size () + Element.size () >= MaxLength) {
392+ OS << " ..." ;
393+ break ;
394+ }
395+ OS << Element;
396+ }
397+ OS.flush ();
398+ return Out;
399+ }
400+
375401struct Callee {
376402 // Only one of Decl or Loc is set.
377403 // Loc is for calls through function pointers.
@@ -422,7 +448,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
422448 Callee.Decl = E->getConstructor ();
423449 if (!Callee.Decl )
424450 return true ;
425- processCall (Callee, {E->getArgs (), E->getNumArgs ()});
451+ processCall (Callee, E->getParenOrBraceRange ().getEnd (),
452+ {E->getArgs (), E->getNumArgs ()});
426453 return true ;
427454 }
428455
@@ -495,7 +522,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
495522 dyn_cast_or_null<CXXMethodDecl>(Callee.Decl ))
496523 if (IsFunctor || Method->hasCXXExplicitFunctionObjectParameter ())
497524 Args = Args.drop_front (1 );
498- processCall (Callee, Args);
525+ processCall (Callee, E-> getRParenLoc (), Args);
499526 return true ;
500527 }
501528
@@ -709,10 +736,12 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
709736private:
710737 using NameVec = SmallVector<StringRef, 8 >;
711738
712- void processCall (Callee Callee, llvm::ArrayRef<const Expr *> Args) {
739+ void processCall (Callee Callee, SourceLocation RParenOrBraceLoc,
740+ llvm::ArrayRef<const Expr *> Args) {
713741 assert (Callee.Decl || Callee.Loc );
714742
715- if (!Cfg.InlayHints .Parameters || Args.size () == 0 )
743+ if ((!Cfg.InlayHints .Parameters && !Cfg.InlayHints .DefaultArguments ) ||
744+ Args.size () == 0 )
716745 return ;
717746
718747 // The parameter name of a move or copy constructor is not very interesting.
@@ -721,6 +750,9 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
721750 if (Ctor->isCopyOrMoveConstructor ())
722751 return ;
723752
753+ SmallVector<std::string> FormattedDefaultArgs;
754+ bool HasNonDefaultArgs = false ;
755+
724756 ArrayRef<const ParmVarDecl *> Params, ForwardedParams;
725757 // Resolve parameter packs to their forwarded parameter
726758 SmallVector<const ParmVarDecl *> ForwardedParamsStorage;
@@ -752,15 +784,44 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
752784 }
753785
754786 StringRef Name = ParameterNames[I];
755- bool NameHint = shouldHintName (Args[I], Name);
756- bool ReferenceHint = shouldHintReference (Params[I], ForwardedParams[I]);
757-
758- if (NameHint || ReferenceHint) {
787+ const bool NameHint =
788+ shouldHintName (Args[I], Name) && Cfg.InlayHints .Parameters ;
789+ const bool ReferenceHint =
790+ shouldHintReference (Params[I], ForwardedParams[I]) &&
791+ Cfg.InlayHints .Parameters ;
792+
793+ const bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]);
794+ HasNonDefaultArgs |= !IsDefault;
795+ if (IsDefault) {
796+ if (Cfg.InlayHints .DefaultArguments ) {
797+ const auto SourceText = Lexer::getSourceText (
798+ CharSourceRange::getTokenRange (Params[I]->getDefaultArgRange ()),
799+ AST.getSourceManager (), AST.getLangOpts ());
800+ const auto Abbrev =
801+ (SourceText.size () > Cfg.InlayHints .TypeNameLimit ||
802+ SourceText.contains (" \n " ))
803+ ? " ..."
804+ : SourceText;
805+ if (NameHint)
806+ FormattedDefaultArgs.emplace_back (
807+ llvm::formatv (" {0}: {1}" , Name, Abbrev));
808+ else
809+ FormattedDefaultArgs.emplace_back (llvm::formatv (" {0}" , Abbrev));
810+ }
811+ } else if (NameHint || ReferenceHint) {
759812 addInlayHint (Args[I]->getSourceRange (), HintSide::Left,
760813 InlayHintKind::Parameter, ReferenceHint ? " &" : " " ,
761814 NameHint ? Name : " " , " : " );
762815 }
763816 }
817+
818+ if (!FormattedDefaultArgs.empty ()) {
819+ std::string Hint =
820+ joinAndTruncate (FormattedDefaultArgs, Cfg.InlayHints .TypeNameLimit );
821+ addInlayHint (SourceRange{RParenOrBraceLoc}, HintSide::Left,
822+ InlayHintKind::DefaultArgument,
823+ HasNonDefaultArgs ? " , " : " " , Hint, " " );
824+ }
764825 }
765826
766827 static bool isSetter (const FunctionDecl *Callee, const NameVec &ParamNames) {
@@ -968,6 +1029,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
9681029 CHECK_KIND (Type, DeducedTypes);
9691030 CHECK_KIND (Designator, Designators);
9701031 CHECK_KIND (BlockEnd, BlockEnd);
1032+ CHECK_KIND (DefaultArgument, DefaultArguments);
9711033#undef CHECK_KIND
9721034 }
9731035
0 commit comments