DiegoAstiazaran updated this revision to Diff 206920.
DiegoAstiazaran marked 7 inline comments as done.
DiegoAstiazaran added a comment.
Fix TagType enum name and members.
Add anonymous namespace.
Separate the implementation from the definition for some functions.
Use emplace_back instead of push_back for instantiation of vector members.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D63857/new/
https://reviews.llvm.org/D63857
Files:
clang-tools-extra/clang-doc/HTMLGenerator.cpp
clang-tools-extra/clang-doc/MDGenerator.cpp
clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
Index: clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
+++ clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
@@ -40,16 +40,31 @@
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
- std::string Expected = R"raw(<h1>namespace Namespace</h1>
-<h2>Namespaces</h2>
-<p>ChildNamespace</p>
-<h2>Records</h2>
-<p>ChildStruct</p>
-<h2>Functions</h2>
-<h3>OneFunction</h3>
-<p> OneFunction()</p>
-<h2>Enums</h2>
-<h3>enum OneEnum</h3>
+ std::string Expected = R"raw(<!DOCTYPE html>
+<meta charset="utf-8"/>
+<title>namespace Namespace</title>
+<div>
+ <h1>namespace Namespace</h1>
+ <h2>Namespaces</h2>
+ <ul>
+ <li>ChildNamespace</li>
+ </ul>
+ <h2>Records</h2>
+ <ul>
+ <li>ChildStruct</li>
+ </ul>
+ <h2>Functions</h2>
+ <div>
+ <h3>OneFunction</h3>
+ <p>
+ OneFunction()
+ </p>
+ </div>
+ <h2>Enums</h2>
+ <div>
+ <h3>enum OneEnum</h3>
+ </div>
+</div>
)raw";
EXPECT_EQ(Expected, Actual.str());
@@ -80,18 +95,37 @@
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
- std::string Expected = R"raw(<h1>class r</h1>
-<p>Defined at line 10 of test.cpp</p>
-<p>Inherits from F, G</p>
-<h2>Members</h2>
-<p>private int X</p>
-<h2>Records</h2>
-<p>ChildStruct</p>
-<h2>Functions</h2>
-<h3>OneFunction</h3>
-<p> OneFunction()</p>
-<h2>Enums</h2>
-<h3>enum OneEnum</h3>
+ std::string Expected = R"raw(<!DOCTYPE html>
+<meta charset="utf-8"/>
+<title>class r</title>
+<div>
+ <h1>class r</h1>
+ <p>
+ Defined at line 10 of test.cpp
+ </p>
+ <p>
+ Inherits from F, G
+ </p>
+ <h2>Members</h2>
+ <ul>
+ <li>private int X</li>
+ </ul>
+ <h2>Records</h2>
+ <ul>
+ <li>ChildStruct</li>
+ </ul>
+ <h2>Functions</h2>
+ <div>
+ <h3>OneFunction</h3>
+ <p>
+ OneFunction()
+ </p>
+ </div>
+ <h2>Enums</h2>
+ <div>
+ <h3>enum OneEnum</h3>
+ </div>
+</div>
)raw";
EXPECT_EQ(Expected, Actual.str());
@@ -116,9 +150,18 @@
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
- std::string Expected = R"raw(<h3>f</h3>
-<p>void f(int P)</p>
-<p>Defined at line 10 of test.cpp</p>
+ std::string Expected = R"raw(<!DOCTYPE html>
+<meta charset="utf-8"/>
+<title></title>
+<div>
+ <h3>f</h3>
+ <p>
+ void f(int P)
+ </p>
+ <p>
+ Defined at line 10 of test.cpp
+ </p>
+</div>
)raw";
EXPECT_EQ(Expected, Actual.str());
@@ -141,11 +184,18 @@
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
- std::string Expected = R"raw(<h3>enum class e</h3>
-<ul>
-<li>X</li>
-</ul>
-<p>Defined at line 10 of test.cpp</p>
+ std::string Expected = R"raw(<!DOCTYPE html>
+<meta charset="utf-8"/>
+<title></title>
+<div>
+ <h3>enum class e</h3>
+ <ul>
+ <li>X</li>
+ </ul>
+ <p>
+ Defined at line 10 of test.cpp
+ </p>
+</div>
)raw";
EXPECT_EQ(Expected, Actual.str());
@@ -194,12 +244,29 @@
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
- std::string Expected = R"raw(<h3>f</h3>
-<p>void f(int I, int J)</p>
-<p>Defined at line 10 of test.cpp</p>
-<p></p>
-<p> Brief description.</p>
-<p> Extended description that continues onto the next line.</p>
+ std::string Expected = R"raw(<!DOCTYPE html>
+<meta charset="utf-8"/>
+<title></title>
+<div>
+ <h3>f</h3>
+ <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>
+ </div>
+ </div>
+</div>
)raw";
EXPECT_EQ(Expected, Actual.str());
Index: clang-tools-extra/clang-doc/MDGenerator.cpp
===================================================================
--- clang-tools-extra/clang-doc/MDGenerator.cpp
+++ clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -20,11 +20,11 @@
// Markdown generation
-std::string genItalic(const Twine &Text) { return "*" + Text.str() + "*"; }
+static std::string genItalic(const Twine &Text) { return "*" + Text.str() + "*"; }
-std::string genEmphasis(const Twine &Text) { return "**" + Text.str() + "**"; }
+static std::string genEmphasis(const Twine &Text) { return "**" + Text.str() + "**"; }
-std::string genLink(const Twine &Text, const Twine &Link) {
+static std::string genLink(const Twine &Text, const Twine &Link) {
return "[" + Text.str() + "](" + Link.str() + ")";
}
@@ -92,7 +92,7 @@
}
}
-void genMarkdown(const EnumInfo &I, llvm::raw_ostream &OS) {
+static void genMarkdown(const EnumInfo &I, llvm::raw_ostream &OS) {
if (I.Scoped)
writeLine("| enum class " + I.Name + " |", OS);
else
@@ -112,7 +112,7 @@
writeDescription(C, OS);
}
-void genMarkdown(const FunctionInfo &I, llvm::raw_ostream &OS) {
+static void genMarkdown(const FunctionInfo &I, llvm::raw_ostream &OS) {
std::string Buffer;
llvm::raw_string_ostream Stream(Buffer);
bool First = true;
@@ -139,7 +139,7 @@
writeDescription(C, OS);
}
-void genMarkdown(const NamespaceInfo &I, llvm::raw_ostream &OS) {
+static void genMarkdown(const NamespaceInfo &I, llvm::raw_ostream &OS) {
if (I.Name == "")
writeHeader("Global Namespace", 1, OS);
else
@@ -178,7 +178,7 @@
}
}
-void genMarkdown(const RecordInfo &I, llvm::raw_ostream &OS) {
+static void genMarkdown(const RecordInfo &I, llvm::raw_ostream &OS) {
writeHeader(getTagType(I.TagType) + " " + I.Name, 1, OS);
if (I.DefLoc)
writeFileDefinition(I.DefLoc.getValue(), OS);
Index: clang-tools-extra/clang-doc/HTMLGenerator.cpp
===================================================================
--- clang-tools-extra/clang-doc/HTMLGenerator.cpp
+++ clang-tools-extra/clang-doc/HTMLGenerator.cpp
@@ -18,67 +18,300 @@
namespace clang {
namespace doc {
+namespace {
+
+class HTMLTag {
+public:
+ // Any other tag can be added if required
+ enum TagType {
+ TAG_META,
+ TAG_TITLE,
+ TAG_DIV,
+ TAG_H1,
+ TAG_H2,
+ TAG_H3,
+ TAG_P,
+ TAG_UL,
+ TAG_LI,
+ };
+
+ HTMLTag() = default;
+ constexpr HTMLTag(TagType Value) : Value(Value) {}
+
+ operator TagType() const { return Value; }
+ operator bool() = delete;
+
+ bool IsSelfClosing() const;
+
+ bool HasInlineChildren() const;
+
+ llvm::SmallString<16> ToString() const;
+
+private:
+ TagType Value;
+};
+
+struct HTMLNode {
+ virtual ~HTMLNode() = default;
+
+ virtual void Render(llvm::raw_ostream &OS, int IndentationLevel) = 0;
+};
+
+struct TextNode : public HTMLNode {
+ TextNode(llvm::StringRef Text, bool Indented)
+ : Text(Text), Indented(Indented) {}
+
+ 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)
+ : Tag(Tag), InlineChildren(Tag.HasInlineChildren()),
+ SelfClosing(Tag.IsSelfClosing()) {}
+ TagNode(HTMLTag Tag, const Twine &Text) : TagNode(Tag) {
+ Children.emplace_back(
+ llvm::make_unique<TextNode>(Text.str(), !InlineChildren));
+ }
+
+ 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
+ std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
+ llvm::StringMap<llvm::SmallString<16>>
+ Attributes; // List of key-value attributes for tag
+
+ void Render(llvm::raw_ostream &OS, int IndentationLevel) override;
+};
+
+struct HTMLFile {
+ llvm::SmallString<16> DoctypeDecl{"<!DOCTYPE html>"};
+ std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
+ void Render(llvm::raw_ostream &OS) {
+ OS << DoctypeDecl << "\n";
+ for (const auto &C : Children) {
+ C->Render(OS, 0);
+ OS << "\n";
+ }
+ }
+};
+
+} // namespace
+
+bool HTMLTag::IsSelfClosing() const {
+ switch (Value) {
+ case HTMLTag::TAG_META:
+ return true;
+ case HTMLTag::TAG_TITLE:
+ case HTMLTag::TAG_DIV:
+ case HTMLTag::TAG_H1:
+ case HTMLTag::TAG_H2:
+ case HTMLTag::TAG_H3:
+ case HTMLTag::TAG_P:
+ case HTMLTag::TAG_UL:
+ case HTMLTag::TAG_LI:
+ return false;
+ }
+}
+
+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:
+ return true;
+ case HTMLTag::TAG_DIV:
+ case HTMLTag::TAG_P:
+ case HTMLTag::TAG_UL:
+ return false;
+ }
+}
+
+llvm::SmallString<16> HTMLTag::ToString() const {
+ switch (Value) {
+ case HTMLTag::TAG_META:
+ return llvm::SmallString<16>("meta");
+ case HTMLTag::TAG_TITLE:
+ return llvm::SmallString<16>("title");
+ case HTMLTag::TAG_DIV:
+ return llvm::SmallString<16>("div");
+ case HTMLTag::TAG_H1:
+ return llvm::SmallString<16>("h1");
+ case HTMLTag::TAG_H2:
+ return llvm::SmallString<16>("h2");
+ case HTMLTag::TAG_H3:
+ return llvm::SmallString<16>("h3");
+ case HTMLTag::TAG_P:
+ return llvm::SmallString<16>("p");
+ case HTMLTag::TAG_UL:
+ return llvm::SmallString<16>("ul");
+ case HTMLTag::TAG_LI:
+ return llvm::SmallString<16>("li");
+ }
+}
+
+void TextNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
+ if (Indented)
+ OS.indent(IndentationLevel * 2);
+ OS << Text;
+}
+
+void TagNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
+ OS.indent(IndentationLevel * 2);
+ OS << "<" << Tag.ToString();
+ for (const auto &A : Attributes)
+ OS << " " << A.getKey() << "=\"" << A.getValue() << "\"";
+ OS << (SelfClosing ? "/>" : ">");
+ if (!InlineChildren)
+ OS << "\n";
+ int ChildrenIndentation = InlineChildren ? 0 : IndentationLevel + 1;
+ for (const auto &C : Children) {
+ C->Render(OS, ChildrenIndentation);
+ if (!InlineChildren)
+ OS << "\n";
+ }
+ if (!InlineChildren)
+ OS.indent(IndentationLevel * 2);
+ if (!SelfClosing)
+ OS << "</" << Tag.ToString() << ">";
+}
+
// HTML generation
-std::string genTag(const Twine &Text, const Twine &Tag) {
- return "<" + Tag.str() + ">" + Text.str() + "</" + Tag.str() + ">";
+static void genHTML(const EnumInfo &I, TagNode *N);
+static void genHTML(const FunctionInfo &I, TagNode *N);
+
+static void genEnumsBlock(const std::vector<EnumInfo> &Enums, TagNode *N) {
+ if (Enums.empty())
+ return;
+
+ N->Children.emplace_back(
+ llvm::make_unique<TagNode>(HTMLTag::TAG_H2, "Enums"));
+
+ auto EnumsBlock = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
+ for (const auto &E : Enums)
+ genHTML(E, EnumsBlock.get());
+ N->Children.push_back(std::move(EnumsBlock));
}
-static void writeLine(const Twine &Text, raw_ostream &OS) {
- OS << genTag(Text, "p") << "\n";
+static void
+genEnumMembersBlock(const llvm::SmallVector<SmallString<16>, 4> &Members,
+ TagNode *N) {
+ if (Members.empty())
+ return;
+ auto List = llvm::make_unique<TagNode>(HTMLTag::TAG_UL);
+ for (const auto &M : Members)
+ List->Children.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_LI, M));
+ N->Children.push_back(std::move(List));
}
-static void writeHeader(const Twine &Text, const Twine &Num, raw_ostream &OS) {
- OS << genTag(Text, "h" + Num) << "\n";
+static void genFunctionsBlock(const std::vector<FunctionInfo> &Functions,
+ TagNode *N) {
+ if (Functions.empty())
+ return;
+
+ N->Children.emplace_back(
+ llvm::make_unique<TagNode>(HTMLTag::TAG_H2, "Functions"));
+
+ auto FunctionsBlock = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
+ for (const auto &F : Functions)
+ genHTML(F, FunctionsBlock.get());
+ N->Children.push_back(std::move(FunctionsBlock));
}
-static void writeFileDefinition(const Location &L, raw_ostream &OS) {
- writeLine("Defined at line " + std::to_string(L.LineNumber) + " of " +
- L.Filename,
- OS);
+static void
+genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members,
+ TagNode *N) {
+ if (Members.empty())
+ return;
+
+ N->Children.emplace_back(
+ llvm::make_unique<TagNode>(HTMLTag::TAG_H2, "Members"));
+
+ auto List = llvm::make_unique<TagNode>(HTMLTag::TAG_UL);
+ for (const auto &M : Members) {
+ std::string Access = getAccess(M.Access);
+ if (Access != "")
+ Access = Access + " ";
+ List->Children.emplace_back(llvm::make_unique<TagNode>(
+ HTMLTag::TAG_LI, Access + M.Type.Name + " " + M.Name));
+ }
+ N->Children.push_back(std::move(List));
}
-static void writeDescription(const CommentInfo &I, raw_ostream &OS) {
+static void genReferencesBlock(const std::vector<Reference> &References,
+ llvm::StringRef Title, TagNode *N) {
+ if (References.empty())
+ return;
+
+ N->Children.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H2, Title));
+
+ auto List = llvm::make_unique<TagNode>(HTMLTag::TAG_UL);
+ for (const auto &R : References)
+ List->Children.emplace_back(
+ llvm::make_unique<TagNode>(HTMLTag::TAG_LI, R.Name));
+ N->Children.push_back(std::move(List));
+}
+
+static void writeFileDefinition(const Location &L, TagNode *N) {
+ N->Children.emplace_back(llvm::make_unique<TagNode>(
+ HTMLTag::TAG_P,
+ "Defined at line " + std::to_string(L.LineNumber) + " of " + L.Filename));
+}
+
+static void genHTML(const CommentInfo &I, TagNode *N) {
if (I.Kind == "FullComment") {
+ auto FullComment = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
for (const auto &Child : I.Children)
- writeDescription(*Child, OS);
+ genHTML(*Child, FullComment.get());
+ N->Children.push_back(std::move(FullComment));
} else if (I.Kind == "ParagraphComment") {
- OS << "<p>";
+ auto ParagraphComment = llvm::make_unique<TagNode>(HTMLTag::TAG_P);
for (const auto &Child : I.Children)
- writeDescription(*Child, OS);
- OS << "</p>\n";
+ genHTML(*Child, ParagraphComment.get());
+ if (!ParagraphComment->Children.empty())
+ N->Children.push_back(std::move(ParagraphComment));
} else if (I.Kind == "TextComment") {
if (I.Text != "")
- OS << I.Text;
+ N->Children.emplace_back(llvm::make_unique<TextNode>(I.Text, true));
}
}
-void genHTML(const EnumInfo &I, llvm::raw_ostream &OS) {
+static void genHTML(const std::vector<CommentInfo> &C, TagNode *N) {
+ auto CommentBlock = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
+ for (const auto &Child : C)
+ genHTML(Child, CommentBlock.get());
+ N->Children.push_back(std::move(CommentBlock));
+}
+
+static void genHTML(const EnumInfo &I, TagNode *N) {
std::string EnumType;
if (I.Scoped)
EnumType = "enum class ";
else
EnumType = "enum ";
- writeHeader(EnumType + I.Name, "3", OS);
- std::string Buffer;
- llvm::raw_string_ostream Members(Buffer);
- if (!I.Members.empty()) {
- Members << "\n";
- for (const auto &N : I.Members)
- Members << genTag(N, "li") << "\n";
- OS << genTag(Members.str(), "ul") << "\n";
- }
+ N->Children.emplace_back(
+ llvm::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.Name));
+
+ genEnumMembersBlock(I.Members, N);
if (I.DefLoc)
- writeFileDefinition(I.DefLoc.getValue(), OS);
+ writeFileDefinition(I.DefLoc.getValue(), N);
- for (const auto &C : I.Description)
- writeDescription(C, OS);
+ std::string Description;
+ if (!I.Description.empty())
+ genHTML(I.Description, N);
}
-void genHTML(const FunctionInfo &I, llvm::raw_ostream &OS) {
- writeHeader(I.Name, "3", OS);
+static void genHTML(const FunctionInfo &I, TagNode *N) {
+ N->Children.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name));
std::string Buffer;
llvm::raw_string_ostream Stream(Buffer);
@@ -87,101 +320,75 @@
Stream << ", ";
Stream << P.Type.Name + " " + P.Name;
}
+
std::string Access = getAccess(I.Access);
if (Access != "")
- writeLine(Access + " " + I.ReturnType.Type.Name + " " + I.Name + "(" +
- Stream.str() + ")",
- OS);
- else
- writeLine(I.ReturnType.Type.Name + " " + I.Name + "(" + Stream.str() + ")",
- OS);
+ Access = Access + " ";
+
+ N->Children.emplace_back(llvm::make_unique<TagNode>(
+ HTMLTag::TAG_P, Access + I.ReturnType.Type.Name + " " + I.Name + "(" +
+ Stream.str() + ")"));
+
if (I.DefLoc)
- writeFileDefinition(I.DefLoc.getValue(), OS);
+ writeFileDefinition(I.DefLoc.getValue(), N);
- for (const auto &C : I.Description)
- writeDescription(C, OS);
+ std::string Description;
+ if (!I.Description.empty())
+ genHTML(I.Description, N);
}
-void genHTML(const NamespaceInfo &I, llvm::raw_ostream &OS) {
- if (I.Name == "")
- writeHeader("Global Namespace", "1", OS);
+static void genHTML(const NamespaceInfo &I, TagNode *N,
+ std::string &InfoTitle) {
+ if (I.Name.str() == "")
+ InfoTitle = "Global Namespace";
else
- writeHeader("namespace " + I.Name, "1", OS);
+ InfoTitle = ("namespace " + I.Name).str();
- if (!I.Description.empty()) {
- for (const auto &C : I.Description)
- writeDescription(C, OS);
- }
+ N->Children.emplace_back(
+ llvm::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
- if (!I.ChildNamespaces.empty()) {
- writeHeader("Namespaces", "2", OS);
- for (const auto &R : I.ChildNamespaces)
- writeLine(R.Name, OS);
- }
- if (!I.ChildRecords.empty()) {
- writeHeader("Records", "2", OS);
- for (const auto &R : I.ChildRecords)
- writeLine(R.Name, OS);
- }
- if (!I.ChildFunctions.empty()) {
- writeHeader("Functions", "2", OS);
- for (const auto &F : I.ChildFunctions)
- genHTML(F, OS);
- }
- if (!I.ChildEnums.empty()) {
- writeHeader("Enums", "2", OS);
- for (const auto &E : I.ChildEnums)
- genHTML(E, OS);
- }
+ std::string Description;
+ if (!I.Description.empty())
+ genHTML(I.Description, N);
+
+ genReferencesBlock(I.ChildNamespaces, "Namespaces", N);
+ genReferencesBlock(I.ChildRecords, "Records", N);
+
+ genFunctionsBlock(I.ChildFunctions, N);
+ genEnumsBlock(I.ChildEnums, N);
}
-void genHTML(const RecordInfo &I, llvm::raw_ostream &OS) {
- writeHeader(getTagType(I.TagType) + " " + I.Name, "1", OS);
+static void genHTML(const RecordInfo &I, TagNode *N, std::string &InfoTitle) {
+ InfoTitle = (getTagType(I.TagType) + " " + I.Name).str();
+ N->Children.emplace_back(
+ llvm::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
+
if (I.DefLoc)
- writeFileDefinition(I.DefLoc.getValue(), OS);
+ writeFileDefinition(I.DefLoc.getValue(), N);
- if (!I.Description.empty()) {
- for (const auto &C : I.Description)
- writeDescription(C, OS);
- }
+ std::string Description;
+ if (!I.Description.empty())
+ genHTML(I.Description, N);
std::string Parents = genReferenceList(I.Parents);
std::string VParents = genReferenceList(I.VirtualParents);
if (!Parents.empty() || !VParents.empty()) {
if (Parents.empty())
- writeLine("Inherits from " + VParents, OS);
+ N->Children.emplace_back(llvm::make_unique<TagNode>(
+ HTMLTag::TAG_P, "Inherits from " + VParents));
else if (VParents.empty())
- writeLine("Inherits from " + Parents, OS);
+ N->Children.emplace_back(llvm::make_unique<TagNode>(
+ HTMLTag::TAG_P, "Inherits from " + Parents));
else
- writeLine("Inherits from " + Parents + ", " + VParents, OS);
+ N->Children.emplace_back(llvm::make_unique<TagNode>(
+ HTMLTag::TAG_P, "Inherits from " + Parents + ", " + VParents));
}
- if (!I.Members.empty()) {
- writeHeader("Members", "2", OS);
- for (const auto Member : I.Members) {
- std::string Access = getAccess(Member.Access);
- if (Access != "")
- writeLine(Access + " " + Member.Type.Name + " " + Member.Name, OS);
- else
- writeLine(Member.Type.Name + " " + Member.Name, OS);
- }
- }
+ genRecordMembersBlock(I.Members, N);
+ genReferencesBlock(I.ChildRecords, "Records", N);
- if (!I.ChildRecords.empty()) {
- writeHeader("Records", "2", OS);
- for (const auto &R : I.ChildRecords)
- writeLine(R.Name, OS);
- }
- if (!I.ChildFunctions.empty()) {
- writeHeader("Functions", "2", OS);
- for (const auto &F : I.ChildFunctions)
- genHTML(F, OS);
- }
- if (!I.ChildEnums.empty()) {
- writeHeader("Enums", "2", OS);
- for (const auto &E : I.ChildEnums)
- genHTML(E, OS);
- }
+ genFunctionsBlock(I.ChildFunctions, N);
+ genEnumsBlock(I.ChildEnums, N);
}
/// Generator for HTML documentation.
@@ -195,31 +402,50 @@
const char *HTMLGenerator::Format = "html";
llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS) {
+ HTMLFile F;
+
+ auto MetaNode = llvm::make_unique<TagNode>(HTMLTag::TAG_META);
+ MetaNode->Attributes.try_emplace("charset", "utf-8");
+ F.Children.push_back(std::move(MetaNode));
+
+ std::string InfoTitle;
+
+ auto MainContentNode = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
+
switch (I->IT) {
case InfoType::IT_namespace:
- genHTML(*static_cast<clang::doc::NamespaceInfo *>(I), OS);
+ genHTML(*static_cast<clang::doc::NamespaceInfo *>(I), MainContentNode.get(),
+ InfoTitle);
break;
case InfoType::IT_record:
- genHTML(*static_cast<clang::doc::RecordInfo *>(I), OS);
+ genHTML(*static_cast<clang::doc::RecordInfo *>(I), MainContentNode.get(),
+ InfoTitle);
break;
case InfoType::IT_enum:
- genHTML(*static_cast<clang::doc::EnumInfo *>(I), OS);
+ genHTML(*static_cast<clang::doc::EnumInfo *>(I), MainContentNode.get());
break;
case InfoType::IT_function:
- genHTML(*static_cast<clang::doc::FunctionInfo *>(I), OS);
+ genHTML(*static_cast<clang::doc::FunctionInfo *>(I), MainContentNode.get());
break;
case InfoType::IT_default:
return llvm::make_error<llvm::StringError>("Unexpected info type.\n",
llvm::inconvertibleErrorCode());
}
+
+ F.Children.emplace_back(
+ llvm::make_unique<TagNode>(HTMLTag::TAG_TITLE, InfoTitle));
+ F.Children.push_back(std::move(MainContentNode));
+
+ F.Render(OS);
+
return llvm::Error::success();
}
static GeneratorRegistry::Add<HTMLGenerator> HTML(HTMLGenerator::Format,
"Generator for HTML output.");
-// This anchor is used to force the linker to link in the generated object file
-// and thus register the generator.
+// This anchor is used to force the linker to link in the generated object
+// file and thus register the generator.
volatile int HTMLGeneratorAnchorSource = 0;
} // namespace doc
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits