forked from OSchip/llvm-project
[clang-doc] Add second index for sections within info's content
This new index contains links to the main section of infos: Namespaces, Records, Functions, Enums, Members. Also to each child function or enum. Index is currently rendered on top of the info content, this will be fixed later with CSS. Depends on D65690. Differential Revision: https://reviews.llvm.org/D65030 llvm-svn: 368209
This commit is contained in:
parent
333f14d52d
commit
d47be4da5a
|
@ -270,15 +270,22 @@ static std::unique_ptr<TagNode> genLink(const Twine &Text, const Twine &Link) {
|
|||
return LinkNode;
|
||||
}
|
||||
|
||||
static std::unique_ptr<HTMLNode> genTypeReference(const Reference &Type,
|
||||
StringRef CurrentDirectory) {
|
||||
if (Type.Path.empty() && !Type.IsInGlobalNamespace)
|
||||
return llvm::make_unique<TextNode>(Type.Name);
|
||||
static std::unique_ptr<HTMLNode>
|
||||
genTypeReference(const Reference &Type, StringRef CurrentDirectory,
|
||||
llvm::Optional<StringRef> JumpToSection = None) {
|
||||
if (Type.Path.empty() && !Type.IsInGlobalNamespace) {
|
||||
if (!JumpToSection)
|
||||
return llvm::make_unique<TextNode>(Type.Name);
|
||||
else
|
||||
return genLink(Type.Name, "#" + JumpToSection.getValue());
|
||||
}
|
||||
llvm::SmallString<128> Path =
|
||||
computeRelativePath(Type.Path, CurrentDirectory);
|
||||
llvm::sys::path::append(Path, Type.Name + ".html");
|
||||
// Paths in HTML must be in posix-style
|
||||
llvm::sys::path::native(Path, llvm::sys::path::Style::posix);
|
||||
if (JumpToSection)
|
||||
Path += ("#" + JumpToSection.getValue()).str();
|
||||
return genLink(Type.Name, Path);
|
||||
}
|
||||
|
||||
|
@ -305,6 +312,7 @@ genEnumsBlock(const std::vector<EnumInfo> &Enums) {
|
|||
|
||||
std::vector<std::unique_ptr<TagNode>> Out;
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H2, "Enums"));
|
||||
Out.back()->Attributes.try_emplace("id", "Enums");
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_DIV));
|
||||
auto &DivBody = Out.back();
|
||||
for (const auto &E : Enums) {
|
||||
|
@ -333,6 +341,7 @@ genFunctionsBlock(const std::vector<FunctionInfo> &Functions,
|
|||
|
||||
std::vector<std::unique_ptr<TagNode>> Out;
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H2, "Functions"));
|
||||
Out.back()->Attributes.try_emplace("id", "Functions");
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_DIV));
|
||||
auto &DivBody = Out.back();
|
||||
for (const auto &F : Functions) {
|
||||
|
@ -350,6 +359,7 @@ genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members,
|
|||
|
||||
std::vector<std::unique_ptr<TagNode>> Out;
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H2, "Members"));
|
||||
Out.back()->Attributes.try_emplace("id", "Members");
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_UL));
|
||||
auto &ULBody = Out.back();
|
||||
for (const auto &M : Members) {
|
||||
|
@ -373,6 +383,7 @@ genReferencesBlock(const std::vector<Reference> &References,
|
|||
|
||||
std::vector<std::unique_ptr<TagNode>> Out;
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H2, Title));
|
||||
Out.back()->Attributes.try_emplace("id", Title);
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_UL));
|
||||
auto &ULBody = Out.back();
|
||||
for (const auto &R : References)
|
||||
|
@ -409,6 +420,41 @@ genCommonFileNodes(StringRef Title, StringRef InfoPath,
|
|||
return Out;
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
typename = std::enable_if<std::is_base_of<T, Info>::value>>
|
||||
static Index genInfoIndexItem(const std::vector<T> &Infos, StringRef Title) {
|
||||
Index Idx(Title, Title);
|
||||
for (const auto &C : Infos)
|
||||
Idx.Children.emplace_back(C.extractName(),
|
||||
llvm::toHex(llvm::toStringRef(C.USR)));
|
||||
return Idx;
|
||||
}
|
||||
|
||||
static std::vector<std::unique_ptr<TagNode>> genHTML(const Index &Index,
|
||||
StringRef InfoPath) {
|
||||
std::vector<std::unique_ptr<TagNode>> Out;
|
||||
if (!Index.Name.empty()) {
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_SPAN));
|
||||
auto &SpanBody = Out.back();
|
||||
if (!Index.JumpToSection)
|
||||
SpanBody->Children.emplace_back(genTypeReference(Index, InfoPath));
|
||||
else
|
||||
SpanBody->Children.emplace_back(genTypeReference(
|
||||
Index, InfoPath, StringRef{Index.JumpToSection.getValue()}));
|
||||
}
|
||||
if (Index.Children.empty())
|
||||
return Out;
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_UL));
|
||||
const auto &UlBody = Out.back();
|
||||
for (const auto &C : Index.Children) {
|
||||
auto LiBody = llvm::make_unique<TagNode>(HTMLTag::TAG_LI);
|
||||
std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(C, InfoPath);
|
||||
AppendVector(std::move(Nodes), LiBody->Children);
|
||||
UlBody->Children.emplace_back(std::move(LiBody));
|
||||
}
|
||||
return Out;
|
||||
}
|
||||
|
||||
static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
|
||||
if (I.Kind == "FullComment") {
|
||||
auto FullComment = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
|
||||
|
@ -455,6 +501,8 @@ static std::vector<std::unique_ptr<TagNode>> genHTML(const EnumInfo &I) {
|
|||
|
||||
Out.emplace_back(
|
||||
llvm::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.Name));
|
||||
Out.back()->Attributes.try_emplace("id",
|
||||
llvm::toHex(llvm::toStringRef(I.USR)));
|
||||
|
||||
std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members);
|
||||
if (Node)
|
||||
|
@ -474,6 +522,10 @@ static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I,
|
|||
StringRef ParentInfoDir) {
|
||||
std::vector<std::unique_ptr<TagNode>> Out;
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name));
|
||||
// USR is used as id for functions instead of name to disambiguate function
|
||||
// overloads.
|
||||
Out.back()->Attributes.try_emplace("id",
|
||||
llvm::toHex(llvm::toStringRef(I.USR)));
|
||||
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P));
|
||||
auto &FunctionHeader = Out.back();
|
||||
|
@ -510,8 +562,8 @@ static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I,
|
|||
return Out;
|
||||
}
|
||||
|
||||
static std::vector<std::unique_ptr<TagNode>> genHTML(const NamespaceInfo &I,
|
||||
std::string &InfoTitle) {
|
||||
static std::vector<std::unique_ptr<TagNode>>
|
||||
genHTML(const NamespaceInfo &I, Index &InfoIndex, std::string &InfoTitle) {
|
||||
std::vector<std::unique_ptr<TagNode>> Out;
|
||||
if (I.Name.str() == "")
|
||||
InfoTitle = "Global Namespace";
|
||||
|
@ -538,11 +590,21 @@ static std::vector<std::unique_ptr<TagNode>> genHTML(const NamespaceInfo &I,
|
|||
genEnumsBlock(I.ChildEnums);
|
||||
AppendVector(std::move(ChildEnums), Out);
|
||||
|
||||
if (!I.ChildNamespaces.empty())
|
||||
InfoIndex.Children.emplace_back("Namespaces", "Namespaces");
|
||||
if (!I.ChildRecords.empty())
|
||||
InfoIndex.Children.emplace_back("Records", "Records");
|
||||
if (!I.ChildFunctions.empty())
|
||||
InfoIndex.Children.emplace_back(
|
||||
genInfoIndexItem(I.ChildFunctions, "Functions"));
|
||||
if (!I.ChildEnums.empty())
|
||||
InfoIndex.Children.emplace_back(genInfoIndexItem(I.ChildEnums, "Enums"));
|
||||
|
||||
return Out;
|
||||
}
|
||||
|
||||
static std::vector<std::unique_ptr<TagNode>> genHTML(const RecordInfo &I,
|
||||
std::string &InfoTitle) {
|
||||
static std::vector<std::unique_ptr<TagNode>>
|
||||
genHTML(const RecordInfo &I, Index &InfoIndex, std::string &InfoTitle) {
|
||||
std::vector<std::unique_ptr<TagNode>> Out;
|
||||
InfoTitle = (getTagType(I.TagType) + " " + I.Name).str();
|
||||
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
|
||||
|
@ -587,6 +649,16 @@ static std::vector<std::unique_ptr<TagNode>> genHTML(const RecordInfo &I,
|
|||
genEnumsBlock(I.ChildEnums);
|
||||
AppendVector(std::move(ChildEnums), Out);
|
||||
|
||||
if (!I.Members.empty())
|
||||
InfoIndex.Children.emplace_back("Members", "Members");
|
||||
if (!I.ChildRecords.empty())
|
||||
InfoIndex.Children.emplace_back("Records", "Records");
|
||||
if (!I.ChildFunctions.empty())
|
||||
InfoIndex.Children.emplace_back(
|
||||
genInfoIndexItem(I.ChildFunctions, "Functions"));
|
||||
if (!I.ChildEnums.empty())
|
||||
InfoIndex.Children.emplace_back(genInfoIndexItem(I.ChildEnums, "Enums"));
|
||||
|
||||
return Out;
|
||||
}
|
||||
|
||||
|
@ -607,16 +679,17 @@ llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
|
|||
HTMLFile F;
|
||||
std::string InfoTitle;
|
||||
auto MainContentNode = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
|
||||
Index InfoIndex;
|
||||
switch (I->IT) {
|
||||
case InfoType::IT_namespace: {
|
||||
std::vector<std::unique_ptr<TagNode>> Nodes =
|
||||
genHTML(*static_cast<clang::doc::NamespaceInfo *>(I), InfoTitle);
|
||||
std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(
|
||||
*static_cast<clang::doc::NamespaceInfo *>(I), InfoIndex, InfoTitle);
|
||||
AppendVector(std::move(Nodes), MainContentNode->Children);
|
||||
break;
|
||||
}
|
||||
case InfoType::IT_record: {
|
||||
std::vector<std::unique_ptr<TagNode>> Nodes =
|
||||
genHTML(*static_cast<clang::doc::RecordInfo *>(I), InfoTitle);
|
||||
std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(
|
||||
*static_cast<clang::doc::RecordInfo *>(I), InfoIndex, InfoTitle);
|
||||
AppendVector(std::move(Nodes), MainContentNode->Children);
|
||||
break;
|
||||
}
|
||||
|
@ -640,6 +713,9 @@ llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
|
|||
std::vector<std::unique_ptr<TagNode>> BasicNodes =
|
||||
genCommonFileNodes(InfoTitle, I->Path, CDCtx);
|
||||
AppendVector(std::move(BasicNodes), F.Children);
|
||||
std::vector<std::unique_ptr<TagNode>> InfoIndexHTML =
|
||||
genHTML(InfoIndex, I->Path);
|
||||
AppendVector(std::move(InfoIndexHTML), F.Children);
|
||||
F.Children.emplace_back(std::move(MainContentNode));
|
||||
F.Render(OS);
|
||||
|
||||
|
|
|
@ -350,12 +350,15 @@ struct EnumInfo : public SymbolInfo {
|
|||
|
||||
struct Index : public Reference {
|
||||
Index() = default;
|
||||
Index(StringRef Name, StringRef JumpToSection)
|
||||
: Reference(Name), JumpToSection(JumpToSection) {}
|
||||
Index(SymbolID USR, StringRef Name, InfoType IT, StringRef Path)
|
||||
: Reference(USR, Name, IT, Path) {}
|
||||
// This is used to look for a USR in a vector of Indexes using std::find
|
||||
bool operator==(const SymbolID &Other) const { return USR == Other; }
|
||||
bool operator<(const Index &Other) const { return Name < Other.Name; }
|
||||
|
||||
llvm::Optional<SmallString<16>> JumpToSection;
|
||||
std::vector<Index> Children;
|
||||
|
||||
void sort();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "ClangDocTest.h"
|
||||
#include "Generators.h"
|
||||
#include "Representation.h"
|
||||
#include "Serialize.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace clang {
|
||||
|
@ -59,24 +60,60 @@ TEST(HTMLGeneratorTest, emitNamespaceHTML) {
|
|||
<link rel="stylesheet" href="user-provided-stylesheet.css"/>
|
||||
<script src="index.js"></script>
|
||||
<div id="index" path=""></div>
|
||||
<ul>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#Namespaces">Namespaces</a>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#Records">Records</a>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#Functions">Functions</a>
|
||||
</span>
|
||||
<ul>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#0000000000000000000000000000000000000000">OneFunction</a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#Enums">Enums</a>
|
||||
</span>
|
||||
<ul>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#0000000000000000000000000000000000000000">OneEnum</a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div>
|
||||
<h1>namespace Namespace</h1>
|
||||
<h2>Namespaces</h2>
|
||||
<h2 id="Namespaces">Namespaces</h2>
|
||||
<ul>
|
||||
<li>ChildNamespace</li>
|
||||
</ul>
|
||||
<h2>Records</h2>
|
||||
<h2 id="Records">Records</h2>
|
||||
<ul>
|
||||
<li>ChildStruct</li>
|
||||
</ul>
|
||||
<h2>Functions</h2>
|
||||
<h2 id="Functions">Functions</h2>
|
||||
<div>
|
||||
<h3>OneFunction</h3>
|
||||
<h3 id="0000000000000000000000000000000000000000">OneFunction</h3>
|
||||
<p>OneFunction()</p>
|
||||
</div>
|
||||
<h2>Enums</h2>
|
||||
<h2 id="Enums">Enums</h2>
|
||||
<div>
|
||||
<h3>enum OneEnum</h3>
|
||||
<h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3>
|
||||
</div>
|
||||
</div>
|
||||
)raw";
|
||||
|
@ -119,6 +156,42 @@ TEST(HTMLGeneratorTest, emitRecordHTML) {
|
|||
<link rel="stylesheet" href="../../../clang-doc-default-stylesheet.css"/>
|
||||
<script src="../../../index.js"></script>
|
||||
<div id="index" path="X/Y/Z"></div>
|
||||
<ul>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#Members">Members</a>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#Records">Records</a>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#Functions">Functions</a>
|
||||
</span>
|
||||
<ul>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#0000000000000000000000000000000000000000">OneFunction</a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#Enums">Enums</a>
|
||||
</span>
|
||||
<ul>
|
||||
<li>
|
||||
<span>
|
||||
<a href="#0000000000000000000000000000000000000000">OneEnum</a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div>
|
||||
<h1>class r</h1>
|
||||
<p>Defined at line 10 of test.cpp</p>
|
||||
|
@ -127,7 +200,7 @@ TEST(HTMLGeneratorTest, emitRecordHTML) {
|
|||
<a href="../../../path/to/F.html">F</a>
|
||||
, G
|
||||
</p>
|
||||
<h2>Members</h2>
|
||||
<h2 id="Members">Members</h2>
|
||||
<ul>
|
||||
<li>
|
||||
private
|
||||
|
@ -135,18 +208,18 @@ TEST(HTMLGeneratorTest, emitRecordHTML) {
|
|||
X
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Records</h2>
|
||||
<h2 id="Records">Records</h2>
|
||||
<ul>
|
||||
<li>ChildStruct</li>
|
||||
</ul>
|
||||
<h2>Functions</h2>
|
||||
<h2 id="Functions">Functions</h2>
|
||||
<div>
|
||||
<h3>OneFunction</h3>
|
||||
<h3 id="0000000000000000000000000000000000000000">OneFunction</h3>
|
||||
<p>OneFunction()</p>
|
||||
</div>
|
||||
<h2>Enums</h2>
|
||||
<h2 id="Enums">Enums</h2>
|
||||
<div>
|
||||
<h3>enum OneEnum</h3>
|
||||
<h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3>
|
||||
</div>
|
||||
</div>
|
||||
)raw";
|
||||
|
@ -183,7 +256,7 @@ TEST(HTMLGeneratorTest, emitFunctionHTML) {
|
|||
<script src="index.js"></script>
|
||||
<div id="index" path=""></div>
|
||||
<div>
|
||||
<h3>f</h3>
|
||||
<h3 id="0000000000000000000000000000000000000000">f</h3>
|
||||
<p>
|
||||
<a href="path/to/float.html">float</a>
|
||||
f(
|
||||
|
@ -222,7 +295,7 @@ TEST(HTMLGeneratorTest, emitEnumHTML) {
|
|||
<script src="index.js"></script>
|
||||
<div id="index" path=""></div>
|
||||
<div>
|
||||
<h3>enum class e</h3>
|
||||
<h3 id="0000000000000000000000000000000000000000">enum class e</h3>
|
||||
<ul>
|
||||
<li>X</li>
|
||||
</ul>
|
||||
|
@ -293,7 +366,7 @@ TEST(HTMLGeneratorTest, emitCommentHTML) {
|
|||
<script src="index.js"></script>
|
||||
<div id="index" path=""></div>
|
||||
<div>
|
||||
<h3>f</h3>
|
||||
<h3 id="0000000000000000000000000000000000000000">f</h3>
|
||||
<p>void f(int I, int J)</p>
|
||||
<p>Defined at line 10 of test.cpp</p>
|
||||
<div>
|
||||
|
|
Loading…
Reference in New Issue