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"
22
+ #include " clang/AST/LambdaCapture.h"
20
23
#include " clang/AST/RecursiveASTVisitor.h"
21
24
#include " clang/AST/Stmt.h"
22
25
#include " clang/AST/StmtVisitor.h"
23
26
#include " clang/AST/Type.h"
24
27
#include " clang/Basic/Builtins.h"
28
+ #include " clang/Basic/Lambda.h"
25
29
#include " clang/Basic/OperatorKinds.h"
30
+ #include " clang/Basic/SourceLocation.h"
26
31
#include " clang/Basic/SourceManager.h"
27
32
#include " llvm/ADT/DenseSet.h"
33
+ #include " llvm/ADT/STLExtras.h"
34
+ #include " llvm/ADT/SmallVector.h"
28
35
#include " llvm/ADT/StringExtras.h"
29
36
#include " llvm/ADT/StringRef.h"
30
37
#include " llvm/ADT/Twine.h"
31
38
#include " llvm/Support/Casting.h"
39
+ #include " llvm/Support/ErrorHandling.h"
40
+ #include " llvm/Support/FormatVariadic.h"
32
41
#include " llvm/Support/SaveAndRestore.h"
33
42
#include " llvm/Support/ScopedPrinter.h"
34
43
#include " llvm/Support/raw_ostream.h"
44
+ #include < algorithm>
45
+ #include < iterator>
35
46
#include < optional>
36
47
#include < string>
37
48
@@ -372,6 +383,38 @@ maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) {
372
383
return Params;
373
384
}
374
385
386
+ llvm::StringRef getLambdaCaptureName (const LambdaCapture &Capture) {
387
+ switch (Capture.getCaptureKind ()) {
388
+ case LCK_This:
389
+ case LCK_StarThis:
390
+ return llvm::StringRef{" this" };
391
+ case LCK_ByCopy:
392
+ case LCK_ByRef:
393
+ case LCK_VLAType:
394
+ return Capture.getCapturedVar ()->getName ();
395
+ }
396
+ llvm_unreachable (" unhandled capture kind" );
397
+ }
398
+
399
+ template <typename R, typename P>
400
+ std::string joinAndTruncate (R &&Range, size_t MaxLength,
401
+ P &&GetAsStringFunction) {
402
+ std::string Out;
403
+ llvm::raw_string_ostream OS (Out);
404
+ llvm::ListSeparator Sep (" , " );
405
+ for (auto &&Element : Range) {
406
+ OS << Sep;
407
+ auto AsString = GetAsStringFunction (Element);
408
+ if (Out.size () + AsString.size () >= MaxLength) {
409
+ OS << " ..." ;
410
+ break ;
411
+ }
412
+ OS << AsString;
413
+ }
414
+ OS.flush ();
415
+ return Out;
416
+ }
417
+
375
418
struct Callee {
376
419
// Only one of Decl or Loc is set.
377
420
// Loc is for calls through function pointers.
@@ -422,7 +465,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
422
465
Callee.Decl = E->getConstructor ();
423
466
if (!Callee.Decl )
424
467
return true ;
425
- processCall (Callee, {E->getArgs (), E->getNumArgs ()});
468
+ processCall (Callee, E->getParenOrBraceRange ().getEnd (),
469
+ {E->getArgs (), E->getNumArgs ()});
426
470
return true ;
427
471
}
428
472
@@ -495,7 +539,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
495
539
dyn_cast_or_null<CXXMethodDecl>(Callee.Decl ))
496
540
if (IsFunctor || Method->hasCXXExplicitFunctionObjectParameter ())
497
541
Args = Args.drop_front (1 );
498
- processCall (Callee, Args);
542
+ processCall (Callee, E-> getRParenLoc (), Args);
499
543
return true ;
500
544
}
501
545
@@ -598,6 +642,15 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
598
642
}
599
643
600
644
bool VisitLambdaExpr (LambdaExpr *E) {
645
+ if (Cfg.InlayHints .LambdaCaptures && E->getCaptureDefault () != LCD_None &&
646
+ !E->implicit_captures ().empty ()) {
647
+ std::string FormattedCaptureList =
648
+ joinAndTruncate (E->implicit_captures (), Cfg.InlayHints .TypeNameLimit ,
649
+ [](const LambdaCapture &ImplicitCapture) {
650
+ return getLambdaCaptureName (ImplicitCapture);
651
+ });
652
+ addImplicitCaptureHint (E->getCaptureDefaultLoc (), FormattedCaptureList);
653
+ }
601
654
FunctionDecl *D = E->getCallOperator ();
602
655
if (!E->hasExplicitResultType ())
603
656
addReturnTypeHint (D, E->hasExplicitParameters ()
@@ -709,7 +762,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
709
762
private:
710
763
using NameVec = SmallVector<StringRef, 8 >;
711
764
712
- void processCall (Callee Callee, llvm::ArrayRef<const Expr *> Args) {
765
+ void processCall (Callee Callee, SourceRange LParenOrBraceRange,
766
+ llvm::ArrayRef<const Expr *> Args) {
713
767
assert (Callee.Decl || Callee.Loc );
714
768
715
769
if (!Cfg.InlayHints .Parameters || Args.size () == 0 )
@@ -721,6 +775,9 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
721
775
if (Ctor->isCopyOrMoveConstructor ())
722
776
return ;
723
777
778
+ SmallVector<std::string> FormattedDefaultArgs;
779
+ bool HasNonDefaultArgs = false ;
780
+
724
781
ArrayRef<const ParmVarDecl *> Params, ForwardedParams;
725
782
// Resolve parameter packs to their forwarded parameter
726
783
SmallVector<const ParmVarDecl *> ForwardedParamsStorage;
@@ -755,12 +812,33 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
755
812
bool NameHint = shouldHintName (Args[I], Name);
756
813
bool ReferenceHint = shouldHintReference (Params[I], ForwardedParams[I]);
757
814
815
+ bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]);
816
+ HasNonDefaultArgs |= !IsDefault;
817
+ if (Cfg.InlayHints .DefaultArguments && IsDefault) {
818
+ auto SourceText = Lexer::getSourceText (
819
+ CharSourceRange::getTokenRange (Params[I]->getDefaultArgRange ()),
820
+ AST.getSourceManager (), AST.getLangOpts ());
821
+ FormattedDefaultArgs.emplace_back (llvm::formatv (
822
+ " {0} = {1}" , Name,
823
+ SourceText.size () > Cfg.InlayHints .TypeNameLimit ? " ..."
824
+ : SourceText));
825
+ }
826
+
758
827
if (NameHint || ReferenceHint) {
759
828
addInlayHint (Args[I]->getSourceRange (), HintSide::Left,
760
829
InlayHintKind::Parameter, ReferenceHint ? " &" : " " ,
761
830
NameHint ? Name : " " , " : " );
762
831
}
763
832
}
833
+
834
+ if (!FormattedDefaultArgs.empty ()) {
835
+ std::string Hint =
836
+ joinAndTruncate (FormattedDefaultArgs, Cfg.InlayHints .TypeNameLimit ,
837
+ [](const auto &E) { return E; });
838
+ addInlayHint (LParenOrBraceRange, HintSide::Left,
839
+ InlayHintKind::DefaultArgument,
840
+ HasNonDefaultArgs ? " , " : " " , Hint, " " );
841
+ }
764
842
}
765
843
766
844
static bool isSetter (const FunctionDecl *Callee, const NameVec &ParamNames) {
@@ -968,6 +1046,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
968
1046
CHECK_KIND (Type, DeducedTypes);
969
1047
CHECK_KIND (Designator, Designators);
970
1048
CHECK_KIND (BlockEnd, BlockEnd);
1049
+ CHECK_KIND (LambdaCapture, LambdaCaptures);
1050
+ CHECK_KIND (DefaultArgument, DefaultArguments);
971
1051
#undef CHECK_KIND
972
1052
}
973
1053
@@ -1021,6 +1101,11 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
1021
1101
/* Prefix=*/ " " , Text, /* Suffix=*/ " =" );
1022
1102
}
1023
1103
1104
+ void addImplicitCaptureHint (SourceRange R, llvm::StringRef Text) {
1105
+ addInlayHint (R, HintSide::Right, InlayHintKind::LambdaCapture,
1106
+ /* Prefix=*/ " : " , Text, /* Suffix=*/ " " );
1107
+ }
1108
+
1024
1109
bool shouldPrintTypeHint (llvm::StringRef TypeName) const noexcept {
1025
1110
return Cfg.InlayHints .TypeNameLimit == 0 ||
1026
1111
TypeName.size () < Cfg.InlayHints .TypeNameLimit ;
0 commit comments