Julie Hockett 671bac7436 [clang-doc] Add a structured HTML generator
Implements an HTML generator.
Nodes are used to represent each part of the HTML file. There are TagNodes that
represent every HTML tag (p, h1, div, ...) and they have children nodes, which
can be TagNodes or TextNodes (these nodes only have text).
Proper indentation is rendered within the files generated by tool.
No styling (CSS) is included.

Committed on behalf of Diego Astiazarán (diegoaat97@gmail.com)

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

llvm-svn: 365687
2019-07-10 19:03:25 +00:00

277 lines
6.9 KiB
C++

//===-- clang-doc/HTMLGeneratorTest.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "ClangDocTest.h"
#include "Generators.h"
#include "Representation.h"
#include "gtest/gtest.h"
namespace clang {
namespace doc {
std::unique_ptr<Generator> getHTMLGenerator() {
auto G = doc::findGeneratorByName("html");
if (!G)
return nullptr;
return std::move(G.get());
}
TEST(HTMLGeneratorTest, emitNamespaceHTML) {
NamespaceInfo I;
I.Name = "Namespace";
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.ChildNamespaces.emplace_back(EmptySID, "ChildNamespace",
InfoType::IT_namespace);
I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
I.ChildFunctions.emplace_back();
I.ChildFunctions.back().Name = "OneFunction";
I.ChildEnums.emplace_back();
I.ChildEnums.back().Name = "OneEnum";
auto G = getHTMLGenerator();
assert(G);
std::string Buffer;
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
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());
}
TEST(HTMLGeneratorTest, emitRecordHTML) {
RecordInfo I;
I.Name = "r";
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
I.Members.emplace_back("int", "X", AccessSpecifier::AS_private);
I.TagType = TagTypeKind::TTK_Class;
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
I.ChildFunctions.emplace_back();
I.ChildFunctions.back().Name = "OneFunction";
I.ChildEnums.emplace_back();
I.ChildEnums.back().Name = "OneEnum";
auto G = getHTMLGenerator();
assert(G);
std::string Buffer;
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
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());
}
TEST(HTMLGeneratorTest, emitFunctionHTML) {
FunctionInfo I;
I.Name = "f";
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
I.Params.emplace_back("int", "P");
I.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
auto G = getHTMLGenerator();
assert(G);
std::string Buffer;
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
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());
}
TEST(HTMLGeneratorTest, emitEnumHTML) {
EnumInfo I;
I.Name = "e";
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
I.Members.emplace_back("X");
I.Scoped = true;
auto G = getHTMLGenerator();
assert(G);
std::string Buffer;
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
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());
}
TEST(HTMLGeneratorTest, emitCommentHTML) {
FunctionInfo I;
I.Name = "f";
I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
I.Params.emplace_back("int", "I");
I.Params.emplace_back("int", "J");
CommentInfo Top;
Top.Kind = "FullComment";
Top.Children.emplace_back(llvm::make_unique<CommentInfo>());
CommentInfo *BlankLine = Top.Children.back().get();
BlankLine->Kind = "ParagraphComment";
BlankLine->Children.emplace_back(llvm::make_unique<CommentInfo>());
BlankLine->Children.back()->Kind = "TextComment";
Top.Children.emplace_back(llvm::make_unique<CommentInfo>());
CommentInfo *Brief = Top.Children.back().get();
Brief->Kind = "ParagraphComment";
Brief->Children.emplace_back(llvm::make_unique<CommentInfo>());
Brief->Children.back()->Kind = "TextComment";
Brief->Children.back()->Name = "ParagraphComment";
Brief->Children.back()->Text = " Brief description.";
Top.Children.emplace_back(llvm::make_unique<CommentInfo>());
CommentInfo *Extended = Top.Children.back().get();
Extended->Kind = "ParagraphComment";
Extended->Children.emplace_back(llvm::make_unique<CommentInfo>());
Extended->Children.back()->Kind = "TextComment";
Extended->Children.back()->Text = " Extended description that";
Extended->Children.emplace_back(llvm::make_unique<CommentInfo>());
Extended->Children.back()->Kind = "TextComment";
Extended->Children.back()->Text = " continues onto the next line.";
I.Description.emplace_back(std::move(Top));
auto G = getHTMLGenerator();
assert(G);
std::string Buffer;
llvm::raw_string_ostream Actual(Buffer);
auto Err = G->generateDocForInfo(&I, Actual);
assert(!Err);
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());
}
} // namespace doc
} // namespace clang