Skip to content

Refactor clang doc comment structure #142273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

snarang181
Copy link
Contributor

@snarang181 snarang181 commented May 31, 2025

This patch refactors CommentKind handling in clang-doc by introducing a strongly typed enum class for better type safety and clarity. It updates all relevant places, including YAML traits and serialization, to work with the new enum. Additionally, it enhances the Mustache-based HTML generation by fully supporting all comment kinds, ensuring accurate structured rendering of comment blocks. The changes simplify future maintenance, improve robustness by eliminating unchecked defaults, and ensure consistency between generators.

Fixes #142083

@snarang181
Copy link
Contributor Author

@ilovepi, would be great to get your review here.

@snarang181 snarang181 marked this pull request as ready for review May 31, 2025 15:20
@llvmbot
Copy link
Member

llvmbot commented May 31, 2025

@llvm/pr-subscribers-clang-tools-extra

Author: Samarth Narang (snarang181)

Changes

Implements #142272


Patch is 51.90 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/142273.diff

17 Files Affected:

  • (modified) clang-tools-extra/clang-doc/BitcodeReader.cpp (+7-2)
  • (modified) clang-tools-extra/clang-doc/BitcodeWriter.cpp (+2-1)
  • (modified) clang-tools-extra/clang-doc/HTMLGenerator.cpp (+12-6)
  • (modified) clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp (+7-5)
  • (modified) clang-tools-extra/clang-doc/MDGenerator.cpp (+38-20)
  • (modified) clang-tools-extra/clang-doc/Representation.cpp (+60)
  • (modified) clang-tools-extra/clang-doc/Representation.h (+26-7)
  • (modified) clang-tools-extra/clang-doc/Serialize.cpp (+1-1)
  • (modified) clang-tools-extra/clang-doc/YAMLGenerator.cpp (+30-1)
  • (added) clang-tools-extra/test/clang-doc/Inputs/html-tag-comment.yaml (+12)
  • (added) clang-tools-extra/test/clang-doc/html-tag-comment.cpp (+17)
  • (modified) clang-tools-extra/test/clang-doc/templates.cpp (+8-8)
  • (modified) clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp (+35-33)
  • (modified) clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp (+10-10)
  • (modified) clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp (+29-27)
  • (modified) clang-tools-extra/unittests/clang-doc/MergeTest.cpp (+9-9)
  • (modified) clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp (+62-60)
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index f8e338eb7c6ed..2e5d402106547 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -315,8 +315,13 @@ static llvm::Error parseRecord(const Record &R, unsigned ID,
 static llvm::Error parseRecord(const Record &R, unsigned ID,
                                llvm::StringRef Blob, CommentInfo *I) {
   switch (ID) {
-  case COMMENT_KIND:
-    return decodeRecord(R, I->Kind, Blob);
+  case COMMENT_KIND: {
+    llvm::SmallString<16> KindStr;
+    if (llvm::Error Err = decodeRecord(R, KindStr, Blob))
+      return Err;
+    I->Kind = stringToCommentKind(KindStr);
+    return llvm::Error::success();
+  }
   case COMMENT_TEXT:
     return decodeRecord(R, I->Text, Blob);
   case COMMENT_NAME:
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
index f0a445e606bff..708ce09d9e5b2 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -484,8 +484,9 @@ void ClangDocBitcodeWriter::emitBlock(const MemberTypeInfo &T) {
 
 void ClangDocBitcodeWriter::emitBlock(const CommentInfo &I) {
   StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);
+  // Handle Kind (enum) separately, since it is not a string.
+  emitRecord(commentKindToString(I.Kind), COMMENT_KIND);
   for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{
-           {I.Kind, COMMENT_KIND},
            {I.Text, COMMENT_TEXT},
            {I.Name, COMMENT_NAME},
            {I.Direction, COMMENT_DIRECTION},
diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp
index 93b9279462a89..8a36fbf99c857 100644
--- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp
@@ -635,7 +635,8 @@ genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList) {
 }
 
 static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
-  if (I.Kind == "FullComment") {
+  switch (I.Kind) {
+  case CommentKind::CK_FullComment: {
     auto FullComment = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
     for (const auto &Child : I.Children) {
       std::unique_ptr<HTMLNode> Node = genHTML(*Child);
@@ -645,7 +646,7 @@ static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
     return std::move(FullComment);
   }
 
-  if (I.Kind == "ParagraphComment") {
+  case CommentKind::CK_ParagraphComment: {
     auto ParagraphComment = std::make_unique<TagNode>(HTMLTag::TAG_P);
     for (const auto &Child : I.Children) {
       std::unique_ptr<HTMLNode> Node = genHTML(*Child);
@@ -657,7 +658,7 @@ static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
     return std::move(ParagraphComment);
   }
 
-  if (I.Kind == "BlockCommandComment") {
+  case CommentKind::CK_BlockCommandComment: {
     auto BlockComment = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
     BlockComment->Children.emplace_back(
         std::make_unique<TagNode>(HTMLTag::TAG_DIV, I.Name));
@@ -670,12 +671,17 @@ static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
       return nullptr;
     return std::move(BlockComment);
   }
-  if (I.Kind == "TextComment") {
-    if (I.Text == "")
+
+  case CommentKind::CK_TextComment: {
+    if (I.Text.empty())
       return nullptr;
     return std::make_unique<TextNode>(I.Text);
   }
-  return nullptr;
+
+  // For now, no handling — fallthrough.
+  default:
+    return nullptr;
+  }
 }
 
 static std::unique_ptr<TagNode> genHTML(const std::vector<CommentInfo> &C) {
diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
index 65dc2e93582e8..95306eee12f31 100644
--- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
@@ -198,21 +198,23 @@ static json::Value extractValue(const TypedefInfo &I) {
 }
 
 static json::Value extractValue(const CommentInfo &I) {
-  assert((I.Kind == "BlockCommandComment" || I.Kind == "FullComment" ||
-          I.Kind == "ParagraphComment" || I.Kind == "TextComment") &&
+  assert((I.Kind == CommentKind::CK_BlockCommandComment ||
+          I.Kind == CommentKind::CK_FullComment ||
+          I.Kind == CommentKind::CK_ParagraphComment ||
+          I.Kind == CommentKind::CK_TextComment) &&
          "Unknown Comment type in CommentInfo.");
 
   Object Obj = Object();
   json::Value Child = Object();
 
   // TextComment has no children, so return it.
-  if (I.Kind == "TextComment") {
+  if (I.Kind == CommentKind::CK_TextComment) {
     Obj.insert({"TextComment", I.Text});
     return Obj;
   }
 
   // BlockCommandComment needs to generate a Command key.
-  if (I.Kind == "BlockCommandComment")
+  if (I.Kind == CommentKind::CK_BlockCommandComment)
     Child.getAsObject()->insert({"Command", I.Name});
 
   // Use the same handling for everything else.
@@ -226,7 +228,7 @@ static json::Value extractValue(const CommentInfo &I) {
   for (const auto &C : I.Children)
     CARef.emplace_back(extractValue(*C));
   Child.getAsObject()->insert({"Children", ChildArr});
-  Obj.insert({I.Kind, Child});
+  Obj.insert({commentKindToString(I.Kind), Child});
 
   return Obj;
 }
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index ccd6175c96cb8..2becccf8b07da 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -75,39 +75,49 @@ static void maybeWriteSourceFileRef(llvm::raw_ostream &OS,
 }
 
 static void writeDescription(const CommentInfo &I, raw_ostream &OS) {
-  if (I.Kind == "FullComment") {
+  switch (I.Kind) {
+  case CommentKind::CK_FullComment:
     for (const auto &Child : I.Children)
       writeDescription(*Child, OS);
-  } else if (I.Kind == "ParagraphComment") {
+    break;
+
+  case CommentKind::CK_ParagraphComment:
     for (const auto &Child : I.Children)
       writeDescription(*Child, OS);
     writeNewLine(OS);
-  } else if (I.Kind == "BlockCommandComment") {
+    break;
+
+  case CommentKind::CK_BlockCommandComment:
     OS << genEmphasis(I.Name);
     for (const auto &Child : I.Children)
       writeDescription(*Child, OS);
-  } else if (I.Kind == "InlineCommandComment") {
+    break;
+
+  case CommentKind::CK_InlineCommandComment:
     OS << genEmphasis(I.Name) << " " << I.Text;
-  } else if (I.Kind == "ParamCommandComment") {
-    std::string Direction = I.Explicit ? (" " + I.Direction).str() : "";
-    OS << genEmphasis(I.ParamName) << I.Text << Direction;
-    for (const auto &Child : I.Children)
-      writeDescription(*Child, OS);
-  } else if (I.Kind == "TParamCommandComment") {
+    break;
+
+  case CommentKind::CK_ParamCommandComment:
+  case CommentKind::CK_TParamCommandComment: {
     std::string Direction = I.Explicit ? (" " + I.Direction).str() : "";
     OS << genEmphasis(I.ParamName) << I.Text << Direction;
     for (const auto &Child : I.Children)
       writeDescription(*Child, OS);
-  } else if (I.Kind == "VerbatimBlockComment") {
+    break;
+  }
+
+  case CommentKind::CK_VerbatimBlockComment:
     for (const auto &Child : I.Children)
       writeDescription(*Child, OS);
-  } else if (I.Kind == "VerbatimBlockLineComment") {
-    OS << I.Text;
-    writeNewLine(OS);
-  } else if (I.Kind == "VerbatimLineComment") {
+    break;
+
+  case CommentKind::CK_VerbatimBlockLineComment:
+  case CommentKind::CK_VerbatimLineComment:
     OS << I.Text;
     writeNewLine(OS);
-  } else if (I.Kind == "HTMLStartTagComment") {
+    break;
+
+  case CommentKind::CK_HTMLStartTagComment: {
     if (I.AttrKeys.size() != I.AttrValues.size())
       return;
     std::string Buffer;
@@ -117,12 +127,20 @@ static void writeDescription(const CommentInfo &I, raw_ostream &OS) {
 
     std::string CloseTag = I.SelfClosing ? "/>" : ">";
     writeLine("<" + I.Name + Attrs.str() + CloseTag, OS);
-  } else if (I.Kind == "HTMLEndTagComment") {
+    break;
+  }
+
+  case CommentKind::CK_HTMLEndTagComment:
     writeLine("</" + I.Name + ">", OS);
-  } else if (I.Kind == "TextComment") {
+    break;
+
+  case CommentKind::CK_TextComment:
     OS << I.Text;
-  } else {
-    OS << "Unknown comment kind: " << I.Kind << ".\n\n";
+    break;
+
+  case CommentKind::CK_Unknown:
+    OS << "Unknown comment kind: " << static_cast<int>(I.Kind) << ".\n\n";
+    break;
   }
 }
 
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index 9ab2f342d969a..9fb3839419731 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -26,6 +26,66 @@
 namespace clang {
 namespace doc {
 
+CommentKind stringToCommentKind(llvm::StringRef KindStr) {
+  if (KindStr == "FullComment")
+    return CommentKind::CK_FullComment;
+  if (KindStr == "ParagraphComment")
+    return CommentKind::CK_ParagraphComment;
+  if (KindStr == "TextComment")
+    return CommentKind::CK_TextComment;
+  if (KindStr == "InlineCommandComment")
+    return CommentKind::CK_InlineCommandComment;
+  if (KindStr == "HTMLStartTagComment")
+    return CommentKind::CK_HTMLStartTagComment;
+  if (KindStr == "HTMLEndTagComment")
+    return CommentKind::CK_HTMLEndTagComment;
+  if (KindStr == "BlockCommandComment")
+    return CommentKind::CK_BlockCommandComment;
+  if (KindStr == "ParamCommandComment")
+    return CommentKind::CK_ParamCommandComment;
+  if (KindStr == "TParamCommandComment")
+    return CommentKind::CK_TParamCommandComment;
+  if (KindStr == "VerbatimBlockComment")
+    return CommentKind::CK_VerbatimBlockComment;
+  if (KindStr == "VerbatimBlockLineComment")
+    return CommentKind::CK_VerbatimBlockLineComment;
+  if (KindStr == "VerbatimLineComment")
+    return CommentKind::CK_VerbatimLineComment;
+  return CommentKind::CK_Unknown;
+}
+
+llvm::StringRef commentKindToString(CommentKind Kind) {
+  switch (Kind) {
+  case CommentKind::CK_FullComment:
+    return "FullComment";
+  case CommentKind::CK_ParagraphComment:
+    return "ParagraphComment";
+  case CommentKind::CK_TextComment:
+    return "TextComment";
+  case CommentKind::CK_InlineCommandComment:
+    return "InlineCommandComment";
+  case CommentKind::CK_HTMLStartTagComment:
+    return "HTMLStartTagComment";
+  case CommentKind::CK_HTMLEndTagComment:
+    return "HTMLEndTagComment";
+  case CommentKind::CK_BlockCommandComment:
+    return "BlockCommandComment";
+  case CommentKind::CK_ParamCommandComment:
+    return "ParamCommandComment";
+  case CommentKind::CK_TParamCommandComment:
+    return "TParamCommandComment";
+  case CommentKind::CK_VerbatimBlockComment:
+    return "VerbatimBlockComment";
+  case CommentKind::CK_VerbatimBlockLineComment:
+    return "VerbatimBlockLineComment";
+  case CommentKind::CK_VerbatimLineComment:
+    return "VerbatimLineComment";
+  case CommentKind::CK_Unknown:
+    return "Unknown";
+  }
+  llvm_unreachable("Unhandled CommentKind");
+}
+
 namespace {
 
 const SymbolID EmptySID = SymbolID();
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index a3a6217f76bbd..15f5638a80803 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -45,6 +45,25 @@ enum class InfoType {
   IT_typedef
 };
 
+enum class CommentKind {
+  CK_FullComment,
+  CK_ParagraphComment,
+  CK_TextComment,
+  CK_InlineCommandComment,
+  CK_HTMLStartTagComment,
+  CK_HTMLEndTagComment,
+  CK_BlockCommandComment,
+  CK_ParamCommandComment,
+  CK_TParamCommandComment,
+  CK_VerbatimBlockComment,
+  CK_VerbatimBlockLineComment,
+  CK_VerbatimLineComment,
+  CK_Unknown
+};
+
+CommentKind stringToCommentKind(llvm::StringRef KindStr);
+llvm::StringRef commentKindToString(CommentKind Kind);
+
 // A representation of a parsed comment.
 struct CommentInfo {
   CommentInfo() = default;
@@ -60,13 +79,13 @@ struct CommentInfo {
   // the vector.
   bool operator<(const CommentInfo &Other) const;
 
-  // TODO: The Kind field should be an enum, so we can switch on it easily.
-  SmallString<16>
-      Kind; // Kind of comment (FullComment, ParagraphComment, TextComment,
-            // InlineCommandComment, HTMLStartTagComment, HTMLEndTagComment,
-            // BlockCommandComment, ParamCommandComment,
-            // TParamCommandComment, VerbatimBlockComment,
-            // VerbatimBlockLineComment, VerbatimLineComment).
+  CommentKind Kind = CommentKind::
+      CK_Unknown; // Kind of comment (FullComment, ParagraphComment,
+                  // TextComment, InlineCommandComment, HTMLStartTagComment,
+                  // HTMLEndTagComment, BlockCommandComment,
+                  // ParamCommandComment, TParamCommandComment,
+                  // VerbatimBlockComment, VerbatimBlockLineComment,
+                  // VerbatimLineComment).
   SmallString<64> Text;      // Text of the comment.
   SmallString<16> Name;      // Name of the comment (for Verbatim and HTML).
   SmallString<8> Direction;  // Parameter direction (for (T)ParamCommand).
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index 3932a939de973..462001b3f3027 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -270,7 +270,7 @@ class ClangDocCommentVisitor
 };
 
 void ClangDocCommentVisitor::parseComment(const comments::Comment *C) {
-  CurrentCI.Kind = C->getCommentKindName();
+  CurrentCI.Kind = stringToCommentKind(C->getCommentKindName());
   ConstCommentVisitor<ClangDocCommentVisitor>::visit(C);
   for (comments::Comment *Child :
        llvm::make_range(C->child_begin(), C->child_end())) {
diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
index 8c110b34e8e20..09fadcbc1e742 100644
--- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -65,6 +65,35 @@ template <> struct ScalarEnumerationTraits<InfoType> {
   }
 };
 
+template <>
+struct llvm::yaml::ScalarEnumerationTraits<clang::doc::CommentKind> {
+  static void enumeration(IO &IO, clang::doc::CommentKind &Value) {
+    IO.enumCase(Value, "FullComment", clang::doc::CommentKind::CK_FullComment);
+    IO.enumCase(Value, "ParagraphComment",
+                clang::doc::CommentKind::CK_ParagraphComment);
+    IO.enumCase(Value, "TextComment", clang::doc::CommentKind::CK_TextComment);
+    IO.enumCase(Value, "InlineCommandComment",
+                clang::doc::CommentKind::CK_InlineCommandComment);
+    IO.enumCase(Value, "HTMLStartTagComment",
+                clang::doc::CommentKind::CK_HTMLStartTagComment);
+    IO.enumCase(Value, "HTMLEndTagComment",
+                clang::doc::CommentKind::CK_HTMLEndTagComment);
+    IO.enumCase(Value, "BlockCommandComment",
+                clang::doc::CommentKind::CK_BlockCommandComment);
+    IO.enumCase(Value, "ParamCommandComment",
+                clang::doc::CommentKind::CK_ParamCommandComment);
+    IO.enumCase(Value, "TParamCommandComment",
+                clang::doc::CommentKind::CK_TParamCommandComment);
+    IO.enumCase(Value, "VerbatimBlockComment",
+                clang::doc::CommentKind::CK_VerbatimBlockComment);
+    IO.enumCase(Value, "VerbatimBlockLineComment",
+                clang::doc::CommentKind::CK_VerbatimBlockLineComment);
+    IO.enumCase(Value, "VerbatimLineComment",
+                clang::doc::CommentKind::CK_VerbatimLineComment);
+    IO.enumCase(Value, "Unknown", clang::doc::CommentKind::CK_Unknown);
+  }
+};
+
 // Scalars to YAML output.
 template <unsigned U> struct ScalarTraits<SmallString<U>> {
 
@@ -149,7 +178,7 @@ static void recordInfoMapping(IO &IO, RecordInfo &I) {
 }
 
 static void commentInfoMapping(IO &IO, CommentInfo &I) {
-  IO.mapOptional("Kind", I.Kind, SmallString<16>());
+  IO.mapOptional("Kind", I.Kind, CommentKind::CK_Unknown);
   IO.mapOptional("Text", I.Text, SmallString<64>());
   IO.mapOptional("Name", I.Name, SmallString<16>());
   IO.mapOptional("Direction", I.Direction, SmallString<8>());
diff --git a/clang-tools-extra/test/clang-doc/Inputs/html-tag-comment.yaml b/clang-tools-extra/test/clang-doc/Inputs/html-tag-comment.yaml
new file mode 100644
index 0000000000000..875e9b5947f47
--- /dev/null
+++ b/clang-tools-extra/test/clang-doc/Inputs/html-tag-comment.yaml
@@ -0,0 +1,12 @@
+---
+Name:            'withHtmlTag'
+Description:
+  - Kind:          FullComment
+    Children:
+      - Kind:        VerbatimBlockComment
+        Name:        'verbatim'
+        CloseName:   'endverbatim'
+        Children:
+          - Kind:      VerbatimBlockLineComment
+            Text:      '<ul class="test"><li> Testing. </li></ul>'
+...
diff --git a/clang-tools-extra/test/clang-doc/html-tag-comment.cpp b/clang-tools-extra/test/clang-doc/html-tag-comment.cpp
new file mode 100644
index 0000000000000..97e2e3b22e368
--- /dev/null
+++ b/clang-tools-extra/test/clang-doc/html-tag-comment.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-doc --public --format=yaml -p %T %s -output=%t
+// RUN: FileCheck --input-file=%S/Inputs/html-tag-comment.yaml %s
+
+/// \verbatim <ul class="test"><li> Testing. </li></ul> \endverbatim
+void withHtmlTag() {}
+// CHECK: ---
+// CHECK: Name:            'withHtmlTag'
+// CHECK: Description:
+// CHECK:   - Kind:          FullComment
+// CHECK:     Children:
+// CHECK:       - Kind:        VerbatimBlockComment
+// CHECK:         Name:        'verbatim'
+// CHECK:         CloseName:   'endverbatim'
+// CHECK:         Children:
+// CHECK:           - Kind:      VerbatimBlockLineComment
+// CHECK:             Text:      '<ul class="test"><li> Testing. </li></ul>'
+// CHECK: ...
diff --git a/clang-tools-extra/test/clang-doc/templates.cpp b/clang-tools-extra/test/clang-doc/templates.cpp
index 426a0b16befd4..abe03a7d2d0ea 100644
--- a/clang-tools-extra/test/clang-doc/templates.cpp
+++ b/clang-tools-extra/test/clang-doc/templates.cpp
@@ -112,22 +112,22 @@ tuple<int, int, bool> func_with_tuple_param(tuple<int, int, bool> t) { return t;
 // YAML-NEXT:   - USR:             '{{([0-9A-F]{40})}}'
 // YAML-NEXT:    Name:            'func_with_tuple_param'
 // YAML-NEXT:    Description:
-// YAML-NEXT:      - Kind:            'FullComment'
+// YAML-NEXT:      - Kind:            FullComment
 // YAML-NEXT:        Children:
-// YAML-NEXT:          - Kind:            'ParagraphComment'
+// YAML-NEXT:          - Kind:            ParagraphComment
 // YAML-NEXT:            Children:
-// YAML-NEXT:              - Kind:            'TextComment'
+// YAML-NEXT:              - Kind:            TextComment
 // YAML-NEXT:                Text:            ' A function with a tuple parameter'
-// YAML-NEXT:          - Kind:            'ParagraphComment'
+// YAML-NEXT:          - Kind:            ParagraphComment
 // YAML-NEXT:            Children:
-// YAML-NEXT:              - Kind:            'TextComment'
-// YAML-NEXT:          - Kind:            'ParamCommandComment'
+// YAML-NEXT:              - Kind:            TextComment
+// YAML-NEXT:          - Kind:            ParamCommandComment
 // YAML-NEXT:            Direction:       '[in]'
 // YAML-NEXT:            ParamName:       't'
 // YAML-NEXT:            Children:
-// YAML-NEXT:              - Kind:            'ParagraphComment'
+// YAML-NEXT:              - Kind:            ParagraphComment
 // YAML-NEXT:                Children:
-// YAML-NEXT:                  - Kind:            'TextComment'
+// YAML-NEXT:                  - Kind:            TextComment
 // YAML-NEXT:                    Text:            ' The input to func_with_tuple_param'
 // YAML-NEXT:    DefLocation:
 // YAML-NEXT:      LineNumber:      [[# @LINE - 23]]
diff --git a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
index 4f2466af9a6bd..bbe158ed50e28 100644
--- a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
@@ -93,12 +93,12 @@ TEST(BitcodeTest, emitRecordInfoBitcode) {
 
   // Documentation for the data member.
   CommentInfo TopComment;
-  TopComment.Kind = "FullComment";
+  TopComment.Kind = CommentKind::CK_FullComment;
   TopComment.Children.emplace_back(std::make_unique<CommentInfo>());
   CommentInfo *Brief = TopComment.Children....
[truncated]

@snarang181 snarang181 marked this pull request as draft June 1, 2025 10:41
@snarang181 snarang181 force-pushed the snarang181/refactor-clang-doc-comment-structure branch from ce0600f to e7d33b2 Compare June 1, 2025 13:13
@snarang181 snarang181 marked this pull request as ready for review June 1, 2025 15:11
@qcolombet qcolombet requested a review from ilovepi June 1, 2025 16:23
Copy link
Contributor

@ilovepi ilovepi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take another pass later in the week, but here are some initial comments.

@snarang181 snarang181 force-pushed the snarang181/refactor-clang-doc-comment-structure branch from 8760ea8 to 832cd39 Compare June 5, 2025 10:47
@snarang181 snarang181 requested review from ilovepi and evelez7 June 5, 2025 10:48
@snarang181
Copy link
Contributor Author

Left a reply to this comment @ilovepi. Addressed some other comments.

Copy link

github-actions bot commented Jun 5, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@snarang181 snarang181 force-pushed the snarang181/refactor-clang-doc-comment-structure branch from 582fd20 to a37af42 Compare June 5, 2025 19:08
Copy link
Contributor

@ilovepi ilovepi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting pretty close. I think once the remaining comments are addressed it will probably be ready to land.

@ilovepi
Copy link
Contributor

ilovepi commented Jun 6, 2025

Oh, lets updated the PR description with a more complete description of the change. It can also be marked as Fixes #NNN since this basically implements everything outlined in the issues, unless I'm forgetting something.

@snarang181
Copy link
Contributor Author

Oh, lets updated the PR description with a more complete description of the change. It can also be marked as Fixes #NNN since this basically implements everything outlined in the issues, unless I'm forgetting something.

Done.

@snarang181 snarang181 force-pushed the snarang181/refactor-clang-doc-comment-structure branch from a37af42 to 5207933 Compare June 6, 2025 03:11
Copy link
Contributor

@ilovepi ilovepi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the last few nits are addressed.

This patch replaces the raw SmallString<16> `Kind` field in `CommentInfo`
with a strongly typed enum `CommentKind`. This improves type safety,
allows compiler-checked switch handling, and removes the reliance on
string comparisons across the clang-doc codebase.
@snarang181 snarang181 force-pushed the snarang181/refactor-clang-doc-comment-structure branch from 5207933 to 273d097 Compare June 6, 2025 21:19
@snarang181
Copy link
Contributor Author

LGTM once the last few nits are addressed.

@ilovepi, for the last few nits,

  • Removed the default case in the switch, and manually returning nullptr for all the unhandled cases.
  • Removed the braces in the case of the switch and shifted the variable decl. inside outside the switch to get around the compiler errors.

@snarang181 snarang181 requested a review from ilovepi June 6, 2025 21:21
Copy link
Contributor

@ilovepi ilovepi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the patch

@snarang181
Copy link
Contributor Author

LGTM. Thanks for the patch

Awesome, feel free to merge when you see fit. I don't think I can do so myself.

@ilovepi ilovepi merged commit d570409 into llvm:main Jun 7, 2025
7 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jun 7, 2025

LLVM Buildbot has detected a new failure on builder sanitizer-x86_64-linux-fast running on sanitizer-buildbot4 while building clang-tools-extra at step 2 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/169/builds/12077

Here is the relevant piece of the build log for the reference
Step 2 (annotate) failure: 'python ../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py' (failure)
...
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/lld-link
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/ld.lld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/lld-link
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/main.py:73: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 90157 tests, 88 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90
FAIL: LLVM :: ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s (62071 of 90157)
******************** TEST 'LLVM :: ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/llvm-mc -filetype=obj -triple=x86_64-windows-msvc /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s -o /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/test/ExecutionEngine/JITLink/x86-64/Output/COFF_directive_alternatename_fail.s.tmp # RUN: at line 1
+ /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/llvm-mc -filetype=obj -triple=x86_64-windows-msvc /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s -o /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/test/ExecutionEngine/JITLink/x86-64/Output/COFF_directive_alternatename_fail.s.tmp
not /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/llvm-jitlink -noexec /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/test/ExecutionEngine/JITLink/x86-64/Output/COFF_directive_alternatename_fail.s.tmp 2>&1 | /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/FileCheck /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s # RUN: at line 2
+ /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/FileCheck /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s
+ not /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/llvm-jitlink -noexec /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/test/ExecutionEngine/JITLink/x86-64/Output/COFF_directive_alternatename_fail.s.tmp

--

********************
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90..
Slowest Tests:
--------------------------------------------------------------------------
563.23s: LLVM :: CodeGen/AMDGPU/sched-group-barrier-pipeline-solver.mir
427.14s: Clang :: Driver/fsanitize.c
335.22s: Clang :: Preprocessor/riscv-target-features.c
326.08s: LLVM :: CodeGen/AMDGPU/amdgcn.bitcast.1024bit.ll
266.76s: Clang :: OpenMP/target_update_codegen.cpp
244.12s: Clang :: OpenMP/target_defaultmap_codegen_01.cpp
243.14s: Clang :: Driver/arm-cortex-cpus-1.c
240.92s: Clang :: Driver/arm-cortex-cpus-2.c
239.23s: Clang :: Preprocessor/arm-target-features.c
228.31s: Clang :: Preprocessor/aarch64-target-features.c
216.39s: LLVM :: CodeGen/AMDGPU/memintrinsic-unroll.ll
202.47s: Clang :: Analysis/a_flaky_crash.cpp
199.89s: Clang :: Preprocessor/predefined-arch-macros.c
185.34s: LLVM :: CodeGen/RISCV/attributes.ll
182.40s: Clang :: CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret.c
162.29s: Clang :: Driver/linux-ld.c
161.02s: Clang :: CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret-bfloat.c
153.04s: Clang :: Driver/x86-target-features.c
146.21s: Clang :: Driver/clang_f_opts.c
144.30s: Clang :: Driver/cl-options.c

Step 10 (stage2/asan_ubsan check) failure: stage2/asan_ubsan check (failure)
...
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/lld-link
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/ld.lld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/lld-link
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/utils/lit/lit/main.py:73: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 90157 tests, 88 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90
FAIL: LLVM :: ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s (62071 of 90157)
******************** TEST 'LLVM :: ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/llvm-mc -filetype=obj -triple=x86_64-windows-msvc /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s -o /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/test/ExecutionEngine/JITLink/x86-64/Output/COFF_directive_alternatename_fail.s.tmp # RUN: at line 1
+ /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/llvm-mc -filetype=obj -triple=x86_64-windows-msvc /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s -o /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/test/ExecutionEngine/JITLink/x86-64/Output/COFF_directive_alternatename_fail.s.tmp
not /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/llvm-jitlink -noexec /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/test/ExecutionEngine/JITLink/x86-64/Output/COFF_directive_alternatename_fail.s.tmp 2>&1 | /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/FileCheck /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s # RUN: at line 2
+ /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/FileCheck /home/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/COFF_directive_alternatename_fail.s
+ not /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/bin/llvm-jitlink -noexec /home/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan_ubsan/test/ExecutionEngine/JITLink/x86-64/Output/COFF_directive_alternatename_fail.s.tmp

--

********************
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90..
Slowest Tests:
--------------------------------------------------------------------------
563.23s: LLVM :: CodeGen/AMDGPU/sched-group-barrier-pipeline-solver.mir
427.14s: Clang :: Driver/fsanitize.c
335.22s: Clang :: Preprocessor/riscv-target-features.c
326.08s: LLVM :: CodeGen/AMDGPU/amdgcn.bitcast.1024bit.ll
266.76s: Clang :: OpenMP/target_update_codegen.cpp
244.12s: Clang :: OpenMP/target_defaultmap_codegen_01.cpp
243.14s: Clang :: Driver/arm-cortex-cpus-1.c
240.92s: Clang :: Driver/arm-cortex-cpus-2.c
239.23s: Clang :: Preprocessor/arm-target-features.c
228.31s: Clang :: Preprocessor/aarch64-target-features.c
216.39s: LLVM :: CodeGen/AMDGPU/memintrinsic-unroll.ll
202.47s: Clang :: Analysis/a_flaky_crash.cpp
199.89s: Clang :: Preprocessor/predefined-arch-macros.c
185.34s: LLVM :: CodeGen/RISCV/attributes.ll
182.40s: Clang :: CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret.c
162.29s: Clang :: Driver/linux-ld.c
161.02s: Clang :: CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret-bfloat.c
153.04s: Clang :: Driver/x86-target-features.c
146.21s: Clang :: Driver/clang_f_opts.c
144.30s: Clang :: Driver/cl-options.c


@snarang181
Copy link
Contributor Author

@ilovepi, this failure is probably related to the merged PR, right?

@ilovepi
Copy link
Contributor

ilovepi commented Jun 8, 2025

@snarang181 I cannot see how this patch would affect a test in the JIT. Sometimes main is not clean, and sometime there is flake in some tests or under a sanitizer. We should be good IMO.

@snarang181
Copy link
Contributor Author

Sounds good, @ilovepi. I also raised an issue to get commit access and you might have gotten a notification. It'd be great if you can take a look at that too :)

@snarang181 snarang181 deleted the snarang181/refactor-clang-doc-comment-structure branch June 9, 2025 18:21
rorth pushed a commit to rorth/llvm-project that referenced this pull request Jun 11, 2025
This patch refactors CommentKind handling in clang-doc by introducing a
strongly typed enum class for better type safety and clarity. It updates
all relevant places, including YAML traits and serialization, to work
with the new enum. Additionally, it enhances the Mustache-based HTML
generation by fully supporting all comment kinds, ensuring accurate
structured rendering of comment blocks. The changes simplify future
maintenance, improve robustness by eliminating unchecked defaults, and
ensure consistency between generators.

Fixes llvm#142083
DhruvSrivastavaX pushed a commit to DhruvSrivastavaX/lldb-for-aix that referenced this pull request Jun 12, 2025
This patch refactors CommentKind handling in clang-doc by introducing a
strongly typed enum class for better type safety and clarity. It updates
all relevant places, including YAML traits and serialization, to work
with the new enum. Additionally, it enhances the Mustache-based HTML
generation by fully supporting all comment kinds, ensuring accurate
structured rendering of comment blocks. The changes simplify future
maintenance, improve robustness by eliminating unchecked defaults, and
ensure consistency between generators.

Fixes llvm#142083
tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
This patch refactors CommentKind handling in clang-doc by introducing a
strongly typed enum class for better type safety and clarity. It updates
all relevant places, including YAML traits and serialization, to work
with the new enum. Additionally, it enhances the Mustache-based HTML
generation by fully supporting all comment kinds, ensuring accurate
structured rendering of comment blocks. The changes simplify future
maintenance, improve robustness by eliminating unchecked defaults, and
ensure consistency between generators.

Fixes llvm#142083
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clang-doc] Handle additional comment types in MustacheHTMLGenerator
5 participants