[clang-tools-extra] r368209 - [clang-doc] Add second index for sections within info's content

Diego Astiazaran via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 7 14:04:52 PDT 2019


Author: diegoastiazaran
Date: Wed Aug  7 14:04:52 2019
New Revision: 368209

URL: http://llvm.org/viewvc/llvm-project?rev=368209&view=rev
Log:
[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

Modified:
    clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp
    clang-tools-extra/trunk/clang-doc/Representation.h
    clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp

Modified: clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp?rev=368209&r1=368208&r2=368209&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp Wed Aug  7 14:04:52 2019
@@ -270,15 +270,22 @@ static std::unique_ptr<TagNode> genLink(
   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
 
   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<Func
 
   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::SmallV
 
   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<Ref
 
   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, Stri
   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<TagNo
 
   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<TagNo
                                                      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<TagNo
   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<TagNo
       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<TagNo
       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::generateDocFo
   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::generateDocFo
   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);
 

Modified: clang-tools-extra/trunk/clang-doc/Representation.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Representation.h?rev=368209&r1=368208&r2=368209&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Representation.h (original)
+++ clang-tools-extra/trunk/clang-doc/Representation.h Wed Aug  7 14:04:52 2019
@@ -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();

Modified: clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp?rev=368209&r1=368208&r2=368209&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp Wed Aug  7 14:04:52 2019
@@ -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, emitNamespaceHTM
 <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>




More information about the cfe-commits mailing list