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

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

snarang181
Copy link
Contributor

@snarang181 snarang181 commented May 31, 2025

Implements #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.

return Obj;
}

// BlockCommandComment needs to generate a Command key.
if (I.Kind == "BlockCommandComment")
case CommentKind::CK_BlockCommandComment: {
Child.getAsObject()->insert({"Command", I.Name});
Copy link
Member

Choose a reason for hiding this comment

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

Might be better to declare Child as an Object to avoid these gets, or use a reference. I believe all of this is still valid if Child is an Object.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed.

@@ -65,6 +65,35 @@ template <> struct ScalarEnumerationTraits<InfoType> {
}
};

template <>
struct llvm::yaml::ScalarEnumerationTraits<clang::doc::CommentKind> {
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't need the llvm::yaml qualification.

Comment on lines +681 to +682
// For now, no handling — fallthrough.
default:
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's handle all the cases w/o default. Then we should get an error if we change the enum and don't handle it here.

Comment on lines +48 to +62
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
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we just use the CommentKind from the clang AST? I haven't looked but I would also suppose that those have parsers already to go to/from the enum. It isn't a huge deal, but if we don't need to maintain that code ourselves .... it could be a good option. That said, I don't think we tablegen things w/ enum class so it may not be that great in the end. Anyway worth considering. I'm OK either way if there's a decent reason.

@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.

@@ -316,8 +316,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: {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can drop the braces here to match the existing convention.

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.
Change existing handling from if/else to switch-case for better clarity and extensibility.
@snarang181 snarang181 force-pushed the snarang181/refactor-clang-doc-comment-structure branch from 582fd20 to a37af42 Compare June 5, 2025 19:08
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.

4 participants