Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 33 additions & 9 deletions clang-tools-extra/clang-doc/JSONGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,21 @@ serializeLocation(const Location &Loc,
return LocationObj;
}

static json::Value serializeComment(const CommentInfo &I) {
static void insertComment(Object &Description, json::Value &Comment,
std::string Key) {
auto *CommentArray = Description.getArray(Key);
if (!CommentArray) {
auto CommentsArray = json::Array();
CommentsArray.push_back(Comment);
Description[Key] = std::move(CommentsArray);
Description["Has" + Key] = true;
} else {
CommentArray->push_back(Comment);
Description[Key] = std::move(*CommentArray);
}
}

static Object serializeComment(const CommentInfo &I, Object &Description) {
// taken from PR #142273
Object Obj = Object();

Expand All @@ -94,7 +108,7 @@ static json::Value serializeComment(const CommentInfo &I) {
auto &CARef = *ChildArr.getAsArray();
CARef.reserve(I.Children.size());
for (const auto &C : I.Children)
CARef.emplace_back(serializeComment(*C));
CARef.emplace_back(serializeComment(*C, Description));

switch (I.Kind) {
case CommentKind::CK_TextComment: {
Expand All @@ -106,6 +120,8 @@ static json::Value serializeComment(const CommentInfo &I) {
Child.insert({"Command", I.Name});
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
if (I.Name == "brief")
insertComment(Description, ChildVal, "BriefComments");
return Obj;
}

Expand Down Expand Up @@ -137,7 +153,10 @@ static json::Value serializeComment(const CommentInfo &I) {
if (!I.CloseName.empty())
Child.insert({"CloseName", I.CloseName});
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
if (I.CloseName == "endcode")
insertComment(Description, ChildVal, "CodeComments");
else if (I.CloseName == "endverbatim")
insertComment(Description, ChildVal, "VerbatimComments");
return Obj;
}

Expand Down Expand Up @@ -210,12 +229,17 @@ serializeCommonAttributes(const Info &I, json::Object &Obj,
}

if (!I.Description.empty()) {
json::Value DescArray = json::Array();
auto &DescArrayRef = *DescArray.getAsArray();
DescArrayRef.reserve(I.Description.size());
for (const auto &Comment : I.Description)
DescArrayRef.push_back(serializeComment(Comment));
Obj["Description"] = DescArray;
Object Description = Object();
// Skip straight to the FullComment's children
auto &Comments = I.Description.at(0).Children;
for (const auto &CommentInfo : Comments) {
json::Value Comment = serializeComment(*CommentInfo, Description);
// Paragraph comments might not be children
if (auto *ParagraphComment =
Comment.getAsObject()->get("ParagraphComment"))
insertComment(Description, *ParagraphComment, "ParagraphComments");
Comment on lines +237 to +240
Copy link
Contributor

Choose a reason for hiding this comment

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

The comment here implies to me that we may be missing paragraph comments. Am I understanding that correctly?

Copy link
Member Author

@evelez7 evelez7 Jul 18, 2025

Choose a reason for hiding this comment

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

Not really, because all paragraph comments were previously handled.

This is meant to signal that there are top level ParagraphComments that can be returned from serializeComment that need to be manually inserted into Description with this modified scheme. They can't be added like brief comments now are because we can't be sure if the ParagraphComment is nested (the text of a brief command is a paragraph comment). So, if the returned comment is a ParagraphComment, then it must be a top-level, standalone comment without a command.

Maybe this comment could use a revision. I just wanted to clarify why the ParagraphComment is handled specially here.

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, rewording would be helpful. thanks

}
Obj["Description"] = std::move(Description);
}

// Namespaces aren't SymbolInfos, so they dont have a DefLoc
Expand Down
51 changes: 24 additions & 27 deletions clang-tools-extra/test/clang-doc/json/class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,33 +33,30 @@ struct MyClass {
};

// CHECK: {
// CHECK-NEXT: "Description": [
// CHECK-NEXT: {
// CHECK-NEXT: "FullComment": {
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "ParagraphComment": {
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": " This is a nice class."
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": " It has some nice methods and fields."
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": ""
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK: {
// CHECK-NEXT: "BlockCommandComment": {
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "ParagraphComment": {
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": " This is a brief description."
// CHECK-NEXT: }
// CHECK: "Command": "brief"
// CHECK-NEXT: "Description": {
// CHECK-NEXT: "BriefComments": [
// CHECK-NEXT: {
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "ParagraphComment": {
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": " This is a brief description."
// CHECK: "Command": "brief"
// CHECK: "HasBriefComments": true,
// CHECK-NEXT: "HasParagraphComments": true,
// CHECK-NEXT: "ParagraphComments": [
// CHECK-NEXT: {
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": " This is a nice class."
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": " It has some nice methods and fields."
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": ""
// CHECK-NEXT: }
// CHECK: "DocumentationFileName": "_ZTV7MyClass",
// CHECK: "Enums": [
// CHECK-NEXT: {
Expand Down
15 changes: 6 additions & 9 deletions clang-tools-extra/test/clang-doc/json/concept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,13 @@ concept Incrementable = requires(T x) {
// CHECK-NEXT: "Concepts": [
// CHECK-NEXT: {
// CHECK-NEXT: "ConstraintExpression": "requires (T x) { ++x; x++; }",
// CHECK-NEXT: "Description": [
// CHECK-NEXT: "Description": {
// CHECK-NEXT: "HasParagraphComments": true,
// CHECK-NEXT: "ParagraphComments": [
// CHECK-NEXT: {
// CHECK-NEXT: "FullComment": {
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "ParagraphComment": {
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": " Requires that T suports post and pre-incrementing."
// CHECK: ],
// CHECK-NEXT: "Children": [
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": " Requires that T suports post and pre-incrementing."
// CHECK: "End": true,
// CHECK-NEXT: "InfoType": "concept",
// CHECK-NEXT: "IsType": true,
Expand Down
Loading