Author: PeterChou1 Date: 2024-08-16T18:37:17-04:00 New Revision: 5ef2456a438578b0783241a2744efc62d47e5ab6
URL: https://github.com/llvm/llvm-project/commit/5ef2456a438578b0783241a2744efc62d47e5ab6 DIFF: https://github.com/llvm/llvm-project/commit/5ef2456a438578b0783241a2744efc62d47e5ab6.diff LOG: [clang-doc] add support for enums comments in html generation (#101282) Part of https://github.com/llvm/llvm-project/issues/101129 This patch adds support for attaching comments to enums for HTML in clang-doc. It changes the enum generation to table tags where as perviously we're using lists which is more in line with what other doc generators are doing. It also gives clang-doc the ability to show user specified enum values Added: Modified: clang-tools-extra/clang-doc/BitcodeReader.cpp clang-tools-extra/clang-doc/BitcodeWriter.cpp clang-tools-extra/clang-doc/HTMLGenerator.cpp clang-tools-extra/clang-doc/Representation.cpp clang-tools-extra/clang-doc/Representation.h clang-tools-extra/clang-doc/Serialize.cpp clang-tools-extra/test/clang-doc/enum.cpp clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index bfb04e7407b380..1f2fb0a8b2b855 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -415,6 +415,10 @@ template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) { return &I->Description.emplace_back(); } +template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) { + return &I->Description.emplace_back(); +} + template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) { I->Children.emplace_back(std::make_unique<CommentInfo>()); return I->Children.back().get(); diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index 7e5a11783d303a..06f30f76e33d8c 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -536,6 +536,8 @@ void ClangDocBitcodeWriter::emitBlock(const EnumValueInfo &I) { emitRecord(I.Name, ENUM_VALUE_NAME); emitRecord(I.Value, ENUM_VALUE_VALUE); emitRecord(I.ValueExpr, ENUM_VALUE_EXPR); + for (const auto &CI : I.Description) + emitBlock(CI); } void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) { diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp index 21ee417da6028a..068eec6599ead8 100644 --- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -48,6 +48,12 @@ class HTMLTag { TAG_SPAN, TAG_TITLE, TAG_UL, + TAG_TABLE, + TAG_THEAD, + TAG_TBODY, + TAG_TR, + TAG_TD, + TAG_TH }; HTMLTag() = default; @@ -133,6 +139,12 @@ bool HTMLTag::isSelfClosing() const { case HTMLTag::TAG_SPAN: case HTMLTag::TAG_TITLE: case HTMLTag::TAG_UL: + case HTMLTag::TAG_TABLE: + case HTMLTag::TAG_THEAD: + case HTMLTag::TAG_TBODY: + case HTMLTag::TAG_TR: + case HTMLTag::TAG_TD: + case HTMLTag::TAG_TH: return false; } llvm_unreachable("Unhandled HTMLTag::TagType"); @@ -174,6 +186,18 @@ StringRef HTMLTag::toString() const { return "title"; case HTMLTag::TAG_UL: return "ul"; + case HTMLTag::TAG_TABLE: + return "table"; + case HTMLTag::TAG_THEAD: + return "thead"; + case HTMLTag::TAG_TBODY: + return "tbody"; + case HTMLTag::TAG_TR: + return "tr"; + case HTMLTag::TAG_TD: + return "td"; + case HTMLTag::TAG_TH: + return "th"; } llvm_unreachable("Unhandled HTMLTag::TagType"); } @@ -377,10 +401,27 @@ genEnumMembersBlock(const llvm::SmallVector<EnumValueInfo, 4> &Members) { if (Members.empty()) return nullptr; - auto List = std::make_unique<TagNode>(HTMLTag::TAG_UL); - for (const auto &M : Members) - List->Children.emplace_back( - std::make_unique<TagNode>(HTMLTag::TAG_LI, M.Name)); + auto List = std::make_unique<TagNode>(HTMLTag::TAG_TBODY); + + for (const auto &M : Members) { + auto TRNode = std::make_unique<TagNode>(HTMLTag::TAG_TR); + TRNode->Children.emplace_back( + std::make_unique<TagNode>(HTMLTag::TAG_TD, M.Name)); + // Use user supplied value if it exists, otherwise use the value + if (!M.ValueExpr.empty()) { + TRNode->Children.emplace_back( + std::make_unique<TagNode>(HTMLTag::TAG_TD, M.ValueExpr)); + } else { + TRNode->Children.emplace_back( + std::make_unique<TagNode>(HTMLTag::TAG_TD, M.Value)); + } + if (!M.Description.empty()) { + auto TD = std::make_unique<TagNode>(HTMLTag::TAG_TD); + TD->Children.emplace_back(genHTML(M.Description)); + TRNode->Children.emplace_back(std::move(TD)); + } + List->Children.emplace_back(std::move(TRNode)); + } return List; } @@ -624,7 +665,7 @@ static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) { } return std::move(FullComment); } - + if (I.Kind == "ParagraphComment") { auto ParagraphComment = std::make_unique<TagNode>(HTMLTag::TAG_P); for (const auto &Child : I.Children) { @@ -658,22 +699,36 @@ static std::vector<std::unique_ptr<TagNode>> genHTML(const EnumInfo &I, const ClangDocContext &CDCtx) { std::vector<std::unique_ptr<TagNode>> Out; std::string EnumType = I.Scoped ? "enum class " : "enum "; - - Out.emplace_back( - std::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.Name)); - Out.back()->Attributes.emplace_back("id", - llvm::toHex(llvm::toStringRef(I.USR))); - - std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members); - if (Node) - Out.emplace_back(std::move(Node)); + // Determine if enum members have comments attached + bool HasComments = std::any_of( + I.Members.begin(), I.Members.end(), + [](const EnumValueInfo &M) { return !M.Description.empty(); }); + std::unique_ptr<TagNode> Table = + std::make_unique<TagNode>(HTMLTag::TAG_TABLE); + std::unique_ptr<TagNode> THead = + std::make_unique<TagNode>(HTMLTag::TAG_THEAD); + std::unique_ptr<TagNode> TRow = std::make_unique<TagNode>(HTMLTag::TAG_TR); + std::unique_ptr<TagNode> TD = + std::make_unique<TagNode>(HTMLTag::TAG_TH, EnumType + I.Name); + // Span 3 columns if enum has comments + TD->Attributes.emplace_back("colspan", HasComments ? "3" : "2"); + + Table->Attributes.emplace_back("id", llvm::toHex(llvm::toStringRef(I.USR))); + TRow->Children.emplace_back(std::move(TD)); + THead->Children.emplace_back(std::move(TRow)); + Table->Children.emplace_back(std::move(THead)); + + if (std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members)) + Table->Children.emplace_back(std::move(Node)); + + Out.emplace_back(std::move(Table)); if (I.DefLoc) { if (!CDCtx.RepositoryUrl) Out.emplace_back(writeFileDefinition(*I.DefLoc)); else - Out.emplace_back(writeFileDefinition( - *I.DefLoc, StringRef{*CDCtx.RepositoryUrl})); + Out.emplace_back( + writeFileDefinition(*I.DefLoc, StringRef{*CDCtx.RepositoryUrl})); } std::string Description; diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index 6f140910b321fb..4da93b24c131fd 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -221,7 +221,7 @@ void SymbolInfo::merge(SymbolInfo &&Other) { } NamespaceInfo::NamespaceInfo(SymbolID USR, StringRef Name, StringRef Path) - : Info(InfoType::IT_namespace, USR, Name, Path) {} + : Info(InfoType::IT_namespace, USR, Name, Path) {} void NamespaceInfo::merge(NamespaceInfo &&Other) { assert(mergeable(Other)); diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 0695197cf3ac95..bb0c534af7b740 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -455,6 +455,8 @@ struct EnumValueInfo { // Stores the user-supplied initialization expression for this enumeration // constant. This will be empty for implicit enumeration values. SmallString<16> ValueExpr; + + std::vector<CommentInfo> Description; /// Comment description of this field. }; // TODO: Expand to allow for documenting templating. diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 3b074d849e8a9c..b9db78cf7d688f 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -394,10 +394,20 @@ static void parseEnumerators(EnumInfo &I, const EnumDecl *D) { std::string ValueExpr; if (const Expr *InitExpr = E->getInitExpr()) ValueExpr = getSourceCode(D, InitExpr->getSourceRange()); - SmallString<16> ValueStr; E->getInitVal().toString(ValueStr); - I.Members.emplace_back(E->getNameAsString(), ValueStr, ValueExpr); + I.Members.emplace_back(E->getNameAsString(), ValueStr.str(), ValueExpr); + ASTContext &Context = E->getASTContext(); + if (RawComment *Comment = + E->getASTContext().getRawCommentForDeclNoCache(E)) { + CommentInfo CInfo; + Comment->setAttached(); + if (comments::FullComment *Fc = Comment->parse(Context, nullptr, E)) { + EnumValueInfo &Member = I.Members.back(); + Member.Description.emplace_back(); + parseFullComment(Fc, Member.Description.back()); + } + } } } @@ -566,7 +576,7 @@ static void populateMemberTypeInfo(MemberTypeInfo &I, const FieldDecl *D) { return; Comment->setAttached(); - if (comments::FullComment* fc = Comment->parse(Context, nullptr, D)) { + if (comments::FullComment *fc = Comment->parse(Context, nullptr, D)) { I.Description.emplace_back(); parseFullComment(fc, I.Description.back()); } diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp index e559940a31de69..ef768e33b45668 100644 --- a/clang-tools-extra/test/clang-doc/enum.cpp +++ b/clang-tools-extra/test/clang-doc/enum.cpp @@ -21,9 +21,9 @@ enum Color { // MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* // HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> - Red, ///< Red - Green, ///< Green - Blue ///< Blue + Red, ///< Comment 1 + Green, ///< Comment 2 + Blue ///< Comment 3 }; // MD-INDEX: ## Enums @@ -34,11 +34,16 @@ enum Color { // MD-INDEX: | Blue | // MD-INDEX: **brief** For specifying RGB colors -// HTML-INDEX: <h2 id="Enums">Enums</h2> -// HTML-INDEX: <h3 id="{{([0-9A-F]{40})}}">enum Color</h3> -// HTML-INDEX: <li>Red</li> -// HTML-INDEX: <li>Green</li> -// HTML-INDEX: <li>Blue</li> +// HTML-INDEX: <th colspan="3">enum Color</th> +// HTML-INDEX: <td>Red</td> +// HTML-INDEX: <td>0</td> +// HTML-INDEX: <p> Comment 1</p> +// HTML-INDEX: <td>Green</td> +// HTML-INDEX: <td>1</td> +// HTML-INDEX: <p> Comment 2</p> +// HTML-INDEX: <td>Blue</td> +// HTML-INDEX: <td>2</td> +// HTML-INDEX: <p> Comment 3</p> /** * @brief Shape Types @@ -46,11 +51,12 @@ enum Color { enum class Shapes { // MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* // HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> - /// Circle + + /// Comment 1 Circle, - /// Rectangle + /// Comment 2 Rectangle, - /// Triangle + /// Comment 3 Triangle }; // MD-INDEX: | enum class Shapes | @@ -60,10 +66,17 @@ enum class Shapes { // MD-INDEX: | Triangle | // MD-INDEX: **brief** Shape Types -// HTML-INDEX: <h3 id="{{([0-9A-F]{40})}}">enum class Shapes</h3> -// HTML-INDEX: <li>Circle</li> -// HTML-INDEX: <li>Rectangle</li> -// HTML-INDEX: <li>Triangle</li> +// HTML-INDEX: <th colspan="3">enum class Shapes</th> +// HTML-INDEX: <td>Circle</td> +// HTML-INDEX: <td>0</td> +// HTML-INDEX: <p> Comment 1</p> +// HTML-INDEX: <td>Rectangle</td> +// HTML-INDEX: <td>1</td> +// HTML-INDEX: <p> Comment 2</p> +// HTML-INDEX: <td>Triangle</td> +// HTML-INDEX: <td>2</td> +// HTML-INDEX: <p> Comment 3</p> + class Animals { @@ -76,18 +89,25 @@ class Animals { enum AnimalType { // MD-ANIMAL-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* // HTML-ANIMAL-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> - Dog, /// Man's best friend - Cat, /// Man's other best friend - Iguana /// A lizard + Dog, ///< Man's best friend + Cat, ///< Man's other best friend + Iguana ///< A lizard }; }; // HTML-ANIMAL: <h1>class Animals</h1> // HTML-ANIMAL: <h2 id="Enums">Enums</h2> -// HTML-ANIMAL: <h3 id="{{([0-9A-F]{40})}}">enum AnimalType</h3> -// HTML-ANIMAL: <li>Dog</li> -// HTML-ANIMAL: <li>Cat</li> -// HTML-ANIMAL: <li>Iguana</li> +// HTML-ANIMAL: <th colspan="3">enum AnimalType</th> +// HTML-ANIMAL: <td>Dog</td> +// HTML-ANIMAL: <td>0</td> +// HTML-ANIMAL: <p> Man's best friend</p> +// HTML-ANIMAL: <td>Cat</td> +// HTML-ANIMAL: <td>1</td> +// HTML-ANIMAL: <p> Man's other best friend</p> +// HTML-ANIMAL: <td>Iguana</td> +// HTML-ANIMAL: <td>2</td> +// HTML-ANIMAL: <p> A lizard</p> + // MD-ANIMAL: # class Animals // MD-ANIMAL: ## Enums @@ -106,10 +126,11 @@ namespace Vehicles { enum Car { // MD-VEHICLES-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* // HTML-VEHICLES-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> - Sedan, /// Sedan - SUV, /// SUV - Pickup, /// Pickup - Hatchback /// Hatchback + + Sedan, ///< Comment 1 + SUV, ///< Comment 2 + Pickup, ///< Comment 3 + Hatchback ///< Comment 4 }; } @@ -124,9 +145,37 @@ namespace Vehicles { // MD-VEHICLES: **brief** specify type of car // HTML-VEHICLES: <h1>namespace Vehicles</h1> -// HTML-VEHICLES: <h2 id="Enums">Enums</h2> -// HTML-VEHICLES: <h3 id="{{([0-9A-F]{40})}}">enum Car</h3> -// HTML-VEHICLES: <li>Sedan</li> -// HTML-VEHICLES: <li>SUV</li> -// HTML-VEHICLES: <li>Pickup</li> -// HTML-VEHICLES: <li>Hatchback</li> \ No newline at end of file +// HTML-VEHICLES: <th colspan="3">enum Car</th> +// HTML-VEHICLES: <td>Sedan</td> +// HTML-VEHICLES: <td>0</td> +// HTML-VEHICLES: <p> Comment 1</p> +// HTML-VEHICLES: <td>SUV</td> +// HTML-VEHICLES: <td>1</td> +// HTML-VEHICLES: <p> Comment 2</p> +// HTML-VEHICLES: <td>Pickup</td> +// HTML-VEHICLES: <td>2</td> +// HTML-VEHICLES: <p> Comment 3</p> +// HTML-VEHICLES: <td>Hatchback</td> +// HTML-VEHICLES: <td>3</td> +// HTML-VEHICLES: <p> Comment 4</p> + + +enum ColorUserSpecified { + RedUserSpecified = 'A', + GreenUserSpecified = 2, + BlueUserSpecified = 'C' +}; + +// MD-INDEX: | enum ColorUserSpecified | +// MD-INDEX: -- +// MD-INDEX: | RedUserSpecified | +// MD-INDEX: | GreenUserSpecified | +// MD-INDEX: | BlueUserSpecified | + +// HTML-INDEX: <th colspan="2">enum ColorUserSpecified</th> +// HTML-INDEX: <td>RedUserSpecified</td> +// HTML-INDEX: <td>'A'</td> +// HTML-INDEX: <td>GreenUserSpecified</td> +// HTML-INDEX: <td>2</td> +// HTML-INDEX: <td>BlueUserSpecified</td> +// HTML-INDEX: <td>'C'</td> diff --git a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp index bd031282b042ab..dfd31e65787145 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp @@ -92,7 +92,13 @@ TEST(HTMLGeneratorTest, emitNamespaceHTML) { </div> <h2 id="Enums">Enums</h2> <div> - <h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3> + <table id="0000000000000000000000000000000000000000"> + <thead> + <tr> + <th colspan="2">enum OneEnum</th> + </tr> + </thead> + </table> </div> </div> <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"> @@ -214,7 +220,13 @@ TEST(HTMLGeneratorTest, emitRecordHTML) { </div> <h2 id="Enums">Enums</h2> <div> - <h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3> + <table id="0000000000000000000000000000000000000000"> + <thead> + <tr> + <th colspan="2">enum OneEnum</th> + </tr> + </thead> + </table> </div> </div> <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"> @@ -348,10 +360,19 @@ TEST(HTMLGeneratorTest, emitEnumHTML) { <main> <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div> <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content"> - <h3 id="0000000000000000000000000000000000000000">enum class e</h3> - <ul> - <li>X</li> - </ul> + <table id="0000000000000000000000000000000000000000"> + <thead> + <tr> + <th colspan="2">enum class e</th> + </tr> + </thead> + <tbody> + <tr> + <td>X</td> + <td>0</td> + </tr> + </tbody> + </table> <p> Defined at line <a href="https://www.repository.com/test.cpp#10">10</a> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits