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
Merged
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
6 changes: 5 additions & 1 deletion clang-tools-extra/clang-doc/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +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) {
llvm::SmallString<16> KindStr;
switch (ID) {
case COMMENT_KIND:
return decodeRecord(R, I->Kind, Blob);
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:
Expand Down
3 changes: 2 additions & 1 deletion clang-tools-extra/clang-doc/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down
27 changes: 21 additions & 6 deletions clang-tools-extra/clang-doc/HTMLGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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));
Expand All @@ -670,12 +671,26 @@ 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, return nullptr for unsupported comment kinds
case CommentKind::CK_InlineCommandComment:
case CommentKind::CK_HTMLStartTagComment:
case CommentKind::CK_HTMLEndTagComment:
case CommentKind::CK_ParamCommandComment:
case CommentKind::CK_TParamCommandComment:
case CommentKind::CK_VerbatimBlockComment:
case CommentKind::CK_VerbatimBlockLineComment:
case CommentKind::CK_VerbatimLineComment:
case CommentKind::CK_Unknown:
return nullptr;
}
llvm_unreachable("Unhandled CommentKind");
}

static std::unique_ptr<TagNode> genHTML(const std::vector<CommentInfo> &C) {
Expand Down
139 changes: 115 additions & 24 deletions clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,37 +208,110 @@ 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") &&
"Unknown Comment type in CommentInfo.");

Object Obj = Object();
json::Value Child = Object();

// TextComment has no children, so return it.
if (I.Kind == "TextComment") {
Obj.insert({"TextComment", I.Text});
return Obj;
}
json::Value ChildVal = Object();
Object &Child = *ChildVal.getAsObject();

// BlockCommandComment needs to generate a Command key.
if (I.Kind == "BlockCommandComment")
Child.getAsObject()->insert({"Command", I.Name});

// Use the same handling for everything else.
// Only valid for:
// - BlockCommandComment
// - FullComment
// - ParagraphComment
json::Value ChildArr = Array();
auto &CARef = *ChildArr.getAsArray();
CARef.reserve(I.Children.size());
for (const auto &C : I.Children)
CARef.emplace_back(extractValue(*C));
Child.getAsObject()->insert({"Children", ChildArr});
Obj.insert({I.Kind, Child});

return Obj;
switch (I.Kind) {
case CommentKind::CK_TextComment: {
Obj.insert({commentKindToString(I.Kind), I.Text});
return Obj;
}

case CommentKind::CK_BlockCommandComment: {
Child.insert({"Command", I.Name});
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
return Obj;
}

case CommentKind::CK_InlineCommandComment: {
json::Value ArgsArr = Array();
auto &ARef = *ArgsArr.getAsArray();
ARef.reserve(I.Args.size());
for (const auto &Arg : I.Args)
ARef.emplace_back(Arg);
Child.insert({"Command", I.Name});
Child.insert({"Args", ArgsArr});
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
return Obj;
}

case CommentKind::CK_ParamCommandComment:
case CommentKind::CK_TParamCommandComment: {
Child.insert({"ParamName", I.ParamName});
Child.insert({"Direction", I.Direction});
Child.insert({"Explicit", I.Explicit});
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
return Obj;
}

case CommentKind::CK_VerbatimBlockComment: {
Child.insert({"Text", I.Text});
if (!I.CloseName.empty())
Child.insert({"CloseName", I.CloseName});
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
return Obj;
}

case CommentKind::CK_VerbatimBlockLineComment:
case CommentKind::CK_VerbatimLineComment: {
Child.insert({"Text", I.Text});
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
return Obj;
}

case CommentKind::CK_HTMLStartTagComment: {
json::Value AttrKeysArray = json::Array();
json::Value AttrValuesArray = json::Array();
auto &KeyArr = *AttrKeysArray.getAsArray();
auto &ValArr = *AttrValuesArray.getAsArray();
KeyArr.reserve(I.AttrKeys.size());
ValArr.reserve(I.AttrValues.size());
for (const auto &K : I.AttrKeys)
KeyArr.emplace_back(K);
for (const auto &V : I.AttrValues)
ValArr.emplace_back(V);
Child.insert({"Name", I.Name});
Child.insert({"SelfClosing", I.SelfClosing});
Child.insert({"AttrKeys", AttrKeysArray});
Child.insert({"AttrValues", AttrValuesArray});
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
return Obj;
}

case CommentKind::CK_HTMLEndTagComment: {
Child.insert({"Name", I.Name});
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
return Obj;
}

case CommentKind::CK_FullComment:
case CommentKind::CK_ParagraphComment: {
Child.insert({"Children", ChildArr});
Obj.insert({commentKindToString(I.Kind), ChildVal});
return Obj;
}

case CommentKind::CK_Unknown: {
Obj.insert({commentKindToString(I.Kind), I.Text});
return Obj;
}
}
llvm_unreachable("Unknown comment kind encountered.");
}

static void maybeInsertLocation(std::optional<Location> Loc,
Expand All @@ -255,6 +328,7 @@ static void extractDescriptionFromInfo(ArrayRef<CommentInfo> Descriptions,
return;
json::Value DescArr = Array();
json::Array &DescARef = *DescArr.getAsArray();
DescARef.reserve(Descriptions.size());
for (const CommentInfo &Child : Descriptions)
DescARef.emplace_back(extractValue(Child));
EnumValObj.insert({"EnumValueComments", DescArr});
Expand All @@ -270,6 +344,7 @@ static json::Value extractValue(const FunctionInfo &I, StringRef ParentInfoDir,

json::Value ParamArr = Array();
json::Array &ParamARef = *ParamArr.getAsArray();
ParamARef.reserve(I.Params.size());
for (const auto Val : enumerate(I.Params)) {
json::Value V = Object();
auto &VRef = *V.getAsObject();
Expand Down Expand Up @@ -297,6 +372,7 @@ static json::Value extractValue(const EnumInfo &I,
Obj.insert({"ID", toHex(toStringRef(I.USR))});
json::Value EnumArr = Array();
json::Array &EnumARef = *EnumArr.getAsArray();
EnumARef.reserve(I.Members.size());
for (const EnumValueInfo &M : I.Members) {
json::Value EnumValue = Object();
auto &EnumValObj = *EnumValue.getAsObject();
Expand All @@ -322,6 +398,7 @@ static void extractScopeChildren(const ScopeChildren &S, Object &Obj,
const ClangDocContext &CDCtx) {
json::Value NamespaceArr = Array();
json::Array &NamespaceARef = *NamespaceArr.getAsArray();
NamespaceARef.reserve(S.Namespaces.size());
for (const Reference &Child : S.Namespaces)
NamespaceARef.emplace_back(extractValue(Child, ParentInfoDir));

Expand All @@ -330,6 +407,7 @@ static void extractScopeChildren(const ScopeChildren &S, Object &Obj,

json::Value RecordArr = Array();
json::Array &RecordARef = *RecordArr.getAsArray();
RecordARef.reserve(S.Records.size());
for (const Reference &Child : S.Records)
RecordARef.emplace_back(extractValue(Child, ParentInfoDir));

Expand All @@ -338,12 +416,15 @@ static void extractScopeChildren(const ScopeChildren &S, Object &Obj,

json::Value FunctionArr = Array();
json::Array &FunctionARef = *FunctionArr.getAsArray();
FunctionARef.reserve(S.Functions.size());

json::Value PublicFunctionArr = Array();
json::Array &PublicFunctionARef = *PublicFunctionArr.getAsArray();
PublicFunctionARef.reserve(S.Functions.size());

json::Value ProtectedFunctionArr = Array();
json::Array &ProtectedFunctionARef = *ProtectedFunctionArr.getAsArray();
ProtectedFunctionARef.reserve(S.Functions.size());

for (const FunctionInfo &Child : S.Functions) {
json::Value F = extractValue(Child, ParentInfoDir, CDCtx);
Expand All @@ -367,6 +448,7 @@ static void extractScopeChildren(const ScopeChildren &S, Object &Obj,

json::Value EnumArr = Array();
auto &EnumARef = *EnumArr.getAsArray();
EnumARef.reserve(S.Enums.size());
for (const EnumInfo &Child : S.Enums)
EnumARef.emplace_back(extractValue(Child, CDCtx));

Expand All @@ -375,6 +457,7 @@ static void extractScopeChildren(const ScopeChildren &S, Object &Obj,

json::Value TypedefArr = Array();
auto &TypedefARef = *TypedefArr.getAsArray();
TypedefARef.reserve(S.Typedefs.size());
for (const TypedefInfo &Child : S.Typedefs)
TypedefARef.emplace_back(extractValue(Child));

Expand Down Expand Up @@ -411,10 +494,13 @@ static json::Value extractValue(const RecordInfo &I,
extractScopeChildren(I.Children, RecordValue, BasePath, CDCtx);
json::Value PublicMembers = Array();
json::Array &PubMemberRef = *PublicMembers.getAsArray();
PubMemberRef.reserve(I.Members.size());
json::Value ProtectedMembers = Array();
json::Array &ProtMemberRef = *ProtectedMembers.getAsArray();
ProtMemberRef.reserve(I.Members.size());
json::Value PrivateMembers = Array();
json::Array &PrivMemberRef = *PrivateMembers.getAsArray();
PrivMemberRef.reserve(I.Members.size());
for (const MemberTypeInfo &Member : I.Members) {
json::Value MemberValue = Object();
auto &MVRef = *MemberValue.getAsObject();
Expand Down Expand Up @@ -446,20 +532,25 @@ static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V,
auto InfoPath = I->getRelativeFilePath("");
SmallString<128> RelativePath = computeRelativePath("", InfoPath);
sys::path::native(RelativePath, sys::path::Style::posix);

auto *SSA = StylesheetArr.getAsArray();
SSA->reserve(CDCtx.UserStylesheets.size());
for (const auto &FilePath : CDCtx.UserStylesheets) {
SmallString<128> StylesheetPath = RelativePath;
sys::path::append(StylesheetPath, sys::path::Style::posix,
sys::path::filename(FilePath));
StylesheetArr.getAsArray()->emplace_back(StylesheetPath);
SSA->emplace_back(StylesheetPath);
}
V.getAsObject()->insert({"Stylesheets", StylesheetArr});

json::Value ScriptArr = Array();
auto *SCA = ScriptArr.getAsArray();
SCA->reserve(CDCtx.JsScripts.size());
for (auto Script : CDCtx.JsScripts) {
SmallString<128> JsPath = RelativePath;
sys::path::append(JsPath, sys::path::Style::posix,
sys::path::filename(Script));
ScriptArr.getAsArray()->emplace_back(JsPath);
SCA->emplace_back(JsPath);
}
V.getAsObject()->insert({"Scripts", ScriptArr});
return Error::success();
Expand Down
Loading