diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h --- a/clang-tools-extra/clangd/Config.h +++ b/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; }; diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp --- a/clang-tools-extra/clangd/ConfigCompile.cpp +++ b/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 #include #include @@ -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 Style; + if (auto Bool = llvm::yaml::parseBool(**F.Designators)) { + Style = *Bool ? Config::InlayHints::All : Config::InlayHints::None; + } else + Style = compileEnum( + "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; diff --git a/clang-tools-extra/clangd/ConfigFragment.h b/clang-tools-extra/clangd/ConfigFragment.h --- a/clang-tools-extra/clangd/ConfigFragment.h +++ b/clang-tools-extra/clangd/ConfigFragment.h @@ -304,7 +304,7 @@ /// Show deduced types for `auto`. llvm::Optional> DeducedTypes; /// Show designators in aggregate initialization. - llvm::Optional> Designators; + llvm::Optional> Designators; }; InlayHintsBlock InlayHints; }; diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp --- a/clang-tools-extra/clangd/ConfigYAML.cpp +++ b/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); diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/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 &Out, const llvm::DenseSet &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 -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 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 Designators = - getDesignators(Syn); + llvm::DenseMap Designators = getDesignators( + Syn, Cfg.InlayHints.Designators == Config::InlayHints::All); for (const Expr *Init : Syn->inits()) { if (llvm::isa(Init)) continue; diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/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 -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 struct Array { T __elements[N]; }; Array 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) {