clang-tools  9.0.0
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 "llvm/ADT/StringRef.h"
12 #include "llvm/Support/FileSystem.h"
13 #include "llvm/Support/Path.h"
14 #include <string>
15 
16 using namespace llvm;
17 
18 namespace clang {
19 namespace doc {
20 
21 namespace {
22 
23 class HTMLTag {
24 public:
25  // Any other tag can be added if required
26  enum TagType {
27  TAG_META,
28  TAG_TITLE,
29  TAG_DIV,
30  TAG_H1,
31  TAG_H2,
32  TAG_H3,
33  TAG_P,
34  TAG_UL,
35  TAG_LI,
36  TAG_A,
37  };
38 
39  HTMLTag() = default;
40  constexpr HTMLTag(TagType Value) : Value(Value) {}
41 
42  operator TagType() const { return Value; }
43  operator bool() = delete;
44 
45  bool IsSelfClosing() const;
46 
47  bool HasInlineChildren() const;
48 
49  llvm::SmallString<16> ToString() const;
50 
51 private:
52  TagType Value;
53 };
54 
55 enum NodeType {
56  NODE_TEXT,
57  NODE_TAG,
58 };
59 
60 struct HTMLNode {
61  HTMLNode(NodeType Type) : Type(Type) {}
62  virtual ~HTMLNode() = default;
63 
64  virtual void Render(llvm::raw_ostream &OS, int IndentationLevel) = 0;
65  NodeType Type; // Type of node
66 };
67 
68 struct TextNode : public HTMLNode {
69  TextNode(const Twine &Text, bool Indented = true)
70  : HTMLNode(NodeType::NODE_TEXT), Text(Text.str()), Indented(Indented) {}
71 
72  std::string Text; // Content of node
73  bool Indented; // Indicates if an indentation must be rendered before the text
74  void Render(llvm::raw_ostream &OS, int IndentationLevel) override;
75 };
76 
77 struct TagNode : public HTMLNode {
78  TagNode(HTMLTag Tag)
79  : HTMLNode(NodeType::NODE_TAG), Tag(Tag),
80  InlineChildren(Tag.HasInlineChildren()),
81  SelfClosing(Tag.IsSelfClosing()) {}
82  TagNode(HTMLTag Tag, const Twine &Text) : TagNode(Tag) {
83  Children.emplace_back(
84  llvm::make_unique<TextNode>(Text.str(), !InlineChildren));
85  }
86 
87  HTMLTag Tag; // Name of HTML Tag (p, div, h1)
88  bool InlineChildren; // Indicates if children nodes are rendered in the same
89  // line as itself or if children must rendered in the
90  // next line and with additional indentation
91  bool SelfClosing; // Indicates if tag is self-closing
92  std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
93  llvm::StringMap<llvm::SmallString<16>>
94  Attributes; // List of key-value attributes for tag
95 
96  void Render(llvm::raw_ostream &OS, int IndentationLevel) override;
97 };
98 
99 constexpr const char *kDoctypeDecl = "<!DOCTYPE html>";
100 
101 struct HTMLFile {
102  std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
103  void Render(llvm::raw_ostream &OS) {
104  OS << kDoctypeDecl << "\n";
105  for (const auto &C : Children) {
106  C->Render(OS, 0);
107  OS << "\n";
108  }
109  }
110 };
111 
112 } // namespace
113 
114 bool HTMLTag::IsSelfClosing() const {
115  switch (Value) {
116  case HTMLTag::TAG_META:
117  return true;
118  case HTMLTag::TAG_TITLE:
119  case HTMLTag::TAG_DIV:
120  case HTMLTag::TAG_H1:
121  case HTMLTag::TAG_H2:
122  case HTMLTag::TAG_H3:
123  case HTMLTag::TAG_P:
124  case HTMLTag::TAG_UL:
125  case HTMLTag::TAG_LI:
126  case HTMLTag::TAG_A:
127  return false;
128  }
129  llvm_unreachable("Unhandled HTMLTag::TagType");
130 }
131 
132 bool HTMLTag::HasInlineChildren() const {
133  switch (Value) {
134  case HTMLTag::TAG_META:
135  case HTMLTag::TAG_TITLE:
136  case HTMLTag::TAG_H1:
137  case HTMLTag::TAG_H2:
138  case HTMLTag::TAG_H3:
139  case HTMLTag::TAG_LI:
140  case HTMLTag::TAG_A:
141  return true;
142  case HTMLTag::TAG_DIV:
143  case HTMLTag::TAG_P:
144  case HTMLTag::TAG_UL:
145  return false;
146  }
147  llvm_unreachable("Unhandled HTMLTag::TagType");
148 }
149 
150 llvm::SmallString<16> HTMLTag::ToString() const {
151  switch (Value) {
152  case HTMLTag::TAG_META:
153  return llvm::SmallString<16>("meta");
154  case HTMLTag::TAG_TITLE:
155  return llvm::SmallString<16>("title");
156  case HTMLTag::TAG_DIV:
157  return llvm::SmallString<16>("div");
158  case HTMLTag::TAG_H1:
159  return llvm::SmallString<16>("h1");
160  case HTMLTag::TAG_H2:
161  return llvm::SmallString<16>("h2");
162  case HTMLTag::TAG_H3:
163  return llvm::SmallString<16>("h3");
164  case HTMLTag::TAG_P:
165  return llvm::SmallString<16>("p");
166  case HTMLTag::TAG_UL:
167  return llvm::SmallString<16>("ul");
168  case HTMLTag::TAG_LI:
169  return llvm::SmallString<16>("li");
170  case HTMLTag::TAG_A:
171  return llvm::SmallString<16>("a");
172  }
173  llvm_unreachable("Unhandled HTMLTag::TagType");
174 }
175 
176 void TextNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
177  if (Indented)
178  OS.indent(IndentationLevel * 2);
179  OS << Text;
180 }
181 
182 void TagNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
183  OS.indent(IndentationLevel * 2);
184  OS << "<" << Tag.ToString();
185  for (const auto &A : Attributes)
186  OS << " " << A.getKey() << "=\"" << A.getValue() << "\"";
187  if (SelfClosing) {
188  OS << "/>";
189  return;
190  }
191  OS << ">";
192  if (!InlineChildren)
193  OS << "\n";
194  bool NewLineRendered = true;
195  for (const auto &C : Children) {
196  int ChildrenIndentation =
197  InlineChildren || !NewLineRendered ? 0 : IndentationLevel + 1;
198  C->Render(OS, ChildrenIndentation);
199  if (!InlineChildren && (C == Children.back() ||
200  (C->Type != NodeType::NODE_TEXT ||
201  (&C + 1)->get()->Type != NodeType::NODE_TEXT))) {
202  OS << "\n";
203  NewLineRendered = true;
204  } else
205  NewLineRendered = false;
206  }
207  if (!InlineChildren)
208  OS.indent(IndentationLevel * 2);
209  OS << "</" << Tag.ToString() << ">";
210 }
211 
212 template <typename Derived, typename Base,
213  typename = std::enable_if<std::is_base_of<Derived, Base>::value>>
214 static void AppendVector(std::vector<Derived> &&New,
215  std::vector<Base> &Original) {
216  std::move(New.begin(), New.end(), std::back_inserter(Original));
217 }
218 
219 // Compute the relative path that names the file path relative to the given
220 // directory.
221 static SmallString<128> computeRelativePath(StringRef FilePath,
222  StringRef Directory) {
223  StringRef Path = FilePath;
224  while (!Path.empty()) {
225  if (Directory == Path)
226  return FilePath.substr(Path.size());
227  Path = llvm::sys::path::parent_path(Path);
228  }
229 
230  StringRef Dir = Directory;
231  SmallString<128> Result;
232  while (!Dir.empty()) {
233  if (Dir == FilePath)
234  break;
235  Dir = llvm::sys::path::parent_path(Dir);
236  llvm::sys::path::append(Result, "..");
237  }
238  llvm::sys::path::append(Result, FilePath.substr(Dir.size()));
239  return Result;
240 }
241 
242 // HTML generation
243 
244 static std::unique_ptr<TagNode> genLink(const Twine &Text, const Twine &Link) {
245  auto LinkNode = llvm::make_unique<TagNode>(HTMLTag::TAG_A, Text);
246  LinkNode->Attributes.try_emplace("href", Link.str());
247  return LinkNode;
248 }
249 
250 static std::unique_ptr<HTMLNode> genTypeReference(const Reference &Type,
251  StringRef CurrentDirectory) {
252  if (Type.Path.empty())
253  return llvm::make_unique<TextNode>(Type.Name);
254  llvm::SmallString<128> Path =
255  computeRelativePath(Type.Path, CurrentDirectory);
256  llvm::sys::path::append(Path, Type.Name + ".html");
257  return genLink(Type.Name, Path);
258 }
259 
260 static std::vector<std::unique_ptr<HTMLNode>>
261 genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs,
262  const StringRef &CurrentDirectory) {
263  std::vector<std::unique_ptr<HTMLNode>> Out;
264  for (const auto &R : Refs) {
265  if (&R != Refs.begin())
266  Out.emplace_back(llvm::make_unique<TextNode>(", "));
267  Out.emplace_back(genTypeReference(R, CurrentDirectory));
268  }
269  return Out;
270 }
271 
272 static std::vector<std::unique_ptr<TagNode>> genHTML(const EnumInfo &I);
273 static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I,
274  StringRef ParentInfoDir);
275 
276 static std::vector<std::unique_ptr<TagNode>>
277 genEnumsBlock(const std::vector<EnumInfo> &Enums) {
278  if (Enums.empty())
279  return {};
280 
281  std::vector<std::unique_ptr<TagNode>> Out;
282  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H2, "Enums"));
283  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_DIV));
284  auto &DivBody = Out.back();
285  for (const auto &E : Enums) {
286  std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(E);
287  AppendVector(std::move(Nodes), DivBody->Children);
288  }
289  return Out;
290 }
291 
292 static std::unique_ptr<TagNode>
293 genEnumMembersBlock(const llvm::SmallVector<SmallString<16>, 4> &Members) {
294  if (Members.empty())
295  return nullptr;
296 
297  auto List = llvm::make_unique<TagNode>(HTMLTag::TAG_UL);
298  for (const auto &M : Members)
299  List->Children.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_LI, M));
300  return List;
301 }
302 
303 static std::vector<std::unique_ptr<TagNode>>
304 genFunctionsBlock(const std::vector<FunctionInfo> &Functions,
305  StringRef ParentInfoDir) {
306  if (Functions.empty())
307  return {};
308 
309  std::vector<std::unique_ptr<TagNode>> Out;
310  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H2, "Functions"));
311  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_DIV));
312  auto &DivBody = Out.back();
313  for (const auto &F : Functions) {
314  std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(F, ParentInfoDir);
315  AppendVector(std::move(Nodes), DivBody->Children);
316  }
317  return Out;
318 }
319 
320 static std::vector<std::unique_ptr<TagNode>>
321 genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members,
322  StringRef ParentInfoDir) {
323  if (Members.empty())
324  return {};
325 
326  std::vector<std::unique_ptr<TagNode>> Out;
327  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H2, "Members"));
328  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_UL));
329  auto &ULBody = Out.back();
330  for (const auto &M : Members) {
331  std::string Access = getAccess(M.Access);
332  if (Access != "")
333  Access = Access + " ";
334  auto LIBody = llvm::make_unique<TagNode>(HTMLTag::TAG_LI);
335  LIBody->Children.emplace_back(llvm::make_unique<TextNode>(Access));
336  LIBody->Children.emplace_back(genTypeReference(M.Type, ParentInfoDir));
337  LIBody->Children.emplace_back(llvm::make_unique<TextNode>(" " + M.Name));
338  ULBody->Children.emplace_back(std::move(LIBody));
339  }
340  return Out;
341 }
342 
343 static std::vector<std::unique_ptr<TagNode>>
344 genReferencesBlock(const std::vector<Reference> &References,
345  llvm::StringRef Title) {
346  if (References.empty())
347  return {};
348 
349  std::vector<std::unique_ptr<TagNode>> Out;
350  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H2, Title));
351  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_UL));
352  auto &ULBody = Out.back();
353  for (const auto &R : References)
354  ULBody->Children.emplace_back(
355  llvm::make_unique<TagNode>(HTMLTag::TAG_LI, R.Name));
356  return Out;
357 }
358 
359 static std::unique_ptr<TagNode> writeFileDefinition(const Location &L) {
360  return llvm::make_unique<TagNode>(
361  HTMLTag::TAG_P,
362  "Defined at line " + std::to_string(L.LineNumber) + " of " + L.Filename);
363 }
364 
365 static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
366  if (I.Kind == "FullComment") {
367  auto FullComment = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
368  for (const auto &Child : I.Children) {
369  std::unique_ptr<HTMLNode> Node = genHTML(*Child);
370  if (Node)
371  FullComment->Children.emplace_back(std::move(Node));
372  }
373  return std::move(FullComment);
374  } else if (I.Kind == "ParagraphComment") {
375  auto ParagraphComment = llvm::make_unique<TagNode>(HTMLTag::TAG_P);
376  for (const auto &Child : I.Children) {
377  std::unique_ptr<HTMLNode> Node = genHTML(*Child);
378  if (Node)
379  ParagraphComment->Children.emplace_back(std::move(Node));
380  }
381  if (ParagraphComment->Children.empty())
382  return nullptr;
383  return std::move(ParagraphComment);
384  } else if (I.Kind == "TextComment") {
385  if (I.Text == "")
386  return nullptr;
387  return llvm::make_unique<TextNode>(I.Text, true);
388  }
389  return nullptr;
390 }
391 
392 static std::unique_ptr<TagNode> genHTML(const std::vector<CommentInfo> &C) {
393  auto CommentBlock = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
394  for (const auto &Child : C) {
395  if (std::unique_ptr<HTMLNode> Node = genHTML(Child))
396  CommentBlock->Children.emplace_back(std::move(Node));
397  }
398  return CommentBlock;
399 }
400 
401 static std::vector<std::unique_ptr<TagNode>> genHTML(const EnumInfo &I) {
402  std::vector<std::unique_ptr<TagNode>> Out;
403  std::string EnumType;
404  if (I.Scoped)
405  EnumType = "enum class ";
406  else
407  EnumType = "enum ";
408 
409  Out.emplace_back(
410  llvm::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.Name));
411 
412  std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members);
413  if (Node)
414  Out.emplace_back(std::move(Node));
415 
416  if (I.DefLoc)
417  Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
418 
419  std::string Description;
420  if (!I.Description.empty())
421  Out.emplace_back(genHTML(I.Description));
422 
423  return Out;
424 }
425 
426 static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I,
427  StringRef ParentInfoDir) {
428  std::vector<std::unique_ptr<TagNode>> Out;
429  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name));
430 
431  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P));
432  auto &FunctionHeader = Out.back();
433 
434  std::string Access = getAccess(I.Access);
435  if (Access != "")
436  FunctionHeader->Children.emplace_back(
437  llvm::make_unique<TextNode>(Access + " "));
438  if (I.ReturnType.Type.Name != "") {
439  FunctionHeader->Children.emplace_back(
440  genTypeReference(I.ReturnType.Type, ParentInfoDir));
441  FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(" "));
442  }
443  FunctionHeader->Children.emplace_back(
444  llvm::make_unique<TextNode>(I.Name + "("));
445 
446  for (const auto &P : I.Params) {
447  if (&P != I.Params.begin())
448  FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(", "));
449  FunctionHeader->Children.emplace_back(
450  genTypeReference(P.Type, ParentInfoDir));
451  FunctionHeader->Children.emplace_back(
452  llvm::make_unique<TextNode>(" " + P.Name));
453  }
454  FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(")"));
455 
456  if (I.DefLoc)
457  Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
458 
459  std::string Description;
460  if (!I.Description.empty())
461  Out.emplace_back(genHTML(I.Description));
462 
463  return Out;
464 }
465 
466 static std::vector<std::unique_ptr<TagNode>> genHTML(const NamespaceInfo &I,
467  std::string &InfoTitle) {
468  std::vector<std::unique_ptr<TagNode>> Out;
469  if (I.Name.str() == "")
470  InfoTitle = "Global Namespace";
471  else
472  InfoTitle = ("namespace " + I.Name).str();
473 
474  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
475 
476  std::string Description;
477  if (!I.Description.empty())
478  Out.emplace_back(genHTML(I.Description));
479 
480  std::vector<std::unique_ptr<TagNode>> ChildNamespaces =
481  genReferencesBlock(I.ChildNamespaces, "Namespaces");
482  AppendVector(std::move(ChildNamespaces), Out);
483  std::vector<std::unique_ptr<TagNode>> ChildRecords =
484  genReferencesBlock(I.ChildRecords, "Records");
485  AppendVector(std::move(ChildRecords), Out);
486 
487  std::vector<std::unique_ptr<TagNode>> ChildFunctions =
489  AppendVector(std::move(ChildFunctions), Out);
490  std::vector<std::unique_ptr<TagNode>> ChildEnums =
492  AppendVector(std::move(ChildEnums), Out);
493 
494  return Out;
495 }
496 
497 static std::vector<std::unique_ptr<TagNode>> genHTML(const RecordInfo &I,
498  std::string &InfoTitle) {
499  std::vector<std::unique_ptr<TagNode>> Out;
500  InfoTitle = (getTagType(I.TagType) + " " + I.Name).str();
501  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
502 
503  if (I.DefLoc)
504  Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
505 
506  std::string Description;
507  if (!I.Description.empty())
508  Out.emplace_back(genHTML(I.Description));
509 
510  std::vector<std::unique_ptr<HTMLNode>> Parents =
512  std::vector<std::unique_ptr<HTMLNode>> VParents =
514  if (!Parents.empty() || !VParents.empty()) {
515  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P));
516  auto &PBody = Out.back();
517  PBody->Children.emplace_back(llvm::make_unique<TextNode>("Inherits from "));
518  if (Parents.empty())
519  AppendVector(std::move(VParents), PBody->Children);
520  else if (VParents.empty())
521  AppendVector(std::move(Parents), PBody->Children);
522  else {
523  AppendVector(std::move(Parents), PBody->Children);
524  PBody->Children.emplace_back(llvm::make_unique<TextNode>(", "));
525  AppendVector(std::move(VParents), PBody->Children);
526  }
527  }
528 
529  std::vector<std::unique_ptr<TagNode>> Members =
531  AppendVector(std::move(Members), Out);
532  std::vector<std::unique_ptr<TagNode>> ChildRecords =
533  genReferencesBlock(I.ChildRecords, "Records");
534  AppendVector(std::move(ChildRecords), Out);
535 
536  std::vector<std::unique_ptr<TagNode>> ChildFunctions =
538  AppendVector(std::move(ChildFunctions), Out);
539  std::vector<std::unique_ptr<TagNode>> ChildEnums =
541  AppendVector(std::move(ChildEnums), Out);
542 
543  return Out;
544 }
545 
546 /// Generator for HTML documentation.
547 class HTMLGenerator : public Generator {
548 public:
549  static const char *Format;
550 
551  llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS) override;
552 };
553 
554 const char *HTMLGenerator::Format = "html";
555 
556 llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS) {
557  HTMLFile F;
558 
559  auto MetaNode = llvm::make_unique<TagNode>(HTMLTag::TAG_META);
560  MetaNode->Attributes.try_emplace("charset", "utf-8");
561  F.Children.emplace_back(std::move(MetaNode));
562 
563  std::string InfoTitle;
564  Info CastedInfo;
565  auto MainContentNode = llvm::make_unique<TagNode>(HTMLTag::TAG_DIV);
566  switch (I->IT) {
567  case InfoType::IT_namespace: {
568  std::vector<std::unique_ptr<TagNode>> Nodes =
569  genHTML(*static_cast<clang::doc::NamespaceInfo *>(I), InfoTitle);
570  AppendVector(std::move(Nodes), MainContentNode->Children);
571  break;
572  }
573  case InfoType::IT_record: {
574  std::vector<std::unique_ptr<TagNode>> Nodes =
575  genHTML(*static_cast<clang::doc::RecordInfo *>(I), InfoTitle);
576  AppendVector(std::move(Nodes), MainContentNode->Children);
577  break;
578  }
579  case InfoType::IT_enum: {
580  std::vector<std::unique_ptr<TagNode>> Nodes =
581  genHTML(*static_cast<clang::doc::EnumInfo *>(I));
582  AppendVector(std::move(Nodes), MainContentNode->Children);
583  break;
584  }
585  case InfoType::IT_function: {
586  std::vector<std::unique_ptr<TagNode>> Nodes =
587  genHTML(*static_cast<clang::doc::FunctionInfo *>(I), "");
588  AppendVector(std::move(Nodes), MainContentNode->Children);
589  break;
590  }
591  case InfoType::IT_default:
592  return llvm::make_error<llvm::StringError>("Unexpected info type.\n",
593  llvm::inconvertibleErrorCode());
594  }
595 
596  F.Children.emplace_back(
597  llvm::make_unique<TagNode>(HTMLTag::TAG_TITLE, InfoTitle));
598  F.Children.emplace_back(std::move(MainContentNode));
599  F.Render(OS);
600 
601  return llvm::Error::success();
602 }
603 
604 static GeneratorRegistry::Add<HTMLGenerator> HTML(HTMLGenerator::Format,
605  "Generator for HTML output.");
606 
607 // This anchor is used to force the linker to link in the generated object
608 // file and thus register the generator.
609 volatile int HTMLGeneratorAnchorSource = 0;
610 
611 } // namespace doc
612 } // namespace clang
static std::unique_ptr< HTMLNode > genTypeReference(const Reference &Type, StringRef CurrentDirectory)
Some operations such as code completion produce a set of candidates.
std::string Text
llvm::StringMap< llvm::SmallString< 16 > > Attributes
volatile int HTMLGeneratorAnchorSource
static std::unique_ptr< TagNode > writeFileDefinition(const Location &L)
static SmallString< 128 > computeRelativePath(StringRef FilePath, StringRef Directory)
HTMLTag Tag
SmallString< 16 > Name
llvm::Optional< Location > DefLoc
bool InlineChildren
std::vector< FunctionInfo > ChildFunctions
std::vector< FunctionInfo > ChildFunctions
std::vector< EnumInfo > ChildEnums
std::vector< HeaderHandle > Path
std::vector< Reference > ChildRecords
static const char * Format
static void AppendVector(std::vector< Derived > &&New, std::vector< Base > &Original)
llvm::SmallVector< Reference, 4 > VirtualParents
std::string getAccess(AccessSpecifier AS)
Definition: Generators.cpp:30
llvm::SmallVector< FieldTypeInfo, 4 > Params
static std::unique_ptr< TagNode > genLink(const Twine &Text, const Twine &Link)
static std::vector< std::unique_ptr< TagNode > > genHTML(const RecordInfo &I, std::string &InfoTitle)
llvm::SmallVector< SmallString< 16 >, 4 > Members
static std::vector< std::unique_ptr< TagNode > > genReferencesBlock(const std::vector< Reference > &References, llvm::StringRef Title)
std::vector< CommentInfo > Description
bool SelfClosing
std::string getTagType(TagTypeKind AS)
Definition: Generators.cpp:44
SmallString< 16 > Name
A base struct for Infos.
llvm::SmallString< 128 > Path
llvm::SmallVector< Reference, 4 > Parents
static std::vector< std::unique_ptr< TagNode > > genFunctionsBlock(const std::vector< FunctionInfo > &Functions, StringRef ParentInfoDir)
Generator for HTML documentation.
llvm::StringRef Directory
std::vector< std::unique_ptr< HTMLNode > > Children
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
unsigned References
static std::vector< std::unique_ptr< TagNode > > genEnumsBlock(const std::vector< EnumInfo > &Enums)
std::vector< Reference > ChildNamespaces
std::vector< Reference > ChildRecords
SmallString< 32 > Filename
const InfoType IT
std::vector< EnumInfo > ChildEnums
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: Rename.cpp:36
llvm::SmallVector< MemberTypeInfo, 4 > Members
bool Indented
SmallString< 16 > Kind
const char * Description
Definition: Dexp.cpp:257
RefSlab Refs
std::unique_ptr< GlobalCompilationDatabase > Base
static GeneratorRegistry::Add< HTMLGenerator > HTML(HTMLGenerator::Format, "Generator for HTML output.")
std::vector< std::unique_ptr< CommentInfo > > Children
SmallString< 64 > Text
static std::vector< std::unique_ptr< HTMLNode > > genReferenceList(const llvm::SmallVectorImpl< Reference > &Refs, const StringRef &CurrentDirectory)
static std::vector< std::unique_ptr< TagNode > > genRecordMembersBlock(const llvm::SmallVector< MemberTypeInfo, 4 > &Members, StringRef ParentInfoDir)
llvm::SmallString< 128 > Path
NodeType Type
static std::unique_ptr< TagNode > genEnumMembersBlock(const llvm::SmallVector< SmallString< 16 >, 4 > &Members)