https://github.com/HighCommander4 created 
https://github.com/llvm/llvm-project/pull/89570

Fixes https://github.com/clangd/clangd/issues/2020

>From d98c95bf213f0c6e81a46a9e37d376b855bb4867 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul...@hotmail.com>
Date: Sun, 21 Apr 2024 20:30:16 -0400
Subject: [PATCH 1/2] [clangd] Show struct fields and enum members in hovers

Fixes https://github.com/clangd/clangd/issues/959
---
 clang-tools-extra/clangd/Hover.cpp            |  2 ++
 .../clangd/unittests/HoverTests.cpp           | 17 ++++++++++++----
 clang/include/clang/AST/PrettyPrinter.h       | 10 +++++++++-
 clang/lib/AST/DeclPrinter.cpp                 | 20 ++++++++++++++++---
 4 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/clang-tools-extra/clangd/Hover.cpp 
b/clang-tools-extra/clangd/Hover.cpp
index 06b949bc4a2b55..d7c433876b08bc 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -69,6 +69,8 @@ namespace {
 PrintingPolicy getPrintingPolicy(PrintingPolicy Base) {
   Base.AnonymousTagLocations = false;
   Base.TerseOutput = true;
+  // Show struct fields and enum members.
+  Base.PrintTagTypeContents = true;
   Base.PolishForDeclaration = true;
   Base.ConstantsAsWritten = true;
   Base.SuppressTemplateArgsInCXXConstructors = true;
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp 
b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 35db757b9c15b5..8c19f5fb3b0ad0 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1645,7 +1645,16 @@ TEST(Hover, All) {
       {
           R"cpp(// Struct
             namespace ns1 {
-              struct MyClass {};
+              struct MyClass {
+                // Public fields shown in hover
+                int field1;
+                int field2;
+
+                // Methods and private fields not shown
+                void method();
+              private:
+                bool private_field;
+              };
             } // namespace ns1
             int main() {
               ns1::[[My^Class]]* Params;
@@ -1655,7 +1664,7 @@ TEST(Hover, All) {
             HI.Name = "MyClass";
             HI.Kind = index::SymbolKind::Struct;
             HI.NamespaceScope = "ns1::";
-            HI.Definition = "struct MyClass {}";
+            HI.Definition = "struct MyClass {\n  int field1;\n  int 
field2;\n}";
           }},
       {
           R"cpp(// Class
@@ -1685,7 +1694,7 @@ TEST(Hover, All) {
             HI.Name = "MyUnion";
             HI.Kind = index::SymbolKind::Union;
             HI.NamespaceScope = "ns1::";
-            HI.Definition = "union MyUnion {}";
+            HI.Definition = "union MyUnion {\n  int x;\n  int y;\n}";
           }},
       {
           R"cpp(// Function definition via pointer
@@ -2030,7 +2039,7 @@ TEST(Hover, All) {
             HI.Name = "Hello";
             HI.Kind = index::SymbolKind::Enum;
             HI.NamespaceScope = "";
-            HI.Definition = "enum Hello {}";
+            HI.Definition = "enum Hello { ONE, TWO, THREE }";
             HI.Documentation = "Enum declaration";
           }},
       {
diff --git a/clang/include/clang/AST/PrettyPrinter.h 
b/clang/include/clang/AST/PrettyPrinter.h
index da276e26049b00..6b8f1ae9143df3 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -70,7 +70,7 @@ struct PrintingPolicy {
         Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11),
         UseVoidForZeroParams(!LO.CPlusPlus),
         SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false),
-        PolishForDeclaration(false), Half(LO.Half),
+        PrintTagTypeContents(false), PolishForDeclaration(false), 
Half(LO.Half),
         MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
         MSVCFormatting(false), ConstantsAsWritten(false),
         SuppressImplicitBase(false), FullyQualifiedName(false),
@@ -252,6 +252,14 @@ struct PrintingPolicy {
   LLVM_PREFERRED_TYPE(bool)
   unsigned TerseOutput : 1;
 
+  /// Print the contents of tag (i.e. record and enum) types, even with
+  /// TerseOutput=true.
+  ///
+  /// For record types (structs/classes/unions), this only prints public
+  /// data members. For enum types, this prints enumerators.
+  /// Has no effect if TerseOutput=false (which prints all members).
+  unsigned PrintTagTypeContents : 1;
+
   /// When true, do certain refinement needed for producing proper declaration
   /// tag; such as, do not print attributes attached to the declaration.
   ///
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 43d221968ea3fb..3fe02fff687fe1 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -21,6 +21,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/Basic/Module.h"
+#include "clang/Basic/Specifiers.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
 
@@ -464,8 +465,10 @@ void 
DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl,
 //----------------------------------------------------------------------------
 
 void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
-  if (Policy.TerseOutput)
-    return;
+  if (Policy.TerseOutput) {
+    if (!Policy.PrintTagTypeContents || !isa<TagDecl>(DC))
+      return;
+  }
 
   if (Indent)
     Indentation += Policy.Indentation;
@@ -474,6 +477,17 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool 
Indent) {
   for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = 
DC->decls_end();
        D != DEnd; ++D) {
 
+    // Print enum members and public struct fields when
+    // PrintTagTypeContents=true. Only applicable when TerseOutput=true since
+    // otherwise all members are printed.
+    if (Policy.TerseOutput) {
+      assert(Policy.PrintTagTypeContents);
+      if (!(isa<EnumConstantDecl>(*D) ||
+            (isa<FieldDecl>(*D) &&
+             dyn_cast<FieldDecl>(*D)->getAccess() == AS_public)))
+        continue;
+    }
+
     // Don't print ObjCIvarDecls, as they are printed when visiting the
     // containing ObjCInterfaceDecl.
     if (isa<ObjCIvarDecl>(*D))
@@ -1182,7 +1196,7 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
 
     // Print the class definition
     // FIXME: Doesn't print access specifiers, e.g., "public:"
-    if (Policy.TerseOutput) {
+    if (Policy.TerseOutput && !Policy.PrintTagTypeContents) {
       Out << " {}";
     } else {
       Out << " {\n";

>From 457545fbf74bb0c5359371f325af1a1fedb02f77 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul...@hotmail.com>
Date: Mon, 22 Apr 2024 02:24:14 -0400
Subject: [PATCH 2/2] [clangd] Show struct members when hovering over a typedef

Fixes https://github.com/clangd/clangd/issues/2020
---
 clang-tools-extra/clangd/Hover.cpp               | 10 ++++++++++
 .../clangd/unittests/HoverTests.cpp              | 16 +++++++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clangd/Hover.cpp 
b/clang-tools-extra/clangd/Hover.cpp
index d7c433876b08bc..598c2a68b7bf16 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -152,6 +152,16 @@ std::string printDefinition(const Decl *D, PrintingPolicy 
PP,
   std::string Definition;
   llvm::raw_string_ostream OS(Definition);
   D->print(OS, PP);
+  
+  // For a typedef to a TagDecl, also print the underlying TagDecl
+  if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
+    if (const auto *TT = dyn_cast<TagType>(
+            TND->getUnderlyingType().getCanonicalType().getTypePtr())) {
+      OS << ";\n";
+      TT->getDecl()->print(OS, PP);
+    }
+  }
+
   OS.flush();
   return Definition;
 }
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp 
b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 8c19f5fb3b0ad0..9657869b1b7641 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1666,6 +1666,20 @@ TEST(Hover, All) {
             HI.NamespaceScope = "ns1::";
             HI.Definition = "struct MyClass {\n  int field1;\n  int 
field2;\n}";
           }},
+          {
+            R"cpp(// Typedef to struct
+              struct Point { int x; int y; };
+              typedef Point TPoint;
+              [[TP^oint]] tp;
+            )cpp",
+            [](HoverInfo &HI) {
+              HI.Name = "TPoint";
+              HI.Kind = index::SymbolKind::TypeAlias;
+              HI.NamespaceScope = "";
+              HI.Type = "struct Point";
+              HI.Definition = "typedef Point TPoint;\nstruct Point {\n  int 
x;\n  int y;\n}";
+            }
+          },
       {
           R"cpp(// Class
             namespace ns1 {
@@ -1889,7 +1903,7 @@ TEST(Hover, All) {
             HI.Name = "Foo";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.NamespaceScope = "";
-            HI.Definition = "typedef struct Bar Foo";
+            HI.Definition = "typedef struct Bar Foo;\nstruct Bar {}";
             HI.Type = "struct Bar";
             HI.Documentation = "Typedef with embedded definition";
           }},

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to