[clang] [clang-tools-extra] [clangd] Show struct fields and enum members in hovers (PR #89557)
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 21 17:57:07 PDT 2024
https://github.com/HighCommander4 created https://github.com/llvm/llvm-project/pull/89557
Fixes https://github.com/clangd/clangd/issues/959
>From d98c95bf213f0c6e81a46a9e37d376b855bb4867 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul976 at hotmail.com>
Date: Sun, 21 Apr 2024 20:30:16 -0400
Subject: [PATCH] [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";
More information about the cfe-commits
mailing list