clang-tools  16.0.0git
HTMLGenerator.cpp
Go to the documentation of this file.
1 //===-- HTMLGenerator.cpp - HTML Generator ----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Generators.h"
10 #include "Representation.h"
11 #include "clang/Basic/Version.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/FileSystem.h"
15 #include "llvm/Support/JSON.h"
16 #include "llvm/Support/Path.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include <string>
19 
20 using namespace llvm;
21 
22 namespace clang {
23 namespace doc {
24 
25 namespace {
26 
27 class HTMLTag {
28 public:
29  // Any other tag can be added if required
30  enum TagType {
31  TAG_A,
32  TAG_DIV,
33  TAG_FOOTER,
34  TAG_H1,
35  TAG_H2,
36  TAG_H3,
37  TAG_HEADER,
38  TAG_LI,
39  TAG_LINK,
40  TAG_MAIN,
41  TAG_META,
42  TAG_OL,
43  TAG_P,
44  TAG_SCRIPT,
45  TAG_SPAN,
46  TAG_TITLE,
47  TAG_UL,
48  };
49 
50  HTMLTag() = default;
51  constexpr HTMLTag(TagType Value) : Value(Value) {}
52 
53  operator TagType() const { return Value; }
54  operator bool() = delete;
55 
56  bool IsSelfClosing() const;
57  llvm::SmallString<16> ToString() const;
58 
59 private:
60  TagType Value;
61 };
62 
63 enum NodeType {
64  NODE_TEXT,
65  NODE_TAG,
66 };
67 
68 struct HTMLNode {
69  HTMLNode(NodeType Type) : Type(Type) {}
70  virtual ~HTMLNode() = default;
71 
72  virtual void Render(llvm::raw_ostream &OS, int IndentationLevel) = 0;
73  NodeType Type; // Type of node
74 };
75 
76 struct TextNode : public HTMLNode {
77  TextNode(const Twine &Text)
78  : HTMLNode(NodeType::NODE_TEXT), Text(Text.str()) {}
79 
80  std::string Text; // Content of node
81  void Render(llvm::raw_ostream &OS, int IndentationLevel) override;
82 };
83 
84 struct TagNode : public HTMLNode {
85  TagNode(HTMLTag Tag) : HTMLNode(NodeType::NODE_TAG), Tag(Tag) {}
86  TagNode(HTMLTag Tag, const Twine &Text) : TagNode(Tag) {
87  Children.emplace_back(std::make_unique<TextNode>(Text.str()));
88  }
89 
90  HTMLTag Tag; // Name of HTML Tag (p, div, h1)
91  std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
92  std::vector<std::pair<std::string, std::string>>
93  Attributes; // List of key-value attributes for tag
94 
95  void Render(llvm::raw_ostream &OS, int IndentationLevel) override;
96 };
97 
98 constexpr const char *kDoctypeDecl = "<!DOCTYPE html>";
99 
100 struct HTMLFile {
101  std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
102  void Render(llvm::raw_ostream &OS) {
103  OS << kDoctypeDecl << "\n";
104  for (const auto &C : Children) {
105  C->Render(OS, 0);
106  OS << "\n";
107  }
108  }
109 };
110 
111 } // namespace
112 
113 bool HTMLTag::IsSelfClosing() const {
114  switch (Value) {
115  case HTMLTag::TAG_META:
116  case HTMLTag::TAG_LINK:
117  return true;
118  case HTMLTag::TAG_A:
119  case HTMLTag::TAG_DIV:
120  case HTMLTag::TAG_FOOTER:
121  case HTMLTag::TAG_H1:
122  case HTMLTag::TAG_H2:
123  case HTMLTag::TAG_H3:
124  case HTMLTag::TAG_HEADER:
125  case HTMLTag::TAG_LI:
126  case HTMLTag::TAG_MAIN:
127  case HTMLTag::TAG_OL:
128  case HTMLTag::TAG_P:
129  case HTMLTag::TAG_SCRIPT:
130  case HTMLTag::TAG_SPAN:
131  case HTMLTag::TAG_TITLE:
132  case HTMLTag::TAG_UL:
133  return false;
134  }
135  llvm_unreachable("Unhandled HTMLTag::TagType");
136 }
137 
138 llvm::SmallString<16> HTMLTag::ToString() const {
139  switch (Value) {
140  case HTMLTag::TAG_A:
141  return llvm::SmallString<16>("a");
142  case HTMLTag::TAG_DIV:
143  return llvm::SmallString<16>("div");
144  case HTMLTag::TAG_FOOTER:
145  return llvm::SmallString<16>("footer");
146  case HTMLTag::TAG_H1:
147  return llvm::SmallString<16>("h1");
148  case HTMLTag::TAG_H2:
149  return llvm::SmallString<16>("h2");
150  case HTMLTag::TAG_H3:
151  return llvm::SmallString<16>("h3");
152  case HTMLTag::TAG_HEADER:
153  return llvm::SmallString<16>("header");
154  case HTMLTag::TAG_LI:
155  return llvm::SmallString<16>("li");
156  case HTMLTag::TAG_LINK:
157  return llvm::SmallString<16>("link");
158  case HTMLTag::TAG_MAIN:
159  return llvm::SmallString<16>("main");
160  case HTMLTag::TAG_META:
161  return llvm::SmallString<16>("meta");
162  case HTMLTag::TAG_OL:
163  return llvm::SmallString<16>("ol");
164  case HTMLTag::TAG_P:
165  return llvm::SmallString<16>("p");
166  case HTMLTag::TAG_SCRIPT:
167  return llvm::SmallString<16>("script");
168  case HTMLTag::TAG_SPAN:
169  return llvm::SmallString<16>("span");
170  case HTMLTag::TAG_TITLE:
171  return llvm::SmallString<16>("title");
172  case HTMLTag::TAG_UL:
173  return llvm::SmallString<16>("ul");
174  }
175  llvm_unreachable("Unhandled HTMLTag::TagType");
176 }
177 
178 void TextNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
179  OS.indent(IndentationLevel * 2);
180  printHTMLEscaped(Text, OS);
181 }
182 
183 void TagNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
184  // Children nodes are rendered in the same line if all of them are text nodes
185  bool InlineChildren = true;
186  for (const auto &C : Children)
187  if (C->Type == NodeType::NODE_TAG) {
188  InlineChildren = false;
189  break;
190  }
191  OS.indent(IndentationLevel * 2);
192  OS << "<" << Tag.ToString();
193  for (const auto &A : Attributes)
194  OS << " " << A.first << "=\"" << A.second << "\"";
195  if (Tag.IsSelfClosing()) {
196  OS << "/>";
197  return;
198  }
199  OS << ">";
200  if (!InlineChildren)
201  OS << "\n";
202  bool NewLineRendered = true;
203  for (const auto &C : Children) {
204  int ChildrenIndentation =
205  InlineChildren || !NewLineRendered ? 0 : IndentationLevel + 1;
206  C->Render(OS, ChildrenIndentation);
207  if (!InlineChildren && (C == Children.back() ||
208  (C->Type != NodeType::NODE_TEXT ||
209  (&C + 1)->get()->Type != NodeType::NODE_TEXT))) {
210  OS << "\n";
211  NewLineRendered = true;
212  } else
213  NewLineRendered = false;
214  }
215  if (!InlineChildren)
216  OS.indent(IndentationLevel * 2);
217  OS << "</" << Tag.ToString() << ">";
218 }
219 
220 template <typename Derived, typename Base,
221  typename = std::enable_if<std::is_base_of<Derived, Base>::value>>
222 static void AppendVector(std::vector<Derived> &&New,
223  std::vector<Base> &Original) {
224  std::move(New.begin(), New.end(), std::back_inserter(Original));
225 }
226 
227 // Compute the relative path from an Origin directory to a Destination directory
228 static SmallString<128> computeRelativePath(StringRef Destination,
229  StringRef Origin) {
230  // If Origin is empty, the relative path to the Destination is its complete
231  // path.
232  if (Origin.empty())
233  return Destination;
234 
235  // The relative path is an empty path if both directories are the same.
236  if (Destination == Origin)
237  return {};
238 
239  // These iterators iterate through each of their parent directories
240  llvm::sys::path::const_iterator FileI = llvm::sys::path::begin(Destination);
241  llvm::sys::path::const_iterator FileE = llvm::sys::path::end(Destination);
242  llvm::sys::path::const_iterator DirI = llvm::sys::path::begin(Origin);
243  llvm::sys::path::const_iterator DirE = llvm::sys::path::end(Origin);
244  // Advance both iterators until the paths differ. Example:
245  // Destination = A/B/C/D
246  // Origin = A/B/E/F
247  // FileI will point to C and DirI to E. The directories behind them is the
248  // directory they share (A/B).
249  while (FileI != FileE && DirI != DirE && *FileI == *DirI) {
250  ++FileI;
251  ++DirI;
252  }
253  SmallString<128> Result; // This will hold the resulting path.
254  // Result has to go up one directory for each of the remaining directories in
255  // Origin
256  while (DirI != DirE) {
257  llvm::sys::path::append(Result, "..");
258  ++DirI;
259  }
260  // Result has to append each of the remaining directories in Destination
261  while (FileI != FileE) {
262  llvm::sys::path::append(Result, *FileI);
263  ++FileI;
264  }
265  return Result;
266 }
267 
268 // HTML generation
269 
270 static std::vector<std::unique_ptr<TagNode>>
271 genStylesheetsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) {
272  std::vector<std::unique_ptr<TagNode>> Out;
273  for (const auto &FilePath : CDCtx.UserStylesheets) {
274  auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_LINK);
275  LinkNode->Attributes.emplace_back("rel", "stylesheet");
276  SmallString<128> StylesheetPath = computeRelativePath("", InfoPath);
277  llvm::sys::path::append(StylesheetPath,
278  llvm::sys::path::filename(FilePath));
279  // Paths in HTML must be in posix-style
280  llvm::sys::path::native(StylesheetPath, llvm::sys::path::Style::posix);
281  LinkNode->Attributes.emplace_back("href", std::string(StylesheetPath.str()));
282  Out.emplace_back(std::move(LinkNode));
283  }
284  return Out;
285 }
286 
287 static std::vector<std::unique_ptr<TagNode>>
288 genJsScriptsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) {
289  std::vector<std::unique_ptr<TagNode>> Out;
290  for (const auto &FilePath : CDCtx.JsScripts) {
291  auto ScriptNode = std::make_unique<TagNode>(HTMLTag::TAG_SCRIPT);
292  SmallString<128> ScriptPath = computeRelativePath("", InfoPath);
293  llvm::sys::path::append(ScriptPath, llvm::sys::path::filename(FilePath));
294  // Paths in HTML must be in posix-style
295  llvm::sys::path::native(ScriptPath, llvm::sys::path::Style::posix);
296  ScriptNode->Attributes.emplace_back("src", std::string(ScriptPath.str()));
297  Out.emplace_back(std::move(ScriptNode));
298  }
299  return Out;
300 }
301 
302 static std::unique_ptr<TagNode> genLink(const Twine &Text, const Twine &Link) {
303  auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_A, Text);
304  LinkNode->Attributes.emplace_back("href", Link.str());
305  return LinkNode;
306 }
307 
308 static std::unique_ptr<HTMLNode>
309 genReference(const Reference &Type, StringRef CurrentDirectory,
310  llvm::Optional<StringRef> JumpToSection = None) {
311  if (Type.Path.empty()) {
312  if (!JumpToSection)
313  return std::make_unique<TextNode>(Type.Name);
314  else
315  return genLink(Type.Name, "#" + *JumpToSection);
316  }
317  llvm::SmallString<64> Path = Type.getRelativeFilePath(CurrentDirectory);
318  llvm::sys::path::append(Path, Type.getFileBaseName() + ".html");
319 
320  // Paths in HTML must be in posix-style
321  llvm::sys::path::native(Path, llvm::sys::path::Style::posix);
322  if (JumpToSection)
323  Path += ("#" + *JumpToSection).str();
324  return genLink(Type.Name, Path);
325 }
326 
327 static std::vector<std::unique_ptr<HTMLNode>>
329  const StringRef &CurrentDirectory) {
330  std::vector<std::unique_ptr<HTMLNode>> Out;
331  for (const auto &R : Refs) {
332  if (&R != Refs.begin())
333  Out.emplace_back(std::make_unique<TextNode>(", "));
334  Out.emplace_back(genReference(R, CurrentDirectory));
335  }
336  return Out;
337 }
338 
339 static std::vector<std::unique_ptr<TagNode>>
340 genHTML(const EnumInfo &I, const ClangDocContext &CDCtx);
341 static std::vector<std::unique_ptr<TagNode>>
342 genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx,
343  StringRef ParentInfoDir);
344 
345 static std::vector<std::unique_ptr<TagNode>>
346 genEnumsBlock(const std::vector<EnumInfo> &Enums,
347  const ClangDocContext &CDCtx) {
348  if (Enums.empty())
349  return {};
350 
351  std::vector<std::unique_ptr<TagNode>> Out;
352  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Enums"));
353  Out.back()->Attributes.emplace_back("id", "Enums");
354  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV));
355  auto &DivBody = Out.back();
356  for (const auto &E : Enums) {
357  std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(E, CDCtx);
358  AppendVector(std::move(Nodes), DivBody->Children);
359  }
360  return Out;
361 }
362 
363 static std::unique_ptr<TagNode>
364 genEnumMembersBlock(const llvm::SmallVector<EnumValueInfo, 4> &Members) {
365  if (Members.empty())
366  return nullptr;
367 
368  auto List = std::make_unique<TagNode>(HTMLTag::TAG_UL);
369  for (const auto &M : Members)
370  List->Children.emplace_back(
371  std::make_unique<TagNode>(HTMLTag::TAG_LI, M.Name));
372  return List;
373 }
374 
375 static std::vector<std::unique_ptr<TagNode>>
376 genFunctionsBlock(const std::vector<FunctionInfo> &Functions,
377  const ClangDocContext &CDCtx, StringRef ParentInfoDir) {
378  if (Functions.empty())
379  return {};
380 
381  std::vector<std::unique_ptr<TagNode>> Out;
382  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Functions"));
383  Out.back()->Attributes.emplace_back("id", "Functions");
384  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV));
385  auto &DivBody = Out.back();
386  for (const auto &F : Functions) {
387  std::vector<std::unique_ptr<TagNode>> Nodes =
388  genHTML(F, CDCtx, ParentInfoDir);
389  AppendVector(std::move(Nodes), DivBody->Children);
390  }
391  return Out;
392 }
393 
394 static std::vector<std::unique_ptr<TagNode>>
395 genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members,
396  StringRef ParentInfoDir) {
397  if (Members.empty())
398  return {};
399 
400  std::vector<std::unique_ptr<TagNode>> Out;
401  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Members"));
402  Out.back()->Attributes.emplace_back("id", "Members");
403  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
404  auto &ULBody = Out.back();
405  for (const auto &M : Members) {
406  std::string Access = getAccessSpelling(M.Access).str();
407  if (Access != "")
408  Access = Access + " ";
409  auto LIBody = std::make_unique<TagNode>(HTMLTag::TAG_LI);
410  LIBody->Children.emplace_back(std::make_unique<TextNode>(Access));
411  LIBody->Children.emplace_back(genReference(M.Type, ParentInfoDir));
412  LIBody->Children.emplace_back(std::make_unique<TextNode>(" " + M.Name));
413  ULBody->Children.emplace_back(std::move(LIBody));
414  }
415  return Out;
416 }
417 
418 static std::vector<std::unique_ptr<TagNode>>
419 genReferencesBlock(const std::vector<Reference> &References,
420  llvm::StringRef Title, StringRef ParentPath) {
421  if (References.empty())
422  return {};
423 
424  std::vector<std::unique_ptr<TagNode>> Out;
425  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, Title));
426  Out.back()->Attributes.emplace_back("id", std::string(Title));
427  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
428  auto &ULBody = Out.back();
429  for (const auto &R : References) {
430  auto LiNode = std::make_unique<TagNode>(HTMLTag::TAG_LI);
431  LiNode->Children.emplace_back(genReference(R, ParentPath));
432  ULBody->Children.emplace_back(std::move(LiNode));
433  }
434  return Out;
435 }
436 
437 static std::unique_ptr<TagNode>
439  llvm::Optional<StringRef> RepositoryUrl = None) {
440  if (!L.IsFileInRootDir || !RepositoryUrl)
441  return std::make_unique<TagNode>(
442  HTMLTag::TAG_P, "Defined at line " + std::to_string(L.LineNumber) +
443  " of file " + L.Filename);
444  SmallString<128> FileURL(*RepositoryUrl);
445  llvm::sys::path::append(FileURL, llvm::sys::path::Style::posix, L.Filename);
446  auto Node = std::make_unique<TagNode>(HTMLTag::TAG_P);
447  Node->Children.emplace_back(std::make_unique<TextNode>("Defined at line "));
448  auto LocNumberNode =
449  std::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.LineNumber));
450  // The links to a specific line in the source code use the github /
451  // googlesource notation so it won't work for all hosting pages.
452  LocNumberNode->Attributes.emplace_back(
453  "href", (FileURL + "#" + std::to_string(L.LineNumber)).str());
454  Node->Children.emplace_back(std::move(LocNumberNode));
455  Node->Children.emplace_back(std::make_unique<TextNode>(" of file "));
456  auto LocFileNode = std::make_unique<TagNode>(
457  HTMLTag::TAG_A, llvm::sys::path::filename(FileURL));
458  LocFileNode->Attributes.emplace_back("href", std::string(FileURL.str()));
459  Node->Children.emplace_back(std::move(LocFileNode));
460  return Node;
461 }
462 
463 static std::vector<std::unique_ptr<TagNode>>
464 genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList);
465 
466 // Generates a list of child nodes for the HTML head tag
467 // It contains a meta node, link nodes to import CSS files, and script nodes to
468 // import JS files
469 static std::vector<std::unique_ptr<TagNode>>
470 genFileHeadNodes(StringRef Title, StringRef InfoPath,
471  const ClangDocContext &CDCtx) {
472  std::vector<std::unique_ptr<TagNode>> Out;
473  auto MetaNode = std::make_unique<TagNode>(HTMLTag::TAG_META);
474  MetaNode->Attributes.emplace_back("charset", "utf-8");
475  Out.emplace_back(std::move(MetaNode));
476  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_TITLE, Title));
477  std::vector<std::unique_ptr<TagNode>> StylesheetsNodes =
478  genStylesheetsHTML(InfoPath, CDCtx);
479  AppendVector(std::move(StylesheetsNodes), Out);
480  std::vector<std::unique_ptr<TagNode>> JsNodes =
481  genJsScriptsHTML(InfoPath, CDCtx);
482  AppendVector(std::move(JsNodes), Out);
483  return Out;
484 }
485 
486 // Generates a header HTML node that can be used for any file
487 // It contains the project name
488 static std::unique_ptr<TagNode> genFileHeaderNode(StringRef ProjectName) {
489  auto HeaderNode = std::make_unique<TagNode>(HTMLTag::TAG_HEADER, ProjectName);
490  HeaderNode->Attributes.emplace_back("id", "project-title");
491  return HeaderNode;
492 }
493 
494 // Generates a main HTML node that has all the main content of an info file
495 // It contains both indexes and the info's documented information
496 // This function should only be used for the info files (not for the file that
497 // only has the general index)
498 static std::unique_ptr<TagNode> genInfoFileMainNode(
499  StringRef InfoPath,
500  std::vector<std::unique_ptr<TagNode>> &MainContentInnerNodes,
501  const Index &InfoIndex) {
502  auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
503 
504  auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
505  LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left");
506  LeftSidebarNode->Attributes.emplace_back("path", std::string(InfoPath));
507  LeftSidebarNode->Attributes.emplace_back(
508  "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");
509 
510  auto MainContentNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
511  MainContentNode->Attributes.emplace_back("id", "main-content");
512  MainContentNode->Attributes.emplace_back(
513  "class", "col-xs-12 col-sm-9 col-md-8 main-content");
514  AppendVector(std::move(MainContentInnerNodes), MainContentNode->Children);
515 
516  auto RightSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
517  RightSidebarNode->Attributes.emplace_back("id", "sidebar-right");
518  RightSidebarNode->Attributes.emplace_back(
519  "class", "col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right");
520  std::vector<std::unique_ptr<TagNode>> InfoIndexHTML =
521  genHTML(InfoIndex, InfoPath, true);
522  AppendVector(std::move(InfoIndexHTML), RightSidebarNode->Children);
523 
524  MainNode->Children.emplace_back(std::move(LeftSidebarNode));
525  MainNode->Children.emplace_back(std::move(MainContentNode));
526  MainNode->Children.emplace_back(std::move(RightSidebarNode));
527 
528  return MainNode;
529 }
530 
531 // Generates a footer HTML node that can be used for any file
532 // It contains clang-doc's version
533 static std::unique_ptr<TagNode> genFileFooterNode() {
534  auto FooterNode = std::make_unique<TagNode>(HTMLTag::TAG_FOOTER);
535  auto SpanNode = std::make_unique<TagNode>(
536  HTMLTag::TAG_SPAN, clang::getClangToolFullVersion("clang-doc"));
537  SpanNode->Attributes.emplace_back("class", "no-break");
538  FooterNode->Children.emplace_back(std::move(SpanNode));
539  return FooterNode;
540 }
541 
542 // Generates a complete HTMLFile for an Info
543 static HTMLFile
544 genInfoFile(StringRef Title, StringRef InfoPath,
545  std::vector<std::unique_ptr<TagNode>> &MainContentNodes,
546  const Index &InfoIndex, const ClangDocContext &CDCtx) {
547  HTMLFile F;
548 
549  std::vector<std::unique_ptr<TagNode>> HeadNodes =
550  genFileHeadNodes(Title, InfoPath, CDCtx);
551  std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName);
552  std::unique_ptr<TagNode> MainNode =
553  genInfoFileMainNode(InfoPath, MainContentNodes, InfoIndex);
554  std::unique_ptr<TagNode> FooterNode = genFileFooterNode();
555 
556  AppendVector(std::move(HeadNodes), F.Children);
557  F.Children.emplace_back(std::move(HeaderNode));
558  F.Children.emplace_back(std::move(MainNode));
559  F.Children.emplace_back(std::move(FooterNode));
560 
561  return F;
562 }
563 
564 template <typename T,
565  typename = std::enable_if<std::is_base_of<T, Info>::value>>
566 static Index genInfoIndexItem(const std::vector<T> &Infos, StringRef Title) {
567  Index Idx(Title, Title);
568  for (const auto &C : Infos)
569  Idx.Children.emplace_back(C.extractName(),
570  llvm::toHex(llvm::toStringRef(C.USR)));
571  return Idx;
572 }
573 
574 static std::vector<std::unique_ptr<TagNode>>
575 genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList) {
576  std::vector<std::unique_ptr<TagNode>> Out;
577  if (!Index.Name.empty()) {
578  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_SPAN));
579  auto &SpanBody = Out.back();
580  if (!Index.JumpToSection)
581  SpanBody->Children.emplace_back(genReference(Index, InfoPath));
582  else
583  SpanBody->Children.emplace_back(
584  genReference(Index, InfoPath, Index.JumpToSection->str()));
585  }
586  if (Index.Children.empty())
587  return Out;
588  // Only the outermost list should use ol, the others should use ul
589  HTMLTag ListHTMLTag = IsOutermostList ? HTMLTag::TAG_OL : HTMLTag::TAG_UL;
590  Out.emplace_back(std::make_unique<TagNode>(ListHTMLTag));
591  const auto &UlBody = Out.back();
592  for (const auto &C : Index.Children) {
593  auto LiBody = std::make_unique<TagNode>(HTMLTag::TAG_LI);
594  std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(C, InfoPath, false);
595  AppendVector(std::move(Nodes), LiBody->Children);
596  UlBody->Children.emplace_back(std::move(LiBody));
597  }
598  return Out;
599 }
600 
601 static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
602  if (I.Kind == "FullComment") {
603  auto FullComment = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
604  for (const auto &Child : I.Children) {
605  std::unique_ptr<HTMLNode> Node = genHTML(*Child);
606  if (Node)
607  FullComment->Children.emplace_back(std::move(Node));
608  }
609  return std::move(FullComment);
610  } else if (I.Kind == "ParagraphComment") {
611  auto ParagraphComment = std::make_unique<TagNode>(HTMLTag::TAG_P);
612  for (const auto &Child : I.Children) {
613  std::unique_ptr<HTMLNode> Node = genHTML(*Child);
614  if (Node)
615  ParagraphComment->Children.emplace_back(std::move(Node));
616  }
617  if (ParagraphComment->Children.empty())
618  return nullptr;
619  return std::move(ParagraphComment);
620  } else if (I.Kind == "TextComment") {
621  if (I.Text == "")
622  return nullptr;
623  return std::make_unique<TextNode>(I.Text);
624  }
625  return nullptr;
626 }
627 
628 static std::unique_ptr<TagNode> genHTML(const std::vector<CommentInfo> &C) {
629  auto CommentBlock = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
630  for (const auto &Child : C) {
631  if (std::unique_ptr<HTMLNode> Node = genHTML(Child))
632  CommentBlock->Children.emplace_back(std::move(Node));
633  }
634  return CommentBlock;
635 }
636 
637 static std::vector<std::unique_ptr<TagNode>>
638 genHTML(const EnumInfo &I, const ClangDocContext &CDCtx) {
639  std::vector<std::unique_ptr<TagNode>> Out;
640  std::string EnumType;
641  if (I.Scoped)
642  EnumType = "enum class ";
643  else
644  EnumType = "enum ";
645 
646  Out.emplace_back(
647  std::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.Name));
648  Out.back()->Attributes.emplace_back("id",
649  llvm::toHex(llvm::toStringRef(I.USR)));
650 
651  std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members);
652  if (Node)
653  Out.emplace_back(std::move(Node));
654 
655  if (I.DefLoc) {
656  if (!CDCtx.RepositoryUrl)
657  Out.emplace_back(writeFileDefinition(I.DefLoc.value()));
658  else
659  Out.emplace_back(writeFileDefinition(
660  I.DefLoc.value(), StringRef{CDCtx.RepositoryUrl.value()}));
661  }
662 
663  std::string Description;
664  if (!I.Description.empty())
665  Out.emplace_back(genHTML(I.Description));
666 
667  return Out;
668 }
669 
670 static std::vector<std::unique_ptr<TagNode>>
671 genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx,
672  StringRef ParentInfoDir) {
673  std::vector<std::unique_ptr<TagNode>> Out;
674  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name));
675  // USR is used as id for functions instead of name to disambiguate function
676  // overloads.
677  Out.back()->Attributes.emplace_back("id",
678  llvm::toHex(llvm::toStringRef(I.USR)));
679 
680  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
681  auto &FunctionHeader = Out.back();
682 
683  std::string Access = getAccessSpelling(I.Access).str();
684  if (Access != "")
685  FunctionHeader->Children.emplace_back(
686  std::make_unique<TextNode>(Access + " "));
687  if (I.ReturnType.Type.Name != "") {
688  FunctionHeader->Children.emplace_back(
689  genReference(I.ReturnType.Type, ParentInfoDir));
690  FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(" "));
691  }
692  FunctionHeader->Children.emplace_back(
693  std::make_unique<TextNode>(I.Name + "("));
694 
695  for (const auto &P : I.Params) {
696  if (&P != I.Params.begin())
697  FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(", "));
698  FunctionHeader->Children.emplace_back(genReference(P.Type, ParentInfoDir));
699  FunctionHeader->Children.emplace_back(
700  std::make_unique<TextNode>(" " + P.Name));
701  }
702  FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(")"));
703 
704  if (I.DefLoc) {
705  if (!CDCtx.RepositoryUrl)
706  Out.emplace_back(writeFileDefinition(I.DefLoc.value()));
707  else
708  Out.emplace_back(writeFileDefinition(
709  I.DefLoc.value(), StringRef{CDCtx.RepositoryUrl.value()}));
710  }
711 
712  std::string Description;
713  if (!I.Description.empty())
714  Out.emplace_back(genHTML(I.Description));
715 
716  return Out;
717 }
718 
719 static std::vector<std::unique_ptr<TagNode>>
720 genHTML(const NamespaceInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx,
721  std::string &InfoTitle) {
722  std::vector<std::unique_ptr<TagNode>> Out;
723  if (I.Name.str() == "")
724  InfoTitle = "Global Namespace";
725  else
726  InfoTitle = ("namespace " + I.Name).str();
727 
728  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
729 
730  std::string Description;
731  if (!I.Description.empty())
732  Out.emplace_back(genHTML(I.Description));
733 
734  llvm::SmallString<64> BasePath = I.getRelativeFilePath("");
735 
736  std::vector<std::unique_ptr<TagNode>> ChildNamespaces =
737  genReferencesBlock(I.Children.Namespaces, "Namespaces", BasePath);
738  AppendVector(std::move(ChildNamespaces), Out);
739  std::vector<std::unique_ptr<TagNode>> ChildRecords =
740  genReferencesBlock(I.Children.Records, "Records", BasePath);
741  AppendVector(std::move(ChildRecords), Out);
742 
743  std::vector<std::unique_ptr<TagNode>> ChildFunctions =
744  genFunctionsBlock(I.Children.Functions, CDCtx, BasePath);
745  AppendVector(std::move(ChildFunctions), Out);
746  std::vector<std::unique_ptr<TagNode>> ChildEnums =
747  genEnumsBlock(I.Children.Enums, CDCtx);
748  AppendVector(std::move(ChildEnums), Out);
749 
750  if (!I.Children.Namespaces.empty())
751  InfoIndex.Children.emplace_back("Namespaces", "Namespaces");
752  if (!I.Children.Records.empty())
753  InfoIndex.Children.emplace_back("Records", "Records");
754  if (!I.Children.Functions.empty())
755  InfoIndex.Children.emplace_back(
756  genInfoIndexItem(I.Children.Functions, "Functions"));
757  if (!I.Children.Enums.empty())
758  InfoIndex.Children.emplace_back(
759  genInfoIndexItem(I.Children.Enums, "Enums"));
760 
761  return Out;
762 }
763 
764 static std::vector<std::unique_ptr<TagNode>>
765 genHTML(const RecordInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx,
766  std::string &InfoTitle) {
767  std::vector<std::unique_ptr<TagNode>> Out;
768  InfoTitle = (getTagType(I.TagType) + " " + I.Name).str();
769  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
770 
771  if (I.DefLoc) {
772  if (!CDCtx.RepositoryUrl)
773  Out.emplace_back(writeFileDefinition(I.DefLoc.value()));
774  else
775  Out.emplace_back(writeFileDefinition(
776  I.DefLoc.value(), StringRef{CDCtx.RepositoryUrl.value()}));
777  }
778 
779  std::string Description;
780  if (!I.Description.empty())
781  Out.emplace_back(genHTML(I.Description));
782 
783  std::vector<std::unique_ptr<HTMLNode>> Parents =
785  std::vector<std::unique_ptr<HTMLNode>> VParents =
787  if (!Parents.empty() || !VParents.empty()) {
788  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
789  auto &PBody = Out.back();
790  PBody->Children.emplace_back(std::make_unique<TextNode>("Inherits from "));
791  if (Parents.empty())
792  AppendVector(std::move(VParents), PBody->Children);
793  else if (VParents.empty())
794  AppendVector(std::move(Parents), PBody->Children);
795  else {
796  AppendVector(std::move(Parents), PBody->Children);
797  PBody->Children.emplace_back(std::make_unique<TextNode>(", "));
798  AppendVector(std::move(VParents), PBody->Children);
799  }
800  }
801 
802  std::vector<std::unique_ptr<TagNode>> Members =
804  AppendVector(std::move(Members), Out);
805  std::vector<std::unique_ptr<TagNode>> ChildRecords =
806  genReferencesBlock(I.Children.Records, "Records", I.Path);
807  AppendVector(std::move(ChildRecords), Out);
808 
809  std::vector<std::unique_ptr<TagNode>> ChildFunctions =
811  AppendVector(std::move(ChildFunctions), Out);
812  std::vector<std::unique_ptr<TagNode>> ChildEnums =
813  genEnumsBlock(I.Children.Enums, CDCtx);
814  AppendVector(std::move(ChildEnums), Out);
815 
816  if (!I.Members.empty())
817  InfoIndex.Children.emplace_back("Members", "Members");
818  if (!I.Children.Records.empty())
819  InfoIndex.Children.emplace_back("Records", "Records");
820  if (!I.Children.Functions.empty())
821  InfoIndex.Children.emplace_back(
822  genInfoIndexItem(I.Children.Functions, "Functions"));
823  if (!I.Children.Enums.empty())
824  InfoIndex.Children.emplace_back(
825  genInfoIndexItem(I.Children.Enums, "Enums"));
826 
827  return Out;
828 }
829 
830 static std::vector<std::unique_ptr<TagNode>>
831 genHTML(const TypedefInfo &I, const ClangDocContext &CDCtx,
832  std::string &InfoTitle) {
833  // TODO support typedefs in HTML.
834  return {};
835 }
836 
837 /// Generator for HTML documentation.
838 class HTMLGenerator : public Generator {
839 public:
840  static const char *Format;
841 
842  llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS,
843  const ClangDocContext &CDCtx) override;
844  llvm::Error createResources(ClangDocContext &CDCtx) override;
845 };
846 
847 const char *HTMLGenerator::Format = "html";
848 
849 llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
850  const ClangDocContext &CDCtx) {
851  std::string InfoTitle;
852  std::vector<std::unique_ptr<TagNode>> MainContentNodes;
853  Index InfoIndex;
854  switch (I->IT) {
855  case InfoType::IT_namespace:
856  MainContentNodes = genHTML(*static_cast<clang::doc::NamespaceInfo *>(I),
857  InfoIndex, CDCtx, InfoTitle);
858  break;
859  case InfoType::IT_record:
860  MainContentNodes = genHTML(*static_cast<clang::doc::RecordInfo *>(I),
861  InfoIndex, CDCtx, InfoTitle);
862  break;
863  case InfoType::IT_enum:
864  MainContentNodes = genHTML(*static_cast<clang::doc::EnumInfo *>(I), CDCtx);
865  break;
866  case InfoType::IT_function:
867  MainContentNodes =
868  genHTML(*static_cast<clang::doc::FunctionInfo *>(I), CDCtx, "");
869  break;
870  case InfoType::IT_typedef:
871  MainContentNodes =
872  genHTML(*static_cast<clang::doc::TypedefInfo *>(I), CDCtx, InfoTitle);
873  break;
874  case InfoType::IT_default:
875  return llvm::createStringError(llvm::inconvertibleErrorCode(),
876  "unexpected info type");
877  }
878 
879  HTMLFile F = genInfoFile(InfoTitle, I->getRelativeFilePath(""),
880  MainContentNodes, InfoIndex, CDCtx);
881  F.Render(OS);
882 
883  return llvm::Error::success();
884 }
885 
886 static std::string getRefType(InfoType IT) {
887  switch (IT) {
888  case InfoType::IT_default:
889  return "default";
890  case InfoType::IT_namespace:
891  return "namespace";
892  case InfoType::IT_record:
893  return "record";
894  case InfoType::IT_function:
895  return "function";
896  case InfoType::IT_enum:
897  return "enum";
898  case InfoType::IT_typedef:
899  return "typedef";
900  }
901  llvm_unreachable("Unknown InfoType");
902 }
903 
904 static llvm::Error SerializeIndex(ClangDocContext &CDCtx) {
905  std::error_code OK;
906  std::error_code FileErr;
907  llvm::SmallString<128> FilePath;
908  llvm::sys::path::native(CDCtx.OutDirectory, FilePath);
909  llvm::sys::path::append(FilePath, "index_json.js");
910  llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);
911  if (FileErr != OK) {
912  return llvm::createStringError(llvm::inconvertibleErrorCode(),
913  "error creating index file: " +
914  FileErr.message());
915  }
916  CDCtx.Idx.sort();
917  llvm::json::OStream J(OS, 2);
918  std::function<void(Index)> IndexToJSON = [&](const Index &I) {
919  J.object([&] {
920  J.attribute("USR", toHex(llvm::toStringRef(I.USR)));
921  J.attribute("Name", I.Name);
922  J.attribute("RefType", getRefType(I.RefType));
923  J.attribute("Path", I.getRelativeFilePath(""));
924  J.attributeArray("Children", [&] {
925  for (const Index &C : I.Children)
926  IndexToJSON(C);
927  });
928  });
929  };
930  OS << "var JsonIndex = `\n";
931  IndexToJSON(CDCtx.Idx);
932  OS << "`;\n";
933  return llvm::Error::success();
934 }
935 
936 // Generates a main HTML node that has the main content of the file that shows
937 // only the general index
938 // It contains the general index with links to all the generated files
939 static std::unique_ptr<TagNode> genIndexFileMainNode() {
940  auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
941 
942  auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
943  LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left");
944  LeftSidebarNode->Attributes.emplace_back("path", "");
945  LeftSidebarNode->Attributes.emplace_back(
946  "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");
947  LeftSidebarNode->Attributes.emplace_back("style", "flex: 0 100%;");
948 
949  MainNode->Children.emplace_back(std::move(LeftSidebarNode));
950 
951  return MainNode;
952 }
953 
954 static llvm::Error GenIndex(const ClangDocContext &CDCtx) {
955  std::error_code FileErr, OK;
956  llvm::SmallString<128> IndexPath;
957  llvm::sys::path::native(CDCtx.OutDirectory, IndexPath);
958  llvm::sys::path::append(IndexPath, "index.html");
959  llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_None);
960  if (FileErr != OK) {
961  return llvm::createStringError(llvm::inconvertibleErrorCode(),
962  "error creating main index: " +
963  FileErr.message());
964  }
965 
966  HTMLFile F;
967 
968  std::vector<std::unique_ptr<TagNode>> HeadNodes =
969  genFileHeadNodes("Index", "", CDCtx);
970  std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName);
971  std::unique_ptr<TagNode> MainNode = genIndexFileMainNode();
972  std::unique_ptr<TagNode> FooterNode = genFileFooterNode();
973 
974  AppendVector(std::move(HeadNodes), F.Children);
975  F.Children.emplace_back(std::move(HeaderNode));
976  F.Children.emplace_back(std::move(MainNode));
977  F.Children.emplace_back(std::move(FooterNode));
978 
979  F.Render(IndexOS);
980 
981  return llvm::Error::success();
982 }
983 
984 static llvm::Error CopyFile(StringRef FilePath, StringRef OutDirectory) {
985  llvm::SmallString<128> PathWrite;
986  llvm::sys::path::native(OutDirectory, PathWrite);
987  llvm::sys::path::append(PathWrite, llvm::sys::path::filename(FilePath));
988  llvm::SmallString<128> PathRead;
989  llvm::sys::path::native(FilePath, PathRead);
990  std::error_code OK;
991  std::error_code FileErr = llvm::sys::fs::copy_file(PathRead, PathWrite);
992  if (FileErr != OK) {
993  return llvm::createStringError(llvm::inconvertibleErrorCode(),
994  "error creating file " +
995  llvm::sys::path::filename(FilePath) +
996  ": " + FileErr.message() + "\n");
997  }
998  return llvm::Error::success();
999 }
1000 
1001 llvm::Error HTMLGenerator::createResources(ClangDocContext &CDCtx) {
1002  auto Err = SerializeIndex(CDCtx);
1003  if (Err)
1004  return Err;
1005  Err = GenIndex(CDCtx);
1006  if (Err)
1007  return Err;
1008 
1009  for (const auto &FilePath : CDCtx.UserStylesheets) {
1010  Err = CopyFile(FilePath, CDCtx.OutDirectory);
1011  if (Err)
1012  return Err;
1013  }
1014  for (const auto &FilePath : CDCtx.FilesToCopy) {
1015  Err = CopyFile(FilePath, CDCtx.OutDirectory);
1016  if (Err)
1017  return Err;
1018  }
1019  return llvm::Error::success();
1020 }
1021 
1022 static GeneratorRegistry::Add<HTMLGenerator> HTML(HTMLGenerator::Format,
1023  "Generator for HTML output.");
1024 
1025 // This anchor is used to force the linker to link in the generated object
1026 // file and thus register the generator.
1027 volatile int HTMLGeneratorAnchorSource = 0;
1028 
1029 } // namespace doc
1030 } // namespace clang
clang::doc::genJsScriptsHTML
static std::vector< std::unique_ptr< TagNode > > genJsScriptsHTML(StringRef InfoPath, const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:288
Base
std::unique_ptr< GlobalCompilationDatabase > Base
Definition: GlobalCompilationDatabaseTests.cpp:85
llvm
Some operations such as code completion produce a set of candidates.
Definition: YAMLGenerator.cpp:31
clang::doc::TypedefInfo
Definition: Representation.h:356
clang::doc::genFileHeadNodes
static std::vector< std::unique_ptr< TagNode > > genFileHeadNodes(StringRef Title, StringRef InfoPath, const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:470
clang::doc::EnumInfo::Members
llvm::SmallVector< EnumValueInfo, 4 > Members
Definition: Representation.h:426
clang::doc::Info::Description
std::vector< CommentInfo > Description
Definition: Representation.h:259
References
unsigned References
Definition: CodeComplete.cpp:183
clang::doc::genEnumMembersBlock
static std::unique_ptr< TagNode > genEnumMembersBlock(const llvm::SmallVector< EnumValueInfo, 4 > &Members)
Definition: HTMLGenerator.cpp:364
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
Type
NodeType Type
Definition: HTMLGenerator.cpp:73
Refs
RefSlab Refs
Definition: SymbolCollectorTests.cpp:312
clang::doc::genInfoFileMainNode
static std::unique_ptr< TagNode > genInfoFileMainNode(StringRef InfoPath, std::vector< std::unique_ptr< TagNode >> &MainContentInnerNodes, const Index &InfoIndex)
Definition: HTMLGenerator.cpp:498
clang::doc::Info::Name
SmallString< 16 > Name
Definition: Representation.h:256
clang::doc::Index
Definition: Representation.h:429
clang::doc::ClangDocContext::Idx
Index Idx
Definition: Representation.h:477
clang::doc::writeFileDefinition
static std::unique_ptr< TagNode > writeFileDefinition(const Location &L, llvm::Optional< StringRef > RepositoryUrl=None)
Definition: HTMLGenerator.cpp:438
clang::doc::FunctionInfo
Definition: Representation.h:304
clang::doc::genReferencesBlock
static std::vector< std::unique_ptr< TagNode > > genReferencesBlock(const std::vector< Reference > &References, llvm::StringRef Title, StringRef ParentPath)
Definition: HTMLGenerator.cpp:419
clang::doc::InfoType
InfoType
Definition: Representation.h:39
clang::doc::getTagType
std::string getTagType(TagTypeKind AS)
Definition: Generators.cpp:29
clang::doc::genFileHeaderNode
static std::unique_ptr< TagNode > genFileHeaderNode(StringRef ProjectName)
Definition: HTMLGenerator.cpp:488
clang::doc::CommentInfo
Definition: Representation.h:49
clang::doc::Reference::Name
SmallString< 16 > Name
Definition: Representation.h:138
clang::doc::ClangDocContext::RepositoryUrl
llvm::Optional< std::string > RepositoryUrl
Definition: Representation.h:469
clang::doc::EnumInfo
Definition: Representation.h:412
Text
std::string Text
Definition: HTMLGenerator.cpp:80
clang::doc::CommentInfo::Kind
SmallString< 16 > Kind
Definition: Representation.h:95
clang::doc::ScopeChildren::Functions
std::vector< FunctionInfo > Functions
Definition: Representation.h:158
Representation.h
clang::doc::RecordInfo::VirtualParents
llvm::SmallVector< Reference, 4 > VirtualParents
Definition: Representation.h:346
clang::doc::genFunctionsBlock
static std::vector< std::unique_ptr< TagNode > > genFunctionsBlock(const std::vector< FunctionInfo > &Functions, const ClangDocContext &CDCtx, StringRef ParentInfoDir)
Definition: HTMLGenerator.cpp:376
clang::doc::genIndexFileMainNode
static std::unique_ptr< TagNode > genIndexFileMainNode()
Definition: HTMLGenerator.cpp:939
clang::doc::genReferenceList
static std::vector< std::unique_ptr< HTMLNode > > genReferenceList(const llvm::SmallVectorImpl< Reference > &Refs, const StringRef &CurrentDirectory)
Definition: HTMLGenerator.cpp:328
RepositoryUrl
static llvm::cl::opt< std::string > RepositoryUrl("repository", llvm::cl::desc(R"( URL of repository that hosts code. Used for links to definition locations.)"), llvm::cl::cat(ClangDocCategory))
clang::doc::RecordInfo::Members
llvm::SmallVector< MemberTypeInfo, 4 > Members
Definition: Representation.h:341
clang::doc::genRecordMembersBlock
static std::vector< std::unique_ptr< TagNode > > genRecordMembersBlock(const llvm::SmallVector< MemberTypeInfo, 4 > &Members, StringRef ParentInfoDir)
Definition: HTMLGenerator.cpp:395
clang::doc::ClangDocContext::ProjectName
std::string ProjectName
Definition: Representation.h:462
clang::doc::Location
Definition: Representation.h:217
clang::doc::Info::Path
llvm::SmallString< 128 > Path
Definition: Representation.h:260
clang::doc::ClangDocContext::UserStylesheets
std::vector< std::string > UserStylesheets
Definition: Representation.h:472
clang::doc::CommentInfo::Children
std::vector< std::unique_ptr< CommentInfo > > Children
Definition: Representation.h:115
Children
std::vector< std::unique_ptr< HTMLNode > > Children
Definition: HTMLGenerator.cpp:91
clang::doc::ScopeChildren::Namespaces
std::vector< Reference > Namespaces
Definition: Representation.h:156
M
const google::protobuf::Message & M
Definition: Server.cpp:309
ns1::ns2::A
@ A
Definition: CategoricalFeature.h:3
clang::doc::ClangDocContext::JsScripts
std::vector< std::string > JsScripts
Definition: Representation.h:474
clang::doc::genHTML
static std::vector< std::unique_ptr< TagNode > > genHTML(const TypedefInfo &I, const ClangDocContext &CDCtx, std::string &InfoTitle)
Definition: HTMLGenerator.cpp:831
Attributes
std::vector< std::pair< std::string, std::string > > Attributes
Definition: HTMLGenerator.cpp:93
clang::doc::HTML
static GeneratorRegistry::Add< HTMLGenerator > HTML(HTMLGenerator::Format, "Generator for HTML output.")
clang::doc::CommentInfo::Text
SmallString< 64 > Text
Definition: Representation.h:100
clang::doc::RecordInfo::Children
ScopeChildren Children
Definition: Representation.h:352
clang::doc::ClangDocContext::OutDirectory
std::string OutDirectory
Definition: Representation.h:464
clang::doc::HTMLGenerator::Format
static const char * Format
Definition: HTMLGenerator.cpp:840
clang::doc::ClangDocContext
Definition: Representation.h:454
clang::doc::Index::JumpToSection
llvm::Optional< SmallString< 16 > > JumpToSection
Definition: Representation.h:440
clang::doc::genEnumsBlock
static std::vector< std::unique_ptr< TagNode > > genEnumsBlock(const std::vector< EnumInfo > &Enums, const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:346
clang::doc::RecordInfo::Parents
llvm::SmallVector< Reference, 4 > Parents
Definition: Representation.h:342
Description
const char * Description
Definition: Dexp.cpp:361
clang::doc::Info::USR
SymbolID USR
Definition: Representation.h:253
clang::doc::FunctionInfo::Access
AccessSpecifier Access
Definition: Representation.h:318
clang::doc::FunctionInfo::Params
llvm::SmallVector< FieldTypeInfo, 4 > Params
Definition: Representation.h:313
clang::doc::getRefType
static std::string getRefType(InfoType IT)
Definition: HTMLGenerator.cpp:886
clang::doc::ScopeChildren::Enums
std::vector< EnumInfo > Enums
Definition: Representation.h:159
clang::doc::RecordInfo
Definition: Representation.h:324
OutDirectory
static llvm::cl::opt< std::string > OutDirectory("output", llvm::cl::desc("Directory for outputting generated files."), llvm::cl::init("docs"), llvm::cl::cat(ClangDocCategory))
clang::doc::TypeInfo::Type
Reference Type
Definition: Representation.h:175
clang::doc::genFileFooterNode
static std::unique_ptr< TagNode > genFileFooterNode()
Definition: HTMLGenerator.cpp:533
Index
const SymbolIndex * Index
Definition: Dexp.cpp:98
clang::doc::Info
A base struct for Infos.
Definition: Representation.h:243
clang::doc::Generator
Definition: Generators.h:24
clang::doc::Reference
Definition: Representation.h:118
clang::doc::Info::IT
const InfoType IT
Definition: Representation.h:255
clang::doc::ScopeChildren::Records
std::vector< Reference > Records
Definition: Representation.h:157
clang::doc::CopyFile
static llvm::Error CopyFile(StringRef FilePath, StringRef OutDirectory)
Definition: HTMLGenerator.cpp:984
clang::doc::NamespaceInfo::Children
ScopeChildren Children
Definition: Representation.h:287
clang::doc::SerializeIndex
static llvm::Error SerializeIndex(ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:904
clang::doc::GenIndex
static llvm::Error GenIndex(const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:954
C
const Criteria C
Definition: FunctionCognitiveComplexityCheck.cpp:93
clang::doc::HTMLGeneratorAnchorSource
volatile int HTMLGeneratorAnchorSource
Definition: HTMLGenerator.cpp:1027
clang::doc::FunctionInfo::ReturnType
TypeInfo ReturnType
Definition: Representation.h:312
clang::doc::genLink
static std::unique_ptr< TagNode > genLink(const Twine &Text, const Twine &Link)
Definition: HTMLGenerator.cpp:302
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::doc::NamespaceInfo
Definition: Representation.h:280
OS
llvm::raw_string_ostream OS
Definition: TraceTests.cpp:160
clang::doc::AppendVector
static void AppendVector(std::vector< Derived > &&New, std::vector< Base > &Original)
Definition: HTMLGenerator.cpp:222
clang::doc::HTMLGenerator
Generator for HTML documentation.
Definition: HTMLGenerator.cpp:838
clang::doc::genReference
static std::unique_ptr< HTMLNode > genReference(const Reference &Type, StringRef CurrentDirectory, llvm::Optional< StringRef > JumpToSection=None)
Definition: HTMLGenerator.cpp:309
clang::doc::genInfoIndexItem
static Index genInfoIndexItem(const std::vector< T > &Infos, StringRef Title)
Definition: HTMLGenerator.cpp:566
clang::doc::RecordInfo::TagType
TagTypeKind TagType
Definition: Representation.h:332
clang::doc::computeRelativePath
static SmallString< 128 > computeRelativePath(StringRef Destination, StringRef Origin)
Definition: HTMLGenerator.cpp:228
Generators.h
clang::doc::genInfoFile
static HTMLFile genInfoFile(StringRef Title, StringRef InfoPath, std::vector< std::unique_ptr< TagNode >> &MainContentNodes, const Index &InfoIndex, const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:544
ProjectName
static llvm::cl::opt< std::string > ProjectName("project-name", llvm::cl::desc("Name of project."), llvm::cl::cat(ClangDocCategory))
clang::doc::ClangDocContext::FilesToCopy
std::vector< std::string > FilesToCopy
Definition: Representation.h:476
llvm::SmallVectorImpl
Definition: NoLintDirectiveHandler.h:23
Out
CompiledFragmentImpl & Out
Definition: ConfigCompile.cpp:99
Tag
HTMLTag Tag
Definition: HTMLGenerator.cpp:90
clang::doc::Index::sort
void sort()
Definition: Representation.cpp:343
clang::doc::SymbolInfo::DefLoc
llvm::Optional< Location > DefLoc
Definition: Representation.h:298
clang::doc::Info::getRelativeFilePath
llvm::SmallString< 64 > getRelativeFilePath(const StringRef &CurrentPath) const
Returns the file path for this Info relative to CurrentPath.
Definition: Representation.cpp:166
clang::doc::EnumInfo::Scoped
bool Scoped
Definition: Representation.h:419
Path
std::vector< HeaderHandle > Path
Definition: PreprocessorTracker.cpp:525
clang::doc::genStylesheetsHTML
static std::vector< std::unique_ptr< TagNode > > genStylesheetsHTML(StringRef InfoPath, const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:271
clang::doc::Index::Children
std::vector< Index > Children
Definition: Representation.h:441