njames93 created this revision. njames93 added reviewers: sammccall, nridge. Herald added subscribers: usaxena95, kadircet, arphaman. Herald added a project: All. njames93 requested review of this revision. Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov. Herald added a project: clang-tools-extra.
Inlay hints can be pretty annoying when using an initializer list to build an array. string HelloW[] = {<0=>"Hello", <1=>"World"}; To silence these I've extended the `Designators` config option to work as an enum that will let users choose to enable or disable arrays while still letting them use the normal designators. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D131066 Files: clang-tools-extra/clangd/Config.h clang-tools-extra/clangd/ConfigCompile.cpp clang-tools-extra/clangd/ConfigFragment.h clang-tools-extra/clangd/ConfigYAML.cpp clang-tools-extra/clangd/InlayHints.cpp clang-tools-extra/clangd/unittests/InlayHintTests.cpp
Index: clang-tools-extra/clangd/unittests/InlayHintTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -76,7 +76,7 @@ Config C; C.InlayHints.Parameters = false; C.InlayHints.DeducedTypes = false; - C.InlayHints.Designators = false; + C.InlayHints.Designators = Config::InlayHints::None; return C; } @@ -114,10 +114,11 @@ } template <typename... ExpectedHints> -void assertDesignatorHints(llvm::StringRef AnnotatedSource, +void assertDesignatorHints(llvm::StringRef AnnotatedSource, bool IncludeArray, ExpectedHints... Expected) { Config Cfg; - Cfg.InlayHints.Designators = true; + Cfg.InlayHints.Designators = + IncludeArray ? Config::InlayHints::All : Config::InlayHints::IgnoreArrays; WithContextValue WithCfg(Config::Key, std::move(Cfg)); assertHints(InlayHintKind::Designator, AnnotatedSource, Expected...); } @@ -1353,14 +1354,17 @@ } TEST(DesignatorHints, Basic) { - assertDesignatorHints(R"cpp( + StringRef Source = R"cpp( struct S { int x, y, z; }; S s {$x[[1]], $y[[2+2]]}; int x[] = {$0[[0]], $1[[1]]}; - )cpp", - ExpectedHint{".x=", "x"}, ExpectedHint{".y=", "y"}, - ExpectedHint{"[0]=", "0"}, ExpectedHint{"[1]=", "1"}); + )cpp"; + assertDesignatorHints(Source, true, ExpectedHint{".x=", "x"}, + ExpectedHint{".y=", "y"}, ExpectedHint{"[0]=", "0"}, + ExpectedHint{"[1]=", "1"}); + assertDesignatorHints(Source, false, ExpectedHint{".x=", "x"}, + ExpectedHint{".y=", "y"}); } TEST(DesignatorHints, Nested) { @@ -1369,8 +1373,9 @@ struct Outer { Inner a, b; }; Outer o{ $a[[{ $x[[1]], $y[[2]] }]], $bx[[3]] }; )cpp", - ExpectedHint{".a=", "a"}, ExpectedHint{".x=", "x"}, - ExpectedHint{".y=", "y"}, ExpectedHint{".b.x=", "bx"}); + true, ExpectedHint{".a=", "a"}, + ExpectedHint{".x=", "x"}, ExpectedHint{".y=", "y"}, + ExpectedHint{".b.x=", "bx"}); } TEST(DesignatorHints, AnonymousRecord) { @@ -1386,7 +1391,7 @@ }; S s{$xy[[42]]}; )cpp", - ExpectedHint{".x.y=", "xy"}); + true, ExpectedHint{".x.y=", "xy"}); } TEST(DesignatorHints, Suppression) { @@ -1394,7 +1399,7 @@ struct Point { int a, b, c, d, e, f, g, h; }; Point p{/*a=*/1, .c=2, /* .d = */3, $e[[4]]}; )cpp", - ExpectedHint{".e=", "e"}); + true, ExpectedHint{".e=", "e"}); } TEST(DesignatorHints, StdArray) { @@ -1404,17 +1409,20 @@ template <typename T, int N> struct Array { T __elements[N]; }; Array<int, 2> x = {$0[[0]], $1[[1]]}; )cpp", - ExpectedHint{"[0]=", "0"}, ExpectedHint{"[1]=", "1"}); + true, ExpectedHint{"[0]=", "0"}, + ExpectedHint{"[1]=", "1"}); } TEST(DesignatorHints, OnlyAggregateInit) { - assertDesignatorHints(R"cpp( + assertDesignatorHints( + R"cpp( struct Copyable { int x; } c; Copyable d{c}; struct Constructible { Constructible(int x); }; Constructible x{42}; - )cpp" /*no designator hints expected (but param hints!)*/); + )cpp", + true /*no designator hints expected (but param hints!)*/); } TEST(InlayHints, RestrictRange) { Index: clang-tools-extra/clangd/InlayHints.cpp =================================================================== --- clang-tools-extra/clangd/InlayHints.cpp +++ clang-tools-extra/clangd/InlayHints.cpp @@ -66,12 +66,15 @@ } // Print the designator to Out. // Returns false if we could not produce a designator for this element. - bool append(std::string &Out, bool ForSubobject) { + bool append(std::string &Out, bool ForSubobject, bool CollectArrays) { if (IsArray) { - Out.push_back('['); - Out.append(std::to_string(Index)); - Out.push_back(']'); - return true; + if (CollectArrays) { + Out.push_back('['); + Out.append(std::to_string(Index)); + Out.push_back(']'); + return true; + } + return false; } if (BasesIt != BasesEnd) return false; // Bases can't be designated. Should we make one up? @@ -126,7 +129,7 @@ void collectDesignators(const InitListExpr *Sem, llvm::DenseMap<SourceLocation, std::string> &Out, const llvm::DenseSet<SourceLocation> &NestedBraces, - std::string &Prefix) { + std::string &Prefix, bool CollectArrays) { if (!Sem || Sem->isTransparent()) return; assert(Sem->isSemanticForm()); @@ -149,14 +152,15 @@ NestedBraces.contains(BraceElidedSubobject->getLBraceLoc())) BraceElidedSubobject = nullptr; // there were braces! - if (!Fields.append(Prefix, BraceElidedSubobject != nullptr)) + if (!Fields.append(Prefix, BraceElidedSubobject != nullptr, CollectArrays)) continue; // no designator available for this subobject if (BraceElidedSubobject) { // If the braces were elided, this aggregate subobject is initialized // inline in the same syntactic list. // Descend into the semantic list describing the subobject. // (NestedBraces are still correct, they're from the same syntactic list). - collectDesignators(BraceElidedSubobject, Out, NestedBraces, Prefix); + collectDesignators(BraceElidedSubobject, Out, NestedBraces, Prefix, + CollectArrays); continue; } Out.try_emplace(Init->getBeginLoc(), Prefix); @@ -166,7 +170,7 @@ // Get designators describing the elements of a (syntactic) init list. // This does not produce designators for any explicitly-written nested lists. llvm::DenseMap<SourceLocation, std::string> -getDesignators(const InitListExpr *Syn) { +getDesignators(const InitListExpr *Syn, bool CollectArrays) { assert(Syn->isSyntacticForm()); // collectDesignators needs to know which InitListExprs in the semantic tree @@ -182,7 +186,7 @@ llvm::DenseMap<SourceLocation, std::string> Designators; std::string EmptyPrefix; collectDesignators(Syn->isSemanticForm() ? Syn : Syn->getSemanticForm(), - Designators, NestedBraces, EmptyPrefix); + Designators, NestedBraces, EmptyPrefix, CollectArrays); return Designators; } @@ -351,12 +355,12 @@ // form of the init-list has nested init-lists for these. // getDesignators will look at the semantic form to determine the labels. assert(Syn->isSyntacticForm() && "RAV should not visit implicit code!"); - if (!Cfg.InlayHints.Designators) + if (Cfg.InlayHints.Designators == Config::InlayHints::None) return true; if (Syn->isIdiomaticZeroInitializer(AST.getLangOpts())) return true; - llvm::DenseMap<SourceLocation, std::string> Designators = - getDesignators(Syn); + llvm::DenseMap<SourceLocation, std::string> Designators = getDesignators( + Syn, Cfg.InlayHints.Designators == Config::InlayHints::All); for (const Expr *Init : Syn->inits()) { if (llvm::isa<DesignatedInitExpr>(Init)) continue; Index: clang-tools-extra/clangd/ConfigYAML.cpp =================================================================== --- clang-tools-extra/clangd/ConfigYAML.cpp +++ clang-tools-extra/clangd/ConfigYAML.cpp @@ -245,7 +245,7 @@ F.DeducedTypes = *Value; }); Dict.handle("Designators", [&](Node &N) { - if (auto Value = boolValue(N, "Designators")) + if (auto Value = scalarValue(N, "Designators")) F.Designators = *Value; }); Dict.parse(N); Index: clang-tools-extra/clangd/ConfigFragment.h =================================================================== --- clang-tools-extra/clangd/ConfigFragment.h +++ clang-tools-extra/clangd/ConfigFragment.h @@ -304,7 +304,7 @@ /// Show deduced types for `auto`. llvm::Optional<Located<bool>> DeducedTypes; /// Show designators in aggregate initialization. - llvm::Optional<Located<bool>> Designators; + llvm::Optional<Located<std::string>> Designators; }; InlayHintsBlock InlayHints; }; Index: clang-tools-extra/clangd/ConfigCompile.cpp =================================================================== --- clang-tools-extra/clangd/ConfigCompile.cpp +++ clang-tools-extra/clangd/ConfigCompile.cpp @@ -44,6 +44,7 @@ #include "llvm/Support/Regex.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLParser.h" #include <algorithm> #include <memory> #include <string> @@ -582,10 +583,22 @@ Out.Apply.push_back([Value(**F.DeducedTypes)](const Params &, Config &C) { C.InlayHints.DeducedTypes = Value; }); - if (F.Designators) - Out.Apply.push_back([Value(**F.Designators)](const Params &, Config &C) { - C.InlayHints.Designators = Value; - }); + if (F.Designators) { + Optional<Config::InlayHints::DesignatorsStlye> Style; + if (auto Bool = llvm::yaml::parseBool(**F.Designators)) { + Style = *Bool ? Config::InlayHints::All : Config::InlayHints::None; + } else + Style = compileEnum<Config::InlayHints::DesignatorsStlye>( + "Designators", *F.Designators) + .map("All", Config::InlayHints::All) + .map("IgnoreArrays", Config::InlayHints::IgnoreArrays) + .map("None", Config::InlayHints::None) + .value(); + if (Style) + Out.Apply.push_back([Style(*Style)](const Params &, Config &C) { + C.InlayHints.Designators = Style; + }); + } } constexpr static llvm::SourceMgr::DiagKind Error = llvm::SourceMgr::DK_Error; Index: clang-tools-extra/clangd/Config.h =================================================================== --- clang-tools-extra/clangd/Config.h +++ clang-tools-extra/clangd/Config.h @@ -131,14 +131,16 @@ bool ShowAKA = true; } Hover; - struct { + struct InlayHints { + enum DesignatorsStlye { None = 0, All, IgnoreArrays }; + /// If false, inlay hints are completely disabled. bool Enabled = true; // Whether specific categories of hints are enabled. bool Parameters = true; bool DeducedTypes = true; - bool Designators = true; + DesignatorsStlye Designators = All; } InlayHints; };
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits