https://github.com/torshepherd updated https://github.com/llvm/llvm-project/pull/95712
>From ee08d8cc7760fe39637260408aec2b1e6ab30d0a Mon Sep 17 00:00:00 2001 From: Tor Shepherd <tor.aksel.sheph...@gmail.com> Date: Mon, 23 Sep 2024 23:12:23 -0400 Subject: [PATCH 1/7] just defaults --- clang-tools-extra/clangd/Config.h | 1 + clang-tools-extra/clangd/ConfigCompile.cpp | 6 +- clang-tools-extra/clangd/ConfigFragment.h | 3 + clang-tools-extra/clangd/ConfigYAML.cpp | 5 +- clang-tools-extra/clangd/InlayHints.cpp | 61 ++++++++++++++++++- clang-tools-extra/clangd/Protocol.cpp | 3 + clang-tools-extra/clangd/Protocol.h | 9 +++ .../clangd/unittests/InlayHintTests.cpp | 29 +++++++++ 8 files changed, 112 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h index 8fcbc5c33469fa..e174f7fabe344e 100644 --- a/clang-tools-extra/clangd/Config.h +++ b/clang-tools-extra/clangd/Config.h @@ -162,6 +162,7 @@ struct Config { bool DeducedTypes = true; bool Designators = true; bool BlockEnd = false; + bool DefaultArguments = false; // Limit the length of type names in inlay hints. (0 means no limit) uint32_t TypeNameLimit = 32; } InlayHints; diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp index 58610a5b87922d..fb7692998d05c7 100644 --- a/clang-tools-extra/clangd/ConfigCompile.cpp +++ b/clang-tools-extra/clangd/ConfigCompile.cpp @@ -43,7 +43,6 @@ #include "llvm/Support/Regex.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" -#include <algorithm> #include <memory> #include <optional> #include <string> @@ -669,6 +668,11 @@ struct FragmentCompiler { Out.Apply.push_back([Value(**F.BlockEnd)](const Params &, Config &C) { C.InlayHints.BlockEnd = Value; }); + if (F.DefaultArguments) + Out.Apply.push_back( + [Value(**F.DefaultArguments)](const Params &, Config &C) { + C.InlayHints.DefaultArguments = Value; + }); if (F.TypeNameLimit) Out.Apply.push_back( [Value(**F.TypeNameLimit)](const Params &, Config &C) { diff --git a/clang-tools-extra/clangd/ConfigFragment.h b/clang-tools-extra/clangd/ConfigFragment.h index fc1b45f5d4c3e9..36f7d04231c414 100644 --- a/clang-tools-extra/clangd/ConfigFragment.h +++ b/clang-tools-extra/clangd/ConfigFragment.h @@ -339,6 +339,9 @@ struct Fragment { std::optional<Located<bool>> Designators; /// Show defined symbol names at the end of a definition block. std::optional<Located<bool>> BlockEnd; + /// Show parameter names and default values of default arguments after all + /// of the explicit arguments. + std::optional<Located<bool>> DefaultArguments; /// Limit the length of type name hints. (0 means no limit) std::optional<Located<uint32_t>> TypeNameLimit; }; diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp index bcdda99eeed67a..32e028981d4244 100644 --- a/clang-tools-extra/clangd/ConfigYAML.cpp +++ b/clang-tools-extra/clangd/ConfigYAML.cpp @@ -14,7 +14,6 @@ #include "llvm/Support/YAMLParser.h" #include <optional> #include <string> -#include <system_error> namespace clang { namespace clangd { @@ -268,6 +267,10 @@ class Parser { if (auto Value = boolValue(N, "BlockEnd")) F.BlockEnd = *Value; }); + Dict.handle("DefaultArguments", [&](Node &N) { + if (auto Value = boolValue(N, "DefaultArguments")) + F.DefaultArguments = *Value; + }); Dict.handle("TypeNameLimit", [&](Node &N) { if (auto Value = uint32Value(N, "TypeNameLimit")) F.TypeNameLimit = *Value; diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index cd4f1931b3ce1d..72fa92a81ce800 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -11,9 +11,11 @@ #include "Config.h" #include "HeuristicResolver.h" #include "ParsedAST.h" +#include "Protocol.h" #include "SourceCode.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -23,15 +25,22 @@ #include "clang/AST/Type.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <iterator> #include <optional> #include <string> @@ -372,6 +381,25 @@ maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) { return Params; } +template <typename R, typename P> +std::string joinAndTruncate(R &&Range, size_t MaxLength, + P &&GetAsStringFunction) { + std::string Out; + llvm::raw_string_ostream OS(Out); + llvm::ListSeparator Sep(", "); + for (auto &&Element : Range) { + OS << Sep; + auto AsString = GetAsStringFunction(Element); + if (Out.size() + AsString.size() >= MaxLength) { + OS << "..."; + break; + } + OS << AsString; + } + OS.flush(); + return Out; +} + struct Callee { // Only one of Decl or Loc is set. // Loc is for calls through function pointers. @@ -422,7 +450,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { Callee.Decl = E->getConstructor(); if (!Callee.Decl) return true; - processCall(Callee, {E->getArgs(), E->getNumArgs()}); + processCall(Callee, E->getParenOrBraceRange().getEnd(), + {E->getArgs(), E->getNumArgs()}); return true; } @@ -495,7 +524,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { dyn_cast_or_null<CXXMethodDecl>(Callee.Decl)) if (IsFunctor || Method->hasCXXExplicitFunctionObjectParameter()) Args = Args.drop_front(1); - processCall(Callee, Args); + processCall(Callee, E->getRParenLoc(), Args); return true; } @@ -709,7 +738,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { private: using NameVec = SmallVector<StringRef, 8>; - void processCall(Callee Callee, llvm::ArrayRef<const Expr *> Args) { + void processCall(Callee Callee, SourceRange LParenOrBraceRange, + llvm::ArrayRef<const Expr *> Args) { assert(Callee.Decl || Callee.Loc); if (!Cfg.InlayHints.Parameters || Args.size() == 0) @@ -721,6 +751,9 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { if (Ctor->isCopyOrMoveConstructor()) return; + SmallVector<std::string> FormattedDefaultArgs; + bool HasNonDefaultArgs = false; + ArrayRef<const ParmVarDecl *> Params, ForwardedParams; // Resolve parameter packs to their forwarded parameter SmallVector<const ParmVarDecl *> ForwardedParamsStorage; @@ -755,12 +788,33 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { bool NameHint = shouldHintName(Args[I], Name); bool ReferenceHint = shouldHintReference(Params[I], ForwardedParams[I]); + bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]); + HasNonDefaultArgs |= !IsDefault; + if (Cfg.InlayHints.DefaultArguments && IsDefault) { + auto SourceText = Lexer::getSourceText( + CharSourceRange::getTokenRange(Params[I]->getDefaultArgRange()), + AST.getSourceManager(), AST.getLangOpts()); + FormattedDefaultArgs.emplace_back(llvm::formatv( + "{0}: {1}", Name, + SourceText.size() > Cfg.InlayHints.TypeNameLimit ? "..." + : SourceText)); + } + if (NameHint || ReferenceHint) { addInlayHint(Args[I]->getSourceRange(), HintSide::Left, InlayHintKind::Parameter, ReferenceHint ? "&" : "", NameHint ? Name : "", ": "); } } + + if (!FormattedDefaultArgs.empty()) { + std::string Hint = + joinAndTruncate(FormattedDefaultArgs, Cfg.InlayHints.TypeNameLimit, + [](const auto &E) { return E; }); + addInlayHint(LParenOrBraceRange, HintSide::Left, + InlayHintKind::DefaultArgument, + HasNonDefaultArgs ? ", " : "", Hint, ""); + } } static bool isSetter(const FunctionDecl *Callee, const NameVec &ParamNames) { @@ -968,6 +1022,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { CHECK_KIND(Type, DeducedTypes); CHECK_KIND(Designator, Designators); CHECK_KIND(BlockEnd, BlockEnd); + CHECK_KIND(DefaultArgument, DefaultArguments); #undef CHECK_KIND } diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index c08f80442eaa06..295ccd26a40454 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -1477,6 +1477,7 @@ llvm::json::Value toJSON(const InlayHintKind &Kind) { return 2; case InlayHintKind::Designator: case InlayHintKind::BlockEnd: + case InlayHintKind::DefaultArgument: // This is an extension, don't serialize. return nullptr; } @@ -1517,6 +1518,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) { return "designator"; case InlayHintKind::BlockEnd: return "block-end"; + case InlayHintKind::DefaultArgument: + return "default-argument"; } llvm_unreachable("Unknown clang.clangd.InlayHintKind"); }; diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index a0f8b04bc4ffdb..52ca9f9afcfbf0 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -1681,6 +1681,15 @@ enum class InlayHintKind { /// This is a clangd extension. BlockEnd = 4, + /// An inlay hint that is for a default argument. + /// + /// An example of a parameter hint for a default argument: + /// void foo(bool A = true); + /// foo(^); + /// Adds an inlay hint "A = true". + /// This is a clangd extension. + DefaultArgument = 6, + /// Other ideas for hints that are not currently implemented: /// /// * Chaining hints, showing the types of intermediate expressions diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index a5a349e93037ad..a4c1ed388b7331 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -15,9 +15,12 @@ #include "support/Context.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/raw_ostream.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include <optional> #include <string> +#include <utility> #include <vector> namespace clang { @@ -81,6 +84,7 @@ Config noHintsConfig() { C.InlayHints.DeducedTypes = false; C.InlayHints.Designators = false; C.InlayHints.BlockEnd = false; + C.InlayHints.DefaultArguments = false; return C; } @@ -1465,6 +1469,31 @@ TEST(TypeHints, DefaultTemplateArgs) { ExpectedHint{": A<float>", "binding"}); } +TEST(DefaultArguments, Smoke) { + Config Cfg; + Cfg.InlayHints.Parameters = + true; // To test interplay of parameters and default parameters + Cfg.InlayHints.DeducedTypes = false; + Cfg.InlayHints.Designators = false; + Cfg.InlayHints.BlockEnd = false; + + Cfg.InlayHints.DefaultArguments = true; + WithContextValue WithCfg(Config::Key, std::move(Cfg)); + + const auto *Code = R"cpp( + int foo(int A = 4) { return A; } + int bar(int A, int B = 1, bool C = foo($default1[[)]]) { return A; } + int A = bar($explicit[[2]]$default2[[)]]; + )cpp"; + + assertHints(InlayHintKind::DefaultArgument, Code, + ExpectedHint{"A: 4", "default1", Left}, + ExpectedHint{", B: 1, C: foo()", "default2", Left}); + + assertHints(InlayHintKind::Parameter, Code, + ExpectedHint{"A: ", "explicit", Left}); +} + TEST(TypeHints, Deduplication) { assertTypeHints(R"cpp( template <typename T> >From 99c78ced163653c9304ad16a410916fffd007f0c Mon Sep 17 00:00:00 2001 From: Tor Shepherd <tor.aksel.sheph...@gmail.com> Date: Mon, 30 Sep 2024 13:47:59 -0400 Subject: [PATCH 2/7] Fix hints for unnamed --- clang-tools-extra/clangd/InlayHints.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 72fa92a81ce800..e7141ad0764b30 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -738,7 +738,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { private: using NameVec = SmallVector<StringRef, 8>; - void processCall(Callee Callee, SourceRange LParenOrBraceRange, + void processCall(Callee Callee, SourceRange RParenOrBraceRange, llvm::ArrayRef<const Expr *> Args) { assert(Callee.Decl || Callee.Loc); @@ -795,7 +795,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { CharSourceRange::getTokenRange(Params[I]->getDefaultArgRange()), AST.getSourceManager(), AST.getLangOpts()); FormattedDefaultArgs.emplace_back(llvm::formatv( - "{0}: {1}", Name, + "{0}: {1}", Name.empty() ? "/*unused*/" : Name, SourceText.size() > Cfg.InlayHints.TypeNameLimit ? "..." : SourceText)); } @@ -811,7 +811,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { std::string Hint = joinAndTruncate(FormattedDefaultArgs, Cfg.InlayHints.TypeNameLimit, [](const auto &E) { return E; }); - addInlayHint(LParenOrBraceRange, HintSide::Left, + addInlayHint(RParenOrBraceRange, HintSide::Left, InlayHintKind::DefaultArgument, HasNonDefaultArgs ? ", " : "", Hint, ""); } >From 4a33c0fb3bb8116647304b8c2c84ec6c5a6b378c Mon Sep 17 00:00:00 2001 From: Tor Shepherd <tor.aksel.sheph...@gmail.com> Date: Mon, 30 Sep 2024 14:18:09 -0400 Subject: [PATCH 3/7] fixes --- clang-tools-extra/clangd/InlayHints.cpp | 21 ++++++++++++------- .../clangd/unittests/InlayHintTests.cpp | 5 ++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index e7141ad0764b30..66fef43e6728e8 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -785,19 +785,24 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { } StringRef Name = ParameterNames[I]; - bool NameHint = shouldHintName(Args[I], Name); - bool ReferenceHint = shouldHintReference(Params[I], ForwardedParams[I]); + const bool NameHint = shouldHintName(Args[I], Name); + const bool ReferenceHint = + shouldHintReference(Params[I], ForwardedParams[I]); - bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]); + const bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]); HasNonDefaultArgs |= !IsDefault; if (Cfg.InlayHints.DefaultArguments && IsDefault) { - auto SourceText = Lexer::getSourceText( + const auto SourceText = Lexer::getSourceText( CharSourceRange::getTokenRange(Params[I]->getDefaultArgRange()), AST.getSourceManager(), AST.getLangOpts()); - FormattedDefaultArgs.emplace_back(llvm::formatv( - "{0}: {1}", Name.empty() ? "/*unused*/" : Name, - SourceText.size() > Cfg.InlayHints.TypeNameLimit ? "..." - : SourceText)); + const auto Abbrev = SourceText.size() > Cfg.InlayHints.TypeNameLimit + ? "..." + : SourceText; + if (NameHint) + FormattedDefaultArgs.emplace_back( + llvm::formatv("{0}: {1}", Name, Abbrev)); + else + FormattedDefaultArgs.emplace_back(llvm::formatv("{0}", Abbrev)); } if (NameHint || ReferenceHint) { diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index a4c1ed388b7331..cfdabf78d25348 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -1484,11 +1484,14 @@ TEST(DefaultArguments, Smoke) { int foo(int A = 4) { return A; } int bar(int A, int B = 1, bool C = foo($default1[[)]]) { return A; } int A = bar($explicit[[2]]$default2[[)]]; + + void baz(int = 5) { if (false) baz($unnamed[[)]]; }; )cpp"; assertHints(InlayHintKind::DefaultArgument, Code, ExpectedHint{"A: 4", "default1", Left}, - ExpectedHint{", B: 1, C: foo()", "default2", Left}); + ExpectedHint{", B: 1, C: foo()", "default2", Left}, + ExpectedHint{"5", "unnamed", Left}); assertHints(InlayHintKind::Parameter, Code, ExpectedHint{"A: ", "explicit", Left}); >From 3d651d4b2cf5929d8d07fb04e257143a61e339ba Mon Sep 17 00:00:00 2001 From: Tor Shepherd <tor.aksel.sheph...@gmail.com> Date: Mon, 30 Sep 2024 14:34:50 -0400 Subject: [PATCH 4/7] if --- clang-tools-extra/clangd/InlayHints.cpp | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 66fef43e6728e8..3a63f65187bd23 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -791,21 +791,21 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { const bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]); HasNonDefaultArgs |= !IsDefault; - if (Cfg.InlayHints.DefaultArguments && IsDefault) { - const auto SourceText = Lexer::getSourceText( - CharSourceRange::getTokenRange(Params[I]->getDefaultArgRange()), - AST.getSourceManager(), AST.getLangOpts()); - const auto Abbrev = SourceText.size() > Cfg.InlayHints.TypeNameLimit - ? "..." - : SourceText; - if (NameHint) - FormattedDefaultArgs.emplace_back( - llvm::formatv("{0}: {1}", Name, Abbrev)); - else - FormattedDefaultArgs.emplace_back(llvm::formatv("{0}", Abbrev)); - } - - if (NameHint || ReferenceHint) { + if (IsDefault) { + if (Cfg.InlayHints.DefaultArguments) { + const auto SourceText = Lexer::getSourceText( + CharSourceRange::getTokenRange(Params[I]->getDefaultArgRange()), + AST.getSourceManager(), AST.getLangOpts()); + const auto Abbrev = SourceText.size() > Cfg.InlayHints.TypeNameLimit + ? "..." + : SourceText; + if (NameHint) + FormattedDefaultArgs.emplace_back( + llvm::formatv("{0}: {1}", Name, Abbrev)); + else + FormattedDefaultArgs.emplace_back(llvm::formatv("{0}", Abbrev)); + } + } else if (NameHint || ReferenceHint) { addInlayHint(Args[I]->getSourceRange(), HintSide::Left, InlayHintKind::Parameter, ReferenceHint ? "&" : "", NameHint ? Name : "", ": "); >From 41db595113e1976661cec005271d270ef3df4a5a Mon Sep 17 00:00:00 2001 From: Tor Shepherd <tor.aksel.sheph...@gmail.com> Date: Mon, 14 Oct 2024 12:55:52 -0400 Subject: [PATCH 5/7] Comments and partial refactor --- clang-tools-extra/clangd/InlayHints.cpp | 34 +++++++-------- clang-tools-extra/clangd/Protocol.h | 2 +- .../clangd/unittests/InlayHintTests.cpp | 41 +++++++++++++++++++ 3 files changed, 60 insertions(+), 17 deletions(-) diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 3a63f65187bd23..c4053fced81d6f 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -381,20 +381,18 @@ maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) { return Params; } -template <typename R, typename P> -std::string joinAndTruncate(R &&Range, size_t MaxLength, - P &&GetAsStringFunction) { +template <typename R> +std::string joinAndTruncate(const R &Range, size_t MaxLength) { std::string Out; llvm::raw_string_ostream OS(Out); llvm::ListSeparator Sep(", "); for (auto &&Element : Range) { OS << Sep; - auto AsString = GetAsStringFunction(Element); - if (Out.size() + AsString.size() >= MaxLength) { + if (Out.size() + Element.size() >= MaxLength) { OS << "..."; break; } - OS << AsString; + OS << Element; } OS.flush(); return Out; @@ -738,11 +736,12 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { private: using NameVec = SmallVector<StringRef, 8>; - void processCall(Callee Callee, SourceRange RParenOrBraceRange, + void processCall(Callee Callee, SourceLocation RParenOrBraceLoc, llvm::ArrayRef<const Expr *> Args) { assert(Callee.Decl || Callee.Loc); - if (!Cfg.InlayHints.Parameters || Args.size() == 0) + if ((!Cfg.InlayHints.Parameters && !Cfg.InlayHints.DefaultArguments) || + Args.size() == 0) return; // The parameter name of a move or copy constructor is not very interesting. @@ -785,9 +784,11 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { } StringRef Name = ParameterNames[I]; - const bool NameHint = shouldHintName(Args[I], Name); + const bool NameHint = + shouldHintName(Args[I], Name) && Cfg.InlayHints.Parameters; const bool ReferenceHint = - shouldHintReference(Params[I], ForwardedParams[I]); + shouldHintReference(Params[I], ForwardedParams[I]) && + Cfg.InlayHints.Parameters; const bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]); HasNonDefaultArgs |= !IsDefault; @@ -796,9 +797,11 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { const auto SourceText = Lexer::getSourceText( CharSourceRange::getTokenRange(Params[I]->getDefaultArgRange()), AST.getSourceManager(), AST.getLangOpts()); - const auto Abbrev = SourceText.size() > Cfg.InlayHints.TypeNameLimit - ? "..." - : SourceText; + const auto Abbrev = + (SourceText.size() > Cfg.InlayHints.TypeNameLimit || + SourceText.contains("\n")) + ? "..." + : SourceText; if (NameHint) FormattedDefaultArgs.emplace_back( llvm::formatv("{0}: {1}", Name, Abbrev)); @@ -814,9 +817,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { if (!FormattedDefaultArgs.empty()) { std::string Hint = - joinAndTruncate(FormattedDefaultArgs, Cfg.InlayHints.TypeNameLimit, - [](const auto &E) { return E; }); - addInlayHint(RParenOrBraceRange, HintSide::Left, + joinAndTruncate(FormattedDefaultArgs, Cfg.InlayHints.TypeNameLimit); + addInlayHint(SourceRange{RParenOrBraceLoc}, HintSide::Left, InlayHintKind::DefaultArgument, HasNonDefaultArgs ? ", " : "", Hint, ""); } diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index 52ca9f9afcfbf0..5b28095758198d 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -1686,7 +1686,7 @@ enum class InlayHintKind { /// An example of a parameter hint for a default argument: /// void foo(bool A = true); /// foo(^); - /// Adds an inlay hint "A = true". + /// Adds an inlay hint "A: true". /// This is a clangd extension. DefaultArgument = 6, diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index cfdabf78d25348..ebd002ba917fb5 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -1497,6 +1497,47 @@ TEST(DefaultArguments, Smoke) { ExpectedHint{"A: ", "explicit", Left}); } +TEST(DefaultArguments, WithoutParameterNames) { + Config Cfg; + Cfg.InlayHints.Parameters = false; // To test just default args this time + Cfg.InlayHints.DeducedTypes = false; + Cfg.InlayHints.Designators = false; + Cfg.InlayHints.BlockEnd = false; + + Cfg.InlayHints.DefaultArguments = true; + WithContextValue WithCfg(Config::Key, std::move(Cfg)); + + const auto *Code = R"cpp( + struct Baz { + Baz(float a = 3 // + + 2); + }; + struct Foo { + Foo(int, Baz baz = // + Baz{$unnamed[[}]] + + // + ) {} + }; + + int main() { + Foo foo1(1$paren[[)]]; + Foo foo2{2$brace1[[}]]; + Foo foo3 = {3$brace2[[}]]; + auto foo4 = Foo{4$brace3[[}]]; + } + )cpp"; + + assertHints(InlayHintKind::DefaultArgument, Code, + ExpectedHint{"...", "unnamed", Left}, + ExpectedHint{", Baz{}", "paren", Left}, + ExpectedHint{", Baz{}", "brace1", Left}, + ExpectedHint{", Baz{}", "brace2", Left}, + ExpectedHint{", Baz{}", "brace3", Left}); + + assertHints(InlayHintKind::Parameter, Code); +} + TEST(TypeHints, Deduplication) { assertTypeHints(R"cpp( template <typename T> >From f7dd236f9df3c739afb3e597b2e5a4bd80e3254f Mon Sep 17 00:00:00 2001 From: Tor Shepherd <tor.aksel.sheph...@gmail.com> Date: Sat, 19 Oct 2024 12:09:05 -0400 Subject: [PATCH 6/7] comment --- clang-tools-extra/clangd/unittests/InlayHintTests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index ebd002ba917fb5..73dd273d6c39d4 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -1514,7 +1514,7 @@ TEST(DefaultArguments, WithoutParameterNames) { }; struct Foo { Foo(int, Baz baz = // - Baz{$unnamed[[}]] + Baz{$abbreviated[[}]] // ) {} @@ -1529,7 +1529,7 @@ TEST(DefaultArguments, WithoutParameterNames) { )cpp"; assertHints(InlayHintKind::DefaultArgument, Code, - ExpectedHint{"...", "unnamed", Left}, + ExpectedHint{"...", "abbreviated", Left}, ExpectedHint{", Baz{}", "paren", Left}, ExpectedHint{", Baz{}", "brace1", Left}, ExpectedHint{", Baz{}", "brace2", Left}, >From 808f9f46945900196b8152b8e2d18ac9a613e2ef Mon Sep 17 00:00:00 2001 From: Tor Shepherd <tor.aksel.sheph...@gmail.com> Date: Sat, 19 Oct 2024 12:12:30 -0400 Subject: [PATCH 7/7] Relnotes --- clang-tools-extra/docs/ReleaseNotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index e8148e06b6af28..a9b1ab367f538a 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -56,6 +56,8 @@ Improvements to clangd Inlay hints ^^^^^^^^^^^ +- Added `DefaultArguments` Inlay Hints option. + Diagnostics ^^^^^^^^^^^ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits