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/FormatVariadic.h"
32
40
#include " llvm/Support/SaveAndRestore.h"
33
41
#include " llvm/Support/ScopedPrinter.h"
34
42
#include " llvm/Support/raw_ostream.h"
43
+ #include < algorithm>
44
+ #include < iterator>
35
45
#include < optional>
36
46
#include < string>
37
47
@@ -372,6 +382,34 @@ maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) {
372
382
return Params;
373
383
}
374
384
385
+ llvm::StringRef getLambdaCaptureName (const LambdaCapture &Capture) {
386
+ if (Capture.capturesVariable ())
387
+ return Capture.getCapturedVar ()->getName ();
388
+ if (Capture.capturesThis ())
389
+ return llvm::StringRef{" this" };
390
+ return llvm::StringRef{" unknown" };
391
+ }
392
+
393
+ template <typename R, typename P>
394
+ std::string joinAndTruncate (R &&Range, size_t MaxLength,
395
+ P &&GetAsStringFunction) {
396
+ std::string Out;
397
+ bool IsFirst = true ;
398
+ for (auto &&Element : Range) {
399
+ if (!IsFirst)
400
+ Out.append (" , " );
401
+ else
402
+ IsFirst = false ;
403
+ auto AsString = GetAsStringFunction (Element);
404
+ if (Out.size () + AsString.size () >= MaxLength) {
405
+ Out.append (" ..." );
406
+ break ;
407
+ }
408
+ Out.append (AsString);
409
+ }
410
+ return Out;
411
+ }
412
+
375
413
struct Callee {
376
414
// Only one of Decl or Loc is set.
377
415
// Loc is for calls through function pointers.
@@ -422,7 +460,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
422
460
Callee.Decl = E->getConstructor ();
423
461
if (!Callee.Decl )
424
462
return true ;
425
- processCall (Callee, {E->getArgs (), E->getNumArgs ()});
463
+ processCall (Callee, E->getParenOrBraceRange ().getEnd (),
464
+ {E->getArgs (), E->getNumArgs ()});
426
465
return true ;
427
466
}
428
467
@@ -495,7 +534,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
495
534
dyn_cast_or_null<CXXMethodDecl>(Callee.Decl ))
496
535
if (IsFunctor || Method->hasCXXExplicitFunctionObjectParameter ())
497
536
Args = Args.drop_front (1 );
498
- processCall (Callee, Args);
537
+ processCall (Callee, E-> getRParenLoc (), Args);
499
538
return true ;
500
539
}
501
540
@@ -598,6 +637,15 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
598
637
}
599
638
600
639
bool VisitLambdaExpr (LambdaExpr *E) {
640
+ if (Cfg.InlayHints .LambdaCaptures && E->getCaptureDefault () != LCD_None &&
641
+ !E->implicit_captures ().empty ()) {
642
+ std::string FormattedCaptureList =
643
+ joinAndTruncate (E->implicit_captures (), Cfg.InlayHints .TypeNameLimit ,
644
+ [](const LambdaCapture &ImplicitCapture) {
645
+ return getLambdaCaptureName (ImplicitCapture);
646
+ });
647
+ addImplicitCaptureHint (E->getCaptureDefaultLoc (), FormattedCaptureList);
648
+ }
601
649
FunctionDecl *D = E->getCallOperator ();
602
650
if (!E->hasExplicitResultType ())
603
651
addReturnTypeHint (D, E->hasExplicitParameters ()
@@ -709,7 +757,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
709
757
private:
710
758
using NameVec = SmallVector<StringRef, 8 >;
711
759
712
- void processCall (Callee Callee, llvm::ArrayRef<const Expr *> Args) {
760
+ void processCall (Callee Callee, SourceRange LParenOrBraceRange,
761
+ llvm::ArrayRef<const Expr *> Args) {
713
762
assert (Callee.Decl || Callee.Loc );
714
763
715
764
if (!Cfg.InlayHints .Parameters || Args.size () == 0 )
@@ -721,6 +770,9 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
721
770
if (Ctor->isCopyOrMoveConstructor ())
722
771
return ;
723
772
773
+ SmallVector<std::string> FormattedDefaultArgs;
774
+ bool HasNonDefaultArgs = false ;
775
+
724
776
ArrayRef<const ParmVarDecl *> Params, ForwardedParams;
725
777
// Resolve parameter packs to their forwarded parameter
726
778
SmallVector<const ParmVarDecl *> ForwardedParamsStorage;
@@ -755,12 +807,34 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
755
807
bool NameHint = shouldHintName (Args[I], Name);
756
808
bool ReferenceHint = shouldHintReference (Params[I], ForwardedParams[I]);
757
809
810
+ bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]);
811
+ HasNonDefaultArgs |= !IsDefault;
812
+ if (Cfg.InlayHints .DefaultArguments && IsDefault) {
813
+ auto SourceText = Lexer::getSourceText (
814
+ CharSourceRange::getTokenRange (Params[I]->getDefaultArgRange ()),
815
+ Callee.Decl ->getASTContext ().getSourceManager (),
816
+ Callee.Decl ->getASTContext ().getLangOpts ());
817
+ FormattedDefaultArgs.emplace_back (llvm::formatv (
818
+ " {0} = {1}" , Name,
819
+ SourceText.size () > Cfg.InlayHints .TypeNameLimit ? " ..."
820
+ : SourceText));
821
+ }
822
+
758
823
if (NameHint || ReferenceHint) {
759
824
addInlayHint (Args[I]->getSourceRange (), HintSide::Left,
760
825
InlayHintKind::Parameter, ReferenceHint ? " &" : " " ,
761
826
NameHint ? Name : " " , " : " );
762
827
}
763
828
}
829
+
830
+ if (!FormattedDefaultArgs.empty ()) {
831
+ std::string Hint =
832
+ joinAndTruncate (FormattedDefaultArgs, Cfg.InlayHints .TypeNameLimit ,
833
+ [](const auto &E) { return E; });
834
+ addInlayHint (LParenOrBraceRange, HintSide::Left,
835
+ InlayHintKind::DefaultArgument,
836
+ HasNonDefaultArgs ? " , " : " " , Hint, " " );
837
+ }
764
838
}
765
839
766
840
static bool isSetter (const FunctionDecl *Callee, const NameVec &ParamNames) {
@@ -968,6 +1042,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
968
1042
CHECK_KIND (Type, DeducedTypes);
969
1043
CHECK_KIND (Designator, Designators);
970
1044
CHECK_KIND (BlockEnd, BlockEnd);
1045
+ CHECK_KIND (LambdaCapture, LambdaCaptures);
1046
+ CHECK_KIND (DefaultArgument, DefaultArguments);
971
1047
#undef CHECK_KIND
972
1048
}
973
1049
@@ -1021,6 +1097,11 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
1021
1097
/* Prefix=*/ " " , Text, /* Suffix=*/ " =" );
1022
1098
}
1023
1099
1100
+ void addImplicitCaptureHint (SourceRange R, llvm::StringRef Text) {
1101
+ addInlayHint (R, HintSide::Right, InlayHintKind::LambdaCapture,
1102
+ /* Prefix=*/ " : " , Text, /* Suffix=*/ " " );
1103
+ }
1104
+
1024
1105
bool shouldPrintTypeHint (llvm::StringRef TypeName) const noexcept {
1025
1106
return Cfg.InlayHints .TypeNameLimit == 0 ||
1026
1107
TypeName.size () < Cfg.InlayHints .TypeNameLimit ;
0 commit comments