Skip to content

Commit

Permalink
[clang-doc] Fix output format of html
Browse files Browse the repository at this point in the history
The children of a TagNode are rendered in the same line as the parent only if they are all TextNodes.
When children are not inline; two text nodes that are adjacent won't have a new line between them, each tag node is rendered in its own line.

Differential Revision: https://reviews.llvm.org/D65005

llvm-svn: 367050
  • Loading branch information
DiegoAstiazaran committed Jul 25, 2019
1 parent c74808b commit 64ca857
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 71 deletions.
54 changes: 15 additions & 39 deletions clang-tools-extra/clang-doc/HTMLGenerator.cpp
Expand Up @@ -44,9 +44,6 @@ class HTMLTag {
operator bool() = delete;

bool IsSelfClosing() const;

bool HasInlineChildren() const;

llvm::SmallString<16> ToString() const;

private:
Expand All @@ -67,29 +64,20 @@ struct HTMLNode {
};

struct TextNode : public HTMLNode {
TextNode(const Twine &Text, bool Indented = true)
: HTMLNode(NodeType::NODE_TEXT), Text(Text.str()), Indented(Indented) {}
TextNode(const Twine &Text)
: HTMLNode(NodeType::NODE_TEXT), Text(Text.str()) {}

std::string Text; // Content of node
bool Indented; // Indicates if an indentation must be rendered before the text
void Render(llvm::raw_ostream &OS, int IndentationLevel) override;
};

struct TagNode : public HTMLNode {
TagNode(HTMLTag Tag)
: HTMLNode(NodeType::NODE_TAG), Tag(Tag),
InlineChildren(Tag.HasInlineChildren()),
SelfClosing(Tag.IsSelfClosing()) {}
TagNode(HTMLTag Tag) : HTMLNode(NodeType::NODE_TAG), Tag(Tag) {}
TagNode(HTMLTag Tag, const Twine &Text) : TagNode(Tag) {
Children.emplace_back(
llvm::make_unique<TextNode>(Text.str(), !InlineChildren));
Children.emplace_back(llvm::make_unique<TextNode>(Text.str()));
}

HTMLTag Tag; // Name of HTML Tag (p, div, h1)
bool InlineChildren; // Indicates if children nodes are rendered in the same
// line as itself or if children must rendered in the
// next line and with additional indentation
bool SelfClosing; // Indicates if tag is self-closing
HTMLTag Tag; // Name of HTML Tag (p, div, h1)
std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
llvm::StringMap<llvm::SmallString<16>>
Attributes; // List of key-value attributes for tag
Expand Down Expand Up @@ -130,24 +118,6 @@ bool HTMLTag::IsSelfClosing() const {
llvm_unreachable("Unhandled HTMLTag::TagType");
}

bool HTMLTag::HasInlineChildren() const {
switch (Value) {
case HTMLTag::TAG_META:
case HTMLTag::TAG_TITLE:
case HTMLTag::TAG_H1:
case HTMLTag::TAG_H2:
case HTMLTag::TAG_H3:
case HTMLTag::TAG_LI:
case HTMLTag::TAG_A:
return true;
case HTMLTag::TAG_DIV:
case HTMLTag::TAG_P:
case HTMLTag::TAG_UL:
return false;
}
llvm_unreachable("Unhandled HTMLTag::TagType");
}

llvm::SmallString<16> HTMLTag::ToString() const {
switch (Value) {
case HTMLTag::TAG_META:
Expand Down Expand Up @@ -175,17 +145,23 @@ llvm::SmallString<16> HTMLTag::ToString() const {
}

void TextNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
if (Indented)
OS.indent(IndentationLevel * 2);
OS.indent(IndentationLevel * 2);
printHTMLEscaped(Text, OS);
}

void TagNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
// Children nodes are rendered in the same line if all of them are text nodes
bool InlineChildren = true;
for (const auto &C : Children)
if (C->Type == NodeType::NODE_TAG) {
InlineChildren = false;
break;
}
OS.indent(IndentationLevel * 2);
OS << "<" << Tag.ToString();
for (const auto &A : Attributes)
OS << " " << A.getKey() << "=\"" << A.getValue() << "\"";
if (SelfClosing) {
if (Tag.IsSelfClosing()) {
OS << "/>";
return;
}
Expand Down Expand Up @@ -385,7 +361,7 @@ static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
} else if (I.Kind == "TextComment") {
if (I.Text == "")
return nullptr;
return llvm::make_unique<TextNode>(I.Text, true);
return llvm::make_unique<TextNode>(I.Text);
}
return nullptr;
}
Expand Down
48 changes: 16 additions & 32 deletions clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
Expand Up @@ -56,9 +56,7 @@ TEST(HTMLGeneratorTest, emitNamespaceHTML) {
<h2>Functions</h2>
<div>
<h3>OneFunction</h3>
<p>
OneFunction()
</p>
<p>OneFunction()</p>
</div>
<h2>Enums</h2>
<div>
Expand Down Expand Up @@ -107,9 +105,7 @@ TEST(HTMLGeneratorTest, emitRecordHTML) {
<title>class r</title>
<div>
<h1>class r</h1>
<p>
Defined at line 10 of test.cpp
</p>
<p>Defined at line 10 of test.cpp</p>
<p>
Inherits from
<a href=")raw" + std::string(PathToF.str()) +
Expand All @@ -118,8 +114,12 @@ TEST(HTMLGeneratorTest, emitRecordHTML) {
</p>
<h2>Members</h2>
<ul>
<li>private <a href=")raw" +
std::string(PathToInt.str()) + R"raw(">int</a> X</li>
<li>
private
<a href=")raw" + std::string(PathToInt.str()) +
R"raw(">int</a>
X
</li>
</ul>
<h2>Records</h2>
<ul>
Expand All @@ -128,9 +128,7 @@ TEST(HTMLGeneratorTest, emitRecordHTML) {
<h2>Functions</h2>
<div>
<h3>OneFunction</h3>
<p>
OneFunction()
</p>
<p>OneFunction()</p>
</div>
<h2>Enums</h2>
<div>
Expand Down Expand Up @@ -180,9 +178,7 @@ TEST(HTMLGeneratorTest, emitFunctionHTML) {
R"raw(">int</a>
P)
</p>
<p>
Defined at line 10 of test.cpp
</p>
<p>Defined at line 10 of test.cpp</p>
</div>
)raw";

Expand Down Expand Up @@ -214,9 +210,7 @@ TEST(HTMLGeneratorTest, emitEnumHTML) {
<ul>
<li>X</li>
</ul>
<p>
Defined at line 10 of test.cpp
</p>
<p>Defined at line 10 of test.cpp</p>
</div>
)raw";

Expand Down Expand Up @@ -280,23 +274,13 @@ TEST(HTMLGeneratorTest, emitCommentHTML) {
<title></title>
<div>
<h3>f</h3>
<p>
void f(int I, int J)
</p>
<p>
Defined at line 10 of test.cpp
</p>
<p>void f(int I, int J)</p>
<p>Defined at line 10 of test.cpp</p>
<div>
<div>
<p>
Brief description.
</p>
<p>
Extended description that continues onto the next line.
</p>
<p>
Comment with html entities: &amp;, &lt;, &gt;, &quot;, &apos;.
</p>
<p> Brief description.</p>
<p> Extended description that continues onto the next line.</p>
<p> Comment with html entities: &amp;, &lt;, &gt;, &quot;, &apos;.</p>
</div>
</div>
</div>
Expand Down

0 comments on commit 64ca857

Please sign in to comment.