This revision was automatically updated to reflect the committed changes. Closed by commit rGc1a00b89add8: [clangd] show layout info when hovering on a class/field definition. (authored by sammccall).
Changed prior to commit: https://reviews.llvm.org/D77355?vs=254786&id=255964#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D77355/new/ https://reviews.llvm.org/D77355 Files: clang-tools-extra/clangd/Hover.cpp clang-tools-extra/clangd/Hover.h clang-tools-extra/clangd/unittests/HoverTests.cpp
Index: clang-tools-extra/clangd/unittests/HoverTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/HoverTests.cpp +++ clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -66,7 +66,7 @@ {R"cpp( namespace ns1 { namespace ns2 { struct Foo { - int [[b^ar]]; + char [[b^ar]]; }; }} )cpp", @@ -75,8 +75,10 @@ HI.LocalScope = "Foo::"; HI.Name = "bar"; HI.Kind = index::SymbolKind::Field; - HI.Definition = "int bar"; - HI.Type = "int"; + HI.Definition = "char bar"; + HI.Type = "char"; + HI.Offset = 0; + HI.Size = 1; }}, // Local to class method. {R"cpp( @@ -100,7 +102,7 @@ {R"cpp( namespace ns1 { namespace { struct { - int [[b^ar]]; + char [[b^ar]]; } T; }} )cpp", @@ -109,8 +111,21 @@ HI.LocalScope = "(anonymous struct)::"; HI.Name = "bar"; HI.Kind = index::SymbolKind::Field; - HI.Definition = "int bar"; - HI.Type = "int"; + HI.Definition = "char bar"; + HI.Type = "char"; + HI.Offset = 0; + HI.Size = 1; + }}, + // Struct definition shows size. + {R"cpp( + struct [[^X]]{}; + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "X"; + HI.Kind = index::SymbolKind::Struct; + HI.Definition = "struct X {}"; + HI.Size = 1; }}, // Variable with template type {R"cpp( @@ -698,6 +713,8 @@ EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters); EXPECT_EQ(H->SymRange, Expected.SymRange); EXPECT_EQ(H->Value, Expected.Value); + EXPECT_EQ(H->Size, Expected.Size); + EXPECT_EQ(H->Offset, Expected.Offset); } } @@ -1862,6 +1879,7 @@ { [](HoverInfo &HI) { HI.Kind = index::SymbolKind::Class; + HI.Size = 10; HI.TemplateParameters = { {std::string("typename"), std::string("T"), llvm::None}, {std::string("typename"), std::string("C"), @@ -1875,6 +1893,7 @@ }, R"(class foo +Size: 10 bytes documentation template <typename T, typename C = bool> class Foo {})", @@ -1911,19 +1930,23 @@ }, { [](HoverInfo &HI) { - HI.Kind = index::SymbolKind::Variable; - HI.LocalScope = "test::bar::"; + HI.Kind = index::SymbolKind::Field; + HI.LocalScope = "test::Bar::"; HI.Value = "value"; HI.Name = "foo"; HI.Type = "type"; HI.Definition = "def"; + HI.Size = 4; + HI.Offset = 12; }, - R"(variable foo + R"(field foo Type: type Value = value +Offset: 12 bytes +Size: 4 bytes -// In test::bar +// In test::Bar def)", }, }; Index: clang-tools-extra/clangd/Hover.h =================================================================== --- clang-tools-extra/clangd/Hover.h +++ clang-tools-extra/clangd/Hover.h @@ -70,6 +70,10 @@ llvm::Optional<std::vector<Param>> TemplateParameters; /// Contains the evaluated value of the symbol if available. llvm::Optional<std::string> Value; + /// Contains the byte-size of fields and types where it's interesting. + llvm::Optional<uint64_t> Size; + /// Contains the offset of fields within the enclosing class. + llvm::Optional<uint64_t> Offset; /// Produce a user-readable information. markup::Document present() const; Index: clang-tools-extra/clangd/Hover.cpp =================================================================== --- clang-tools-extra/clangd/Hover.cpp +++ clang-tools-extra/clangd/Hover.cpp @@ -651,6 +651,28 @@ return punctuationIndicatesLineBreak(Line) || isHardLineBreakIndicator(Rest); } +void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) { + const auto &Ctx = ND.getASTContext(); + + if (auto *RD = llvm::dyn_cast<RecordDecl>(&ND)) { + if (auto Size = Ctx.getTypeSizeInCharsIfKnown(RD->getTypeForDecl())) + HI.Size = Size->getQuantity(); + return; + } + + if (const auto *FD = llvm::dyn_cast<FieldDecl>(&ND)) { + const auto *Record = FD->getParent()->getDefinition(); + if (Record && !Record->isDependentType()) { + uint64_t OffsetBits = Ctx.getFieldOffset(FD); + if (auto Size = Ctx.getTypeSizeInCharsIfKnown(FD->getType())) { + HI.Size = Size->getQuantity(); + HI.Offset = OffsetBits / 8; + } + } + return; + } +} + } // namespace llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos, @@ -707,6 +729,9 @@ auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias); if (!Decls.empty()) { HI = getHoverContents(Decls.front(), Index); + // Layout info only shown when hovering on the field/class itself. + if (Decls.front() == N->ASTNode.get<Decl>()) + addLayoutInfo(*Decls.front(), *HI); // Look for a close enclosing expression to show the value of. if (!HI->Value) HI->Value = printExprValue(N, AST.getASTContext()); @@ -782,6 +807,13 @@ P.appendCode(*Value); } + if (Offset) + Output.addParagraph().appendText( + llvm::formatv("Offset: {0} byte{1}", *Offset, *Offset == 1 ? "" : "s")); + if (Size) + Output.addParagraph().appendText( + llvm::formatv("Size: {0} byte{1}", *Size, *Size == 1 ? "" : "s")); + if (!Documentation.empty()) parseDocumentation(Documentation, Output);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits