11
11
#include " Config.h"
12
12
#include " HeuristicResolver.h"
13
13
#include " ParsedAST.h"
14
+ #include " Protocol.h"
14
15
#include " SourceCode.h"
15
16
#include " clang/AST/ASTDiagnostic.h"
16
17
#include " clang/AST/Decl.h"
18
+ #include " clang/AST/DeclBase.h"
17
19
#include " clang/AST/DeclarationName.h"
18
20
#include " clang/AST/Expr.h"
19
21
#include " clang/AST/ExprCXX.h"
23
25
#include " clang/AST/Type.h"
24
26
#include " clang/Basic/Builtins.h"
25
27
#include " clang/Basic/OperatorKinds.h"
28
+ #include " clang/Basic/SourceLocation.h"
26
29
#include " clang/Basic/SourceManager.h"
27
30
#include " llvm/ADT/DenseSet.h"
31
+ #include " llvm/ADT/STLExtras.h"
32
+ #include " llvm/ADT/SmallVector.h"
28
33
#include " llvm/ADT/StringExtras.h"
29
34
#include " llvm/ADT/StringRef.h"
30
35
#include " llvm/ADT/Twine.h"
31
36
#include " llvm/Support/Casting.h"
37
+ #include " llvm/Support/ErrorHandling.h"
38
+ #include " llvm/Support/FormatVariadic.h"
32
39
#include " llvm/Support/SaveAndRestore.h"
33
40
#include " llvm/Support/ScopedPrinter.h"
34
41
#include " llvm/Support/raw_ostream.h"
42
+ #include < algorithm>
43
+ #include < iterator>
35
44
#include < optional>
36
45
#include < string>
37
46
@@ -372,6 +381,23 @@ maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) {
372
381
return Params;
373
382
}
374
383
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
+
375
401
struct Callee {
376
402
// Only one of Decl or Loc is set.
377
403
// Loc is for calls through function pointers.
@@ -422,7 +448,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
422
448
Callee.Decl = E->getConstructor ();
423
449
if (!Callee.Decl )
424
450
return true ;
425
- processCall (Callee, {E->getArgs (), E->getNumArgs ()});
451
+ processCall (Callee, E->getParenOrBraceRange ().getEnd (),
452
+ {E->getArgs (), E->getNumArgs ()});
426
453
return true ;
427
454
}
428
455
@@ -495,7 +522,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
495
522
dyn_cast_or_null<CXXMethodDecl>(Callee.Decl ))
496
523
if (IsFunctor || Method->hasCXXExplicitFunctionObjectParameter ())
497
524
Args = Args.drop_front (1 );
498
- processCall (Callee, Args);
525
+ processCall (Callee, E-> getRParenLoc (), Args);
499
526
return true ;
500
527
}
501
528
@@ -709,10 +736,12 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
709
736
private:
710
737
using NameVec = SmallVector<StringRef, 8 >;
711
738
712
- void processCall (Callee Callee, llvm::ArrayRef<const Expr *> Args) {
739
+ void processCall (Callee Callee, SourceLocation RParenOrBraceLoc,
740
+ llvm::ArrayRef<const Expr *> Args) {
713
741
assert (Callee.Decl || Callee.Loc );
714
742
715
- if (!Cfg.InlayHints .Parameters || Args.size () == 0 )
743
+ if ((!Cfg.InlayHints .Parameters && !Cfg.InlayHints .DefaultArguments ) ||
744
+ Args.size () == 0 )
716
745
return ;
717
746
718
747
// The parameter name of a move or copy constructor is not very interesting.
@@ -721,6 +750,9 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
721
750
if (Ctor->isCopyOrMoveConstructor ())
722
751
return ;
723
752
753
+ SmallVector<std::string> FormattedDefaultArgs;
754
+ bool HasNonDefaultArgs = false ;
755
+
724
756
ArrayRef<const ParmVarDecl *> Params, ForwardedParams;
725
757
// Resolve parameter packs to their forwarded parameter
726
758
SmallVector<const ParmVarDecl *> ForwardedParamsStorage;
@@ -752,15 +784,44 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
752
784
}
753
785
754
786
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) {
759
812
addInlayHint (Args[I]->getSourceRange (), HintSide::Left,
760
813
InlayHintKind::Parameter, ReferenceHint ? " &" : " " ,
761
814
NameHint ? Name : " " , " : " );
762
815
}
763
816
}
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
+ }
764
825
}
765
826
766
827
static bool isSetter (const FunctionDecl *Callee, const NameVec &ParamNames) {
@@ -968,6 +1029,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
968
1029
CHECK_KIND (Type, DeducedTypes);
969
1030
CHECK_KIND (Designator, Designators);
970
1031
CHECK_KIND (BlockEnd, BlockEnd);
1032
+ CHECK_KIND (DefaultArgument, DefaultArguments);
971
1033
#undef CHECK_KIND
972
1034
}
973
1035
0 commit comments