Comment to HTML conversion: refactor. Extracted a class to for FullComment

semantic parts -- this will be reused for comment to XML conversion.

llvm-svn: 161139
This commit is contained in:
Dmitri Gribenko 2012-08-01 22:48:16 +00:00
parent 2db6b65330
commit 3a770d0fe4
1 changed files with 137 additions and 122 deletions

View File

@ -396,6 +396,126 @@ public:
}
};
/// Separate parts of a FullComment.
struct FullCommentParts {
/// Take a full comment apart and initialize members accordingly.
FullCommentParts(const FullComment *C);
const BlockContentComment *Brief;
const ParagraphComment *FirstParagraph;
const BlockCommandComment *Returns;
SmallVector<const ParamCommandComment *, 8> Params;
SmallVector<const TParamCommandComment *, 4> TParams;
SmallVector<const BlockContentComment *, 8> MiscBlocks;
};
FullCommentParts::FullCommentParts(const FullComment *C) :
Brief(NULL), FirstParagraph(NULL), Returns(NULL) {
for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
I != E; ++I) {
const Comment *Child = *I;
if (!Child)
continue;
switch (Child->getCommentKind()) {
case Comment::NoCommentKind:
continue;
case Comment::ParagraphCommentKind: {
const ParagraphComment *PC = cast<ParagraphComment>(Child);
if (PC->isWhitespace())
break;
if (!FirstParagraph)
FirstParagraph = PC;
MiscBlocks.push_back(PC);
break;
}
case Comment::BlockCommandCommentKind: {
const BlockCommandComment *BCC = cast<BlockCommandComment>(Child);
StringRef CommandName = BCC->getCommandName();
if (!Brief && (CommandName == "brief" || CommandName == "short")) {
Brief = BCC;
break;
}
if (!Returns && (CommandName == "returns" || CommandName == "return")) {
Returns = BCC;
break;
}
MiscBlocks.push_back(BCC);
break;
}
case Comment::ParamCommandCommentKind: {
const ParamCommandComment *PCC = cast<ParamCommandComment>(Child);
if (!PCC->hasParamName())
break;
if (!PCC->isDirectionExplicit() && !PCC->hasNonWhitespaceParagraph())
break;
Params.push_back(PCC);
break;
}
case Comment::TParamCommandCommentKind: {
const TParamCommandComment *TPCC = cast<TParamCommandComment>(Child);
if (!TPCC->hasParamName())
break;
if (!TPCC->hasNonWhitespaceParagraph())
break;
TParams.push_back(TPCC);
break;
}
case Comment::VerbatimBlockCommentKind:
case Comment::VerbatimLineCommentKind:
MiscBlocks.push_back(cast<BlockCommandComment>(Child));
break;
case Comment::TextCommentKind:
case Comment::InlineCommandCommentKind:
case Comment::HTMLStartTagCommentKind:
case Comment::HTMLEndTagCommentKind:
case Comment::VerbatimBlockLineCommentKind:
case Comment::FullCommentKind:
llvm_unreachable("AST node of this kind can't be a child of "
"a FullComment");
}
}
// Sort params in order they are declared in the function prototype.
// Unresolved parameters are put at the end of the list in the same order
// they were seen in the comment.
std::stable_sort(Params.begin(), Params.end(),
ParamCommandCommentCompareIndex());
std::stable_sort(TParams.begin(), TParams.end(),
TParamCommandCommentComparePosition());
}
void PrintHTMLStartTagComment(const HTMLStartTagComment *C,
llvm::raw_svector_ostream &Result) {
Result << "<" << C->getTagName();
if (C->getNumAttrs() != 0) {
for (unsigned i = 0, e = C->getNumAttrs(); i != e; i++) {
Result << " ";
const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
Result << Attr.Name;
if (!Attr.Value.empty())
Result << "=\"" << Attr.Value << "\"";
}
}
if (!C->isSelfClosing())
Result << ">";
else
Result << "/>";
}
class CommentASTToHTMLConverter :
public ConstCommentVisitor<CommentASTToHTMLConverter> {
public:
@ -479,22 +599,7 @@ void CommentASTToHTMLConverter::visitInlineCommandComment(
void CommentASTToHTMLConverter::visitHTMLStartTagComment(
const HTMLStartTagComment *C) {
Result << "<" << C->getTagName();
if (C->getNumAttrs() != 0) {
for (unsigned i = 0, e = C->getNumAttrs(); i != e; i++) {
Result << " ";
const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
Result << Attr.Name;
if (!Attr.Value.empty())
Result << "=\"" << Attr.Value << "\"";
}
}
if (!C->isSelfClosing())
Result << ">";
else
Result << "/>";
PrintHTMLStartTagComment(C, Result);
}
void CommentASTToHTMLConverter::visitHTMLEndTagComment(
@ -616,131 +721,41 @@ void CommentASTToHTMLConverter::visitVerbatimLineComment(
}
void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) {
const BlockContentComment *Brief = NULL;
const ParagraphComment *FirstParagraph = NULL;
const BlockCommandComment *Returns = NULL;
SmallVector<const ParamCommandComment *, 8> Params;
SmallVector<const TParamCommandComment *, 4> TParams;
SmallVector<const BlockContentComment *, 8> MiscBlocks;
// Extract various blocks into separate variables and vectors above.
for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
I != E; ++I) {
const Comment *Child = *I;
if (!Child)
continue;
switch (Child->getCommentKind()) {
case Comment::NoCommentKind:
continue;
case Comment::ParagraphCommentKind: {
const ParagraphComment *PC = cast<ParagraphComment>(Child);
if (PC->isWhitespace())
break;
if (!FirstParagraph)
FirstParagraph = PC;
MiscBlocks.push_back(PC);
break;
}
case Comment::BlockCommandCommentKind: {
const BlockCommandComment *BCC = cast<BlockCommandComment>(Child);
StringRef CommandName = BCC->getCommandName();
if (!Brief && (CommandName == "brief" || CommandName == "short")) {
Brief = BCC;
break;
}
if (!Returns && (CommandName == "returns" || CommandName == "return")) {
Returns = BCC;
break;
}
MiscBlocks.push_back(BCC);
break;
}
case Comment::ParamCommandCommentKind: {
const ParamCommandComment *PCC = cast<ParamCommandComment>(Child);
if (!PCC->hasParamName())
break;
if (!PCC->isDirectionExplicit() && !PCC->hasNonWhitespaceParagraph())
break;
Params.push_back(PCC);
break;
}
case Comment::TParamCommandCommentKind: {
const TParamCommandComment *TPCC = cast<TParamCommandComment>(Child);
if (!TPCC->hasParamName())
break;
if (!TPCC->hasNonWhitespaceParagraph())
break;
TParams.push_back(TPCC);
break;
}
case Comment::VerbatimBlockCommentKind:
case Comment::VerbatimLineCommentKind:
MiscBlocks.push_back(cast<BlockCommandComment>(Child));
break;
case Comment::TextCommentKind:
case Comment::InlineCommandCommentKind:
case Comment::HTMLStartTagCommentKind:
case Comment::HTMLEndTagCommentKind:
case Comment::VerbatimBlockLineCommentKind:
case Comment::FullCommentKind:
llvm_unreachable("AST node of this kind can't be a child of "
"a FullComment");
}
}
// Sort params in order they are declared in the function prototype.
// Unresolved parameters are put at the end of the list in the same order
// they were seen in the comment.
std::stable_sort(Params.begin(), Params.end(),
ParamCommandCommentCompareIndex());
std::stable_sort(TParams.begin(), TParams.end(),
TParamCommandCommentComparePosition());
FullCommentParts Parts(C);
bool FirstParagraphIsBrief = false;
if (Brief)
visit(Brief);
else if (FirstParagraph) {
if (Parts.Brief)
visit(Parts.Brief);
else if (Parts.FirstParagraph) {
Result << "<p class=\"para-brief\">";
visitNonStandaloneParagraphComment(FirstParagraph);
visitNonStandaloneParagraphComment(Parts.FirstParagraph);
Result << "</p>";
FirstParagraphIsBrief = true;
}
for (unsigned i = 0, e = MiscBlocks.size(); i != e; ++i) {
const Comment *C = MiscBlocks[i];
if (FirstParagraphIsBrief && C == FirstParagraph)
for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
const Comment *C = Parts.MiscBlocks[i];
if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
continue;
visit(C);
}
if (TParams.size() != 0) {
if (Parts.TParams.size() != 0) {
Result << "<dl>";
for (unsigned i = 0, e = TParams.size(); i != e; ++i)
visit(TParams[i]);
for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
visit(Parts.TParams[i]);
Result << "</dl>";
}
if (Params.size() != 0) {
if (Parts.Params.size() != 0) {
Result << "<dl>";
for (unsigned i = 0, e = Params.size(); i != e; ++i)
visit(Params[i]);
for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
visit(Parts.Params[i]);
Result << "</dl>";
}
if (Returns)
visit(Returns);
if (Parts.Returns)
visit(Parts.Returns);
Result.flush();
}