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
  • [PATCH] D131066: [clangd] Add... Nathan James via Phabricator via cfe-commits

Reply via email to