clang-tools 10.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 "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", 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", 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() && !Type.IsInGlobalNamespace) {
312 if (!JumpToSection)
313 return std::make_unique<TextNode>(Type.Name);
314 else
315 return genLink(Type.Name, "#" + JumpToSection.getValue());
316 }
317 llvm::SmallString<128> Path =
318 computeRelativePath(Type.Path, CurrentDirectory);
319 llvm::sys::path::append(Path, Type.Name + ".html");
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.getValue()).str();
324 return genLink(Type.Name, Path);
325 }
326
327 static std::vector<std::unique_ptr<HTMLNode>>
328 genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs,
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<SmallString<16>, 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(std::make_unique<TagNode>(HTMLTag::TAG_LI, M));
371 return List;
372 }
373
374 static std::vector<std::unique_ptr<TagNode>>
375 genFunctionsBlock(const std::vector<FunctionInfo> &Functions,
376 const ClangDocContext &CDCtx, StringRef ParentInfoDir) {
377 if (Functions.empty())
378 return {};
379
380 std::vector<std::unique_ptr<TagNode>> Out;
381 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Functions"));
382 Out.back()->Attributes.emplace_back("id", "Functions");
383 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV));
384 auto &DivBody = Out.back();
385 for (const auto &F : Functions) {
386 std::vector<std::unique_ptr<TagNode>> Nodes =
387 genHTML(F, CDCtx, ParentInfoDir);
388 AppendVector(std::move(Nodes), DivBody->Children);
389 }
390 return Out;
391 }
392
393 static std::vector<std::unique_ptr<TagNode>>
394 genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members,
395 StringRef ParentInfoDir) {
396 if (Members.empty())
397 return {};
398
399 std::vector<std::unique_ptr<TagNode>> Out;
400 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Members"));
401 Out.back()->Attributes.emplace_back("id", "Members");
402 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
403 auto &ULBody = Out.back();
404 for (const auto &M : Members) {
405 std::string Access = getAccess(M.Access);
406 if (Access != "")
407 Access = Access + " ";
408 auto LIBody = std::make_unique<TagNode>(HTMLTag::TAG_LI);
409 LIBody->Children.emplace_back(std::make_unique<TextNode>(Access));
410 LIBody->Children.emplace_back(genReference(M.Type, ParentInfoDir));
411 LIBody->Children.emplace_back(std::make_unique<TextNode>(" " + M.Name));
412 ULBody->Children.emplace_back(std::move(LIBody));
413 }
414 return Out;
415 }
416
417 static std::vector<std::unique_ptr<TagNode>>
418 genReferencesBlock(const std::vector<Reference> &References,
419 llvm::StringRef Title, StringRef ParentPath) {
420 if (References.empty())
421 return {};
422
423 std::vector<std::unique_ptr<TagNode>> Out;
424 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, Title));
425 Out.back()->Attributes.emplace_back("id", Title);
426 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
427 auto &ULBody = Out.back();
428 for (const auto &R : References) {
429 auto LiNode = std::make_unique<TagNode>(HTMLTag::TAG_LI);
430 LiNode->Children.emplace_back(genReference(R, ParentPath));
431 ULBody->Children.emplace_back(std::move(LiNode));
432 }
433 return Out;
434 }
435
436 static std::unique_ptr<TagNode>
437 writeFileDefinition(const Location &L,
438 llvm::Optional<StringRef> RepositoryUrl = None) {
439 if (!L.IsFileInRootDir || !RepositoryUrl)
440 return std::make_unique<TagNode>(
441 HTMLTag::TAG_P, "Defined at line " + std::to_string(L.LineNumber) +
442 " of file " + L.Filename);
443 SmallString<128> FileURL(RepositoryUrl.getValue());
444 llvm::sys::path::append(FileURL, llvm::sys::path::Style::posix, L.Filename);
445 auto Node = std::make_unique<TagNode>(HTMLTag::TAG_P);
446 Node->Children.emplace_back(std::make_unique<TextNode>("Defined at line "));
447 auto LocNumberNode =
448 std::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.LineNumber));
449 // The links to a specific line in the source code use the github /
450 // googlesource notation so it won't work for all hosting pages.
451 LocNumberNode->Attributes.emplace_back(
452 "href", (FileURL + "#" + std::to_string(L.LineNumber)).str());
453 Node->Children.emplace_back(std::move(LocNumberNode));
454 Node->Children.emplace_back(std::make_unique<TextNode>(" of file "));
455 auto LocFileNode = std::make_unique<TagNode>(
456 HTMLTag::TAG_A, llvm::sys::path::filename(FileURL));
457 LocFileNode->Attributes.emplace_back("href", FileURL.str());
458 Node->Children.emplace_back(std::move(LocFileNode));
459 return Node;
460 }
461
462 static std::vector<std::unique_ptr<TagNode>>
463 genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList);
464
465 // Generates a list of child nodes for the HTML head tag
466 // It contains a meta node, link nodes to import CSS files, and script nodes to
467 // import JS files
468 static std::vector<std::unique_ptr<TagNode>>
469 genFileHeadNodes(StringRef Title, StringRef InfoPath,
470 const ClangDocContext &CDCtx) {
471 std::vector<std::unique_ptr<TagNode>> Out;
472 auto MetaNode = std::make_unique<TagNode>(HTMLTag::TAG_META);
473 MetaNode->Attributes.emplace_back("charset", "utf-8");
474 Out.emplace_back(std::move(MetaNode));
475 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_TITLE, Title));
476 std::vector<std::unique_ptr<TagNode>> StylesheetsNodes =
477 genStylesheetsHTML(InfoPath, CDCtx);
478 AppendVector(std::move(StylesheetsNodes), Out);
479 std::vector<std::unique_ptr<TagNode>> JsNodes =
480 genJsScriptsHTML(InfoPath, CDCtx);
481 AppendVector(std::move(JsNodes), Out);
482 return Out;
483 }
484
485 // Generates a header HTML node that can be used for any file
486 // It contains the project name
487 static std::unique_ptr<TagNode> genFileHeaderNode(StringRef ProjectName) {
488 auto HeaderNode = std::make_unique<TagNode>(HTMLTag::TAG_HEADER, ProjectName);
489 HeaderNode->Attributes.emplace_back("id", "project-title");
490 return HeaderNode;
491 }
492
493 // Generates a main HTML node that has all the main content of an info file
494 // It contains both indexes and the info's documented information
495 // This function should only be used for the info files (not for the file that
496 // only has the general index)
497 static std::unique_ptr<TagNode> genInfoFileMainNode(
498 StringRef InfoPath,
499 std::vector<std::unique_ptr<TagNode>> &MainContentInnerNodes,
500 const Index &InfoIndex) {
501 auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
502
503 auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
504 LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left");
505 LeftSidebarNode->Attributes.emplace_back("path", InfoPath);
506 LeftSidebarNode->Attributes.emplace_back(
507 "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");
508
509 auto MainContentNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
510 MainContentNode->Attributes.emplace_back("id", "main-content");
511 MainContentNode->Attributes.emplace_back(
512 "class", "col-xs-12 col-sm-9 col-md-8 main-content");
513 AppendVector(std::move(MainContentInnerNodes), MainContentNode->Children);
514
515 auto RightSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
516 RightSidebarNode->Attributes.emplace_back("id", "sidebar-right");
517 RightSidebarNode->Attributes.emplace_back(
518 "class", "col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right");
519 std::vector<std::unique_ptr<TagNode>> InfoIndexHTML =
520 genHTML(InfoIndex, InfoPath, true);
521 AppendVector(std::move(InfoIndexHTML), RightSidebarNode->Children);
522
523 MainNode->Children.emplace_back(std::move(LeftSidebarNode));
524 MainNode->Children.emplace_back(std::move(MainContentNode));
525 MainNode->Children.emplace_back(std::move(RightSidebarNode));
526
527 return MainNode;
528 }
529
530 // Generates a footer HTML node that can be used for any file
531 // It contains clang-doc's version
532 static std::unique_ptr<TagNode> genFileFooterNode() {
533 auto FooterNode = std::make_unique<TagNode>(HTMLTag::TAG_FOOTER);
534 auto SpanNode = std::make_unique<TagNode>(
535 HTMLTag::TAG_SPAN, clang::getClangToolFullVersion("clang-doc"));
536 SpanNode->Attributes.emplace_back("class", "no-break");
537 FooterNode->Children.emplace_back(std::move(SpanNode));
538 return FooterNode;
539 }
540
541 // Generates a complete HTMLFile for an Info
542 static HTMLFile
543 genInfoFile(StringRef Title, StringRef InfoPath,
544 std::vector<std::unique_ptr<TagNode>> &MainContentNodes,
545 const Index &InfoIndex, const ClangDocContext &CDCtx) {
546 HTMLFile F;
547
548 std::vector<std::unique_ptr<TagNode>> HeadNodes =
549 genFileHeadNodes(Title, InfoPath, CDCtx);
550 std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName);
551 std::unique_ptr<TagNode> MainNode =
552 genInfoFileMainNode(InfoPath, MainContentNodes, InfoIndex);
553 std::unique_ptr<TagNode> FooterNode = genFileFooterNode();
554
555 AppendVector(std::move(HeadNodes), F.Children);
556 F.Children.emplace_back(std::move(HeaderNode));
557 F.Children.emplace_back(std::move(MainNode));
558 F.Children.emplace_back(std::move(FooterNode));
559
560 return F;
561 }
562
563 template <typename T,
564 typename = std::enable_if<std::is_base_of<T, Info>::value>>
565 static Index genInfoIndexItem(const std::vector<T> &Infos, StringRef Title) {
566 Index Idx(Title, Title);
567 for (const auto &C : Infos)
568 Idx.Children.emplace_back(C.extractName(),
569 llvm::toHex(llvm::toStringRef(C.USR)));
570 return Idx;
571 }
572
573 static std::vector<std::unique_ptr<TagNode>>
574 genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList) {
575 std::vector<std::unique_ptr<TagNode>> Out;
576 if (!Index.Name.empty()) {
577 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_SPAN));
578 auto &SpanBody = Out.back();
579 if (!Index.JumpToSection)
580 SpanBody->Children.emplace_back(genReference(Index, InfoPath));
581 else
582 SpanBody->Children.emplace_back(genReference(
583 Index, InfoPath, StringRef{Index.JumpToSection.getValue()}));
584 }
585 if (Index.Children.empty())
586 return Out;
587 // Only the outermost list should use ol, the others should use ul
588 HTMLTag ListHTMLTag = IsOutermostList ? HTMLTag::TAG_OL : HTMLTag::TAG_UL;
589 Out.emplace_back(std::make_unique<TagNode>(ListHTMLTag));
590 const auto &UlBody = Out.back();
591 for (const auto &C : Index.Children) {
592 auto LiBody = std::make_unique<TagNode>(HTMLTag::TAG_LI);
593 std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(C, InfoPath, false);
594 AppendVector(std::move(Nodes), LiBody->Children);
595 UlBody->Children.emplace_back(std::move(LiBody));
596 }
597 return Out;
598 }
599
600 static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
601 if (I.Kind == "FullComment") {
602 auto FullComment = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
603 for (const auto &Child : I.Children) {
604 std::unique_ptr<HTMLNode> Node = genHTML(*Child);
605 if (Node)
606 FullComment->Children.emplace_back(std::move(Node));
607 }
608 return std::move(FullComment);
609 } else if (I.Kind == "ParagraphComment") {
610 auto ParagraphComment = std::make_unique<TagNode>(HTMLTag::TAG_P);
611 for (const auto &Child : I.Children) {
612 std::unique_ptr<HTMLNode> Node = genHTML(*Child);
613 if (Node)
614 ParagraphComment->Children.emplace_back(std::move(Node));
615 }
616 if (ParagraphComment->Children.empty())
617 return nullptr;
618 return std::move(ParagraphComment);
619 } else if (I.Kind == "TextComment") {
620 if (I.Text == "")
621 return nullptr;
622 return std::make_unique<TextNode>(I.Text);
623 }
624 return nullptr;
625 }
626
627 static std::unique_ptr<TagNode> genHTML(const std::vector<CommentInfo> &C) {
628 auto CommentBlock = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
629 for (const auto &Child : C) {
630 if (std::unique_ptr<HTMLNode> Node = genHTML(Child))
631 CommentBlock->Children.emplace_back(std::move(Node));
632 }
633 return CommentBlock;
634 }
635
636 static std::vector<std::unique_ptr<TagNode>>
637 genHTML(const EnumInfo &I, const ClangDocContext &CDCtx) {
638 std::vector<std::unique_ptr<TagNode>> Out;
639 std::string EnumType;
640 if (I.Scoped)
641 EnumType = "enum class ";
642 else
643 EnumType = "enum ";
644
645 Out.emplace_back(
646 std::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.Name));
647 Out.back()->Attributes.emplace_back("id",
648 llvm::toHex(llvm::toStringRef(I.USR)));
649
650 std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members);
651 if (Node)
652 Out.emplace_back(std::move(Node));
653
654 if (I.DefLoc) {
655 if (!CDCtx.RepositoryUrl)
656 Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
657 else
658 Out.emplace_back(writeFileDefinition(
659 I.DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()}));
660 }
661
662 std::string Description;
663 if (!I.Description.empty())
664 Out.emplace_back(genHTML(I.Description));
665
666 return Out;
667 }
668
669 static std::vector<std::unique_ptr<TagNode>>
670 genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx,
671 StringRef ParentInfoDir) {
672 std::vector<std::unique_ptr<TagNode>> Out;
673 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name));
674 // USR is used as id for functions instead of name to disambiguate function
675 // overloads.
676 Out.back()->Attributes.emplace_back("id",
677 llvm::toHex(llvm::toStringRef(I.USR)));
678
679 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
680 auto &FunctionHeader = Out.back();
681
682 std::string Access = getAccess(I.Access);
683 if (Access != "")
684 FunctionHeader->Children.emplace_back(
685 std::make_unique<TextNode>(Access + " "));
686 if (I.ReturnType.Type.Name != "") {
687 FunctionHeader->Children.emplace_back(
688 genReference(I.ReturnType.Type, ParentInfoDir));
689 FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(" "));
690 }
691 FunctionHeader->Children.emplace_back(
692 std::make_unique<TextNode>(I.Name + "("));
693
694 for (const auto &P : I.Params) {
695 if (&P != I.Params.begin())
696 FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(", "));
697 FunctionHeader->Children.emplace_back(genReference(P.Type, ParentInfoDir));
698 FunctionHeader->Children.emplace_back(
699 std::make_unique<TextNode>(" " + P.Name));
700 }
701 FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(")"));
702
703 if (I.DefLoc) {
704 if (!CDCtx.RepositoryUrl)
705 Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
706 else
707 Out.emplace_back(writeFileDefinition(
708 I.DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()}));
709 }
710
711 std::string Description;
712 if (!I.Description.empty())
713 Out.emplace_back(genHTML(I.Description));
714
715 return Out;
716 }
717
718 static std::vector<std::unique_ptr<TagNode>>
719 genHTML(const NamespaceInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx,
720 std::string &InfoTitle) {
721 std::vector<std::unique_ptr<TagNode>> Out;
722 if (I.Name.str() == "")
723 InfoTitle = "Global Namespace";
724 else
725 InfoTitle = ("namespace " + I.Name).str();
726
727 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
728
729 std::string Description;
730 if (!I.Description.empty())
731 Out.emplace_back(genHTML(I.Description));
732
733 std::vector<std::unique_ptr<TagNode>> ChildNamespaces =
734 genReferencesBlock(I.ChildNamespaces, "Namespaces", I.Path);
735 AppendVector(std::move(ChildNamespaces), Out);
736 std::vector<std::unique_ptr<TagNode>> ChildRecords =
737 genReferencesBlock(I.ChildRecords, "Records", I.Path);
738 AppendVector(std::move(ChildRecords), Out);
739
740 std::vector<std::unique_ptr<TagNode>> ChildFunctions =
741 genFunctionsBlock(I.ChildFunctions, CDCtx, I.Path);
742 AppendVector(std::move(ChildFunctions), Out);
743 std::vector<std::unique_ptr<TagNode>> ChildEnums =
744 genEnumsBlock(I.ChildEnums, CDCtx);
745 AppendVector(std::move(ChildEnums), Out);
746
747 if (!I.ChildNamespaces.empty())
748 InfoIndex.Children.emplace_back("Namespaces", "Namespaces");
749 if (!I.ChildRecords.empty())
750 InfoIndex.Children.emplace_back("Records", "Records");
751 if (!I.ChildFunctions.empty())
752 InfoIndex.Children.emplace_back(
753 genInfoIndexItem(I.ChildFunctions, "Functions"));
754 if (!I.ChildEnums.empty())
755 InfoIndex.Children.emplace_back(genInfoIndexItem(I.ChildEnums, "Enums"));
756
757 return Out;
758 }
759
760 static std::vector<std::unique_ptr<TagNode>>
761 genHTML(const RecordInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx,
762 std::string &InfoTitle) {
763 std::vector<std::unique_ptr<TagNode>> Out;
764 InfoTitle = (getTagType(I.TagType) + " " + I.Name).str();
765 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
766
767 if (I.DefLoc) {
768 if (!CDCtx.RepositoryUrl)
769 Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
770 else
771 Out.emplace_back(writeFileDefinition(
772 I.DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()}));
773 }
774
775 std::string Description;
776 if (!I.Description.empty())
777 Out.emplace_back(genHTML(I.Description));
778
779 std::vector<std::unique_ptr<HTMLNode>> Parents =
780 genReferenceList(I.Parents, I.Path);
781 std::vector<std::unique_ptr<HTMLNode>> VParents =
782 genReferenceList(I.VirtualParents, I.Path);
783 if (!Parents.empty() || !VParents.empty()) {
784 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
785 auto &PBody = Out.back();
786 PBody->Children.emplace_back(std::make_unique<TextNode>("Inherits from "));
787 if (Parents.empty())
788 AppendVector(std::move(VParents), PBody->Children);
789 else if (VParents.empty())
790 AppendVector(std::move(Parents), PBody->Children);
791 else {
792 AppendVector(std::move(Parents), PBody->Children);
793 PBody->Children.emplace_back(std::make_unique<TextNode>(", "));
794 AppendVector(std::move(VParents), PBody->Children);
795 }
796 }
797
798 std::vector<std::unique_ptr<TagNode>> Members =
799 genRecordMembersBlock(I.Members, I.Path);
800 AppendVector(std::move(Members), Out);
801 std::vector<std::unique_ptr<TagNode>> ChildRecords =
802 genReferencesBlock(I.ChildRecords, "Records", I.Path);
803 AppendVector(std::move(ChildRecords), Out);
804
805 std::vector<std::unique_ptr<TagNode>> ChildFunctions =
806 genFunctionsBlock(I.ChildFunctions, CDCtx, I.Path);
807 AppendVector(std::move(ChildFunctions), Out);
808 std::vector<std::unique_ptr<TagNode>> ChildEnums =
809 genEnumsBlock(I.ChildEnums, CDCtx);
810 AppendVector(std::move(ChildEnums), Out);
811
812 if (!I.Members.empty())
813 InfoIndex.Children.emplace_back("Members", "Members");
814 if (!I.ChildRecords.empty())
815 InfoIndex.Children.emplace_back("Records", "Records");
816 if (!I.ChildFunctions.empty())
817 InfoIndex.Children.emplace_back(
818 genInfoIndexItem(I.ChildFunctions, "Functions"));
819 if (!I.ChildEnums.empty())
820 InfoIndex.Children.emplace_back(genInfoIndexItem(I.ChildEnums, "Enums"));
821
822 return Out;
823 }
824
825 /// Generator for HTML documentation.
826 class HTMLGenerator : public Generator {
827 public:
828 static const char *Format;
829
830 llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS,
831 const ClangDocContext &CDCtx) override;
832 llvm::Error createResources(ClangDocContext &CDCtx) override;
833 };
834
835 const char *HTMLGenerator::Format = "html";
836
837 llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
838 const ClangDocContext &CDCtx) {
839 std::string InfoTitle;
840 std::vector<std::unique_ptr<TagNode>> MainContentNodes;
841 Index InfoIndex;
842 switch (I->IT) {
843 case InfoType::IT_namespace:
844 MainContentNodes = genHTML(*static_cast<clang::doc::NamespaceInfo *>(I),
845 InfoIndex, CDCtx, InfoTitle);
846 break;
847 case InfoType::IT_record:
848 MainContentNodes = genHTML(*static_cast<clang::doc::RecordInfo *>(I),
849 InfoIndex, CDCtx, InfoTitle);
850 break;
851 case InfoType::IT_enum:
852 MainContentNodes = genHTML(*static_cast<clang::doc::EnumInfo *>(I), CDCtx);
853 break;
854 case InfoType::IT_function:
855 MainContentNodes =
856 genHTML(*static_cast<clang::doc::FunctionInfo *>(I), CDCtx, "");
857 break;
858 case InfoType::IT_default:
859 return llvm::createStringError(llvm::inconvertibleErrorCode(),
860 "unexpected info type");
861 }
862
863 HTMLFile F =
864 genInfoFile(InfoTitle, I->Path, MainContentNodes, InfoIndex, CDCtx);
865 F.Render(OS);
866
867 return llvm::Error::success();
868 }
869
870 static std::string getRefType(InfoType IT) {
871 switch (IT) {
872 case InfoType::IT_default:
873 return "default";
874 case InfoType::IT_namespace:
875 return "namespace";
876 case InfoType::IT_record:
877 return "record";
878 case InfoType::IT_function:
879 return "function";
880 case InfoType::IT_enum:
881 return "enum";
882 }
883 llvm_unreachable("Unknown InfoType");
884 }
885
886 static llvm::Error SerializeIndex(ClangDocContext &CDCtx) {
887 std::error_code OK;
888 std::error_code FileErr;
889 llvm::SmallString<128> FilePath;
890 llvm::sys::path::native(CDCtx.OutDirectory, FilePath);
891 llvm::sys::path::append(FilePath, "index_json.js");
892 llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);
893 if (FileErr != OK) {
894 return llvm::createStringError(llvm::inconvertibleErrorCode(),
895 "error creating index file: " +
896 FileErr.message());
897 }
898 CDCtx.Idx.sort();
899 llvm::json::OStream J(OS, 2);
900 std::function<void(Index)> IndexToJSON = [&](Index I) {
901 J.object([&] {
902 J.attribute("USR", toHex(llvm::toStringRef(I.USR)));
903 J.attribute("Name", I.Name);
904 J.attribute("RefType", getRefType(I.RefType));
905 J.attribute("Path", I.Path);
906 J.attributeArray("Children", [&] {
907 for (const Index &C : I.Children)
908 IndexToJSON(C);
909 });
910 });
911 };
912 OS << "var JsonIndex = `\n";
913 IndexToJSON(CDCtx.Idx);
914 OS << "`;\n";
915 return llvm::Error::success();
916 }
917
918 // Generates a main HTML node that has the main content of the file that shows
919 // only the general index
920 // It contains the general index with links to all the generated files
921 static std::unique_ptr<TagNode> genIndexFileMainNode() {
922 auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
923
924 auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
925 LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left");
926 LeftSidebarNode->Attributes.emplace_back("path", "");
927 LeftSidebarNode->Attributes.emplace_back(
928 "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");
929 LeftSidebarNode->Attributes.emplace_back("style", "flex: 0 100%;");
930
931 MainNode->Children.emplace_back(std::move(LeftSidebarNode));
932
933 return MainNode;
934 }
935
936 static llvm::Error GenIndex(const ClangDocContext &CDCtx) {
937 std::error_code FileErr, OK;
938 llvm::SmallString<128> IndexPath;
939 llvm::sys::path::native(CDCtx.OutDirectory, IndexPath);
940 llvm::sys::path::append(IndexPath, "index.html");
941 llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_None);
942 if (FileErr != OK) {
943 return llvm::createStringError(llvm::inconvertibleErrorCode(),
944 "error creating main index: " +
945 FileErr.message());
946 }
947
948 HTMLFile F;
949
950 std::vector<std::unique_ptr<TagNode>> HeadNodes =
951 genFileHeadNodes("Index", "", CDCtx);
952 std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName);
953 std::unique_ptr<TagNode> MainNode = genIndexFileMainNode();
954 std::unique_ptr<TagNode> FooterNode = genFileFooterNode();
955
956 AppendVector(std::move(HeadNodes), F.Children);
957 F.Children.emplace_back(std::move(HeaderNode));
958 F.Children.emplace_back(std::move(MainNode));
959 F.Children.emplace_back(std::move(FooterNode));
960
961 F.Render(IndexOS);
962
963 return llvm::Error::success();
964 }
965
966 static llvm::Error CopyFile(StringRef FilePath, StringRef OutDirectory) {
967 llvm::SmallString<128> PathWrite;
968 llvm::sys::path::native(OutDirectory, PathWrite);
969 llvm::sys::path::append(PathWrite, llvm::sys::path::filename(FilePath));
970 llvm::SmallString<128> PathRead;
971 llvm::sys::path::native(FilePath, PathRead);
972 std::error_code OK;
973 std::error_code FileErr = llvm::sys::fs::copy_file(PathRead, PathWrite);
974 if (FileErr != OK) {
975 return llvm::createStringError(llvm::inconvertibleErrorCode(),
976 "error creating file " +
977 llvm::sys::path::filename(FilePath) +
978 ": " + FileErr.message() + "\n");
979 }
980 return llvm::Error::success();
981 }
982
983 llvm::Error HTMLGenerator::createResources(ClangDocContext &CDCtx) {
984 auto Err = SerializeIndex(CDCtx);
985 if (Err)
986 return Err;
987 Err = GenIndex(CDCtx);
988 if (Err)
989 return Err;
990
991 for (const auto &FilePath : CDCtx.UserStylesheets) {
992 Err = CopyFile(FilePath, CDCtx.OutDirectory);
993 if (Err)
994 return Err;
995 }
996 for (const auto &FilePath : CDCtx.FilesToCopy) {
997 Err = CopyFile(FilePath, CDCtx.OutDirectory);
998 if (Err)
999 return Err;
1000 }
1001 return llvm::Error::success();
1002 }
1003
1004 static GeneratorRegistry::Add<HTMLGenerator> HTML(HTMLGenerator::Format,
1005 "Generator for HTML output.");
1006
1007 // This anchor is used to force the linker to link in the generated object
1008 // file and thus register the generator.
1009 volatile int HTMLGeneratorAnchorSource = 0;
1010
1011 } // namespace doc
1012 } // namespace clang
clang::doc::genFileFooterNode
static std::unique_ptr< TagNode > genFileFooterNode()
Definition: HTMLGenerator.cpp:532
clang::doc::Index::Children
std::vector< Index > Children
Definition: Representation.h:401
Representation.h
llvm
Some operations such as code completion produce a set of candidates.
Definition: YAMLGenerator.cpp:28
Text
std::string Text
Definition: HTMLGenerator.cpp:80
clang::doc::GenIndex
static llvm::Error GenIndex(const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:936
clang::doc::Reference
Definition: Representation.h:115
clang::doc::HTMLGeneratorAnchorSource
volatile int HTMLGeneratorAnchorSource
Definition: HTMLGenerator.cpp:1009
clang::doc::ClangDocContext::RepositoryUrl
llvm::Optional< std::string > RepositoryUrl
Definition: Representation.h:429
clang::doc::genEnumsBlock
static std::vector< std::unique_ptr< TagNode > > genEnumsBlock(const std::vector< EnumInfo > &Enums, const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:346
Tag
HTMLTag Tag
Definition: HTMLGenerator.cpp:90
clang::doc::CopyFile
static llvm::Error CopyFile(StringRef FilePath, StringRef OutDirectory)
Definition: HTMLGenerator.cpp:966
clang::doc::genInfoIndexItem
static Index genInfoIndexItem(const std::vector< T > &Infos, StringRef Title)
Definition: HTMLGenerator.cpp:565
clang::doc::TypeInfo::Type
Reference Type
Definition: Representation.h:163
clang::doc::Reference::Name
SmallString< 16 > Name
Definition: Representation.h:139
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::SymbolInfo::DefLoc
llvm::Optional< Location > DefLoc
Definition: Representation.h:301
clang::doc::ClangDocContext::JsScripts
std::vector< std::string > JsScripts
Definition: Representation.h:434
clang::doc::RecordInfo::ChildFunctions
std::vector< FunctionInfo > ChildFunctions
Definition: Representation.h:357
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::getRefType
static std::string getRefType(InfoType IT)
Definition: HTMLGenerator.cpp:870
clang::doc::ClangDocContext::ProjectName
std::string ProjectName
Definition: Representation.h:422
clang::doc::Index
Definition: Representation.h:389
clang::doc::Index::JumpToSection
llvm::Optional< SmallString< 16 > > JumpToSection
Definition: Representation.h:400
clang::doc::NamespaceInfo::ChildFunctions
std::vector< FunctionInfo > ChildFunctions
Definition: Representation.h:287
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:543
clang::doc::NamespaceInfo::ChildEnums
std::vector< EnumInfo > ChildEnums
Definition: Representation.h:288
clang::doc::EnumInfo::Scoped
bool Scoped
Definition: Representation.h:384
Path
std::vector< HeaderHandle > Path
Definition: PreprocessorTracker.cpp:537
clang::doc::genHTML
static std::vector< std::unique_ptr< TagNode > > genHTML(const RecordInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx, std::string &InfoTitle)
Definition: HTMLGenerator.cpp:761
clang::doc::RecordInfo::ChildRecords
std::vector< Reference > ChildRecords
Definition: Representation.h:356
clang::doc::HTMLGenerator::Format
static const char * Format
Definition: HTMLGenerator.cpp:828
clang::doc::AppendVector
static void AppendVector(std::vector< Derived > &&New, std::vector< Base > &Original)
Definition: HTMLGenerator.cpp:222
clang::doc::SerializeIndex
static llvm::Error SerializeIndex(ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:886
clang::doc::RecordInfo::VirtualParents
llvm::SmallVector< Reference, 4 > VirtualParents
Definition: Representation.h:347
clang::doc::computeRelativePath
static SmallString< 128 > computeRelativePath(StringRef Destination, StringRef Origin)
Definition: HTMLGenerator.cpp:228
clang::doc::genJsScriptsHTML
static std::vector< std::unique_ptr< TagNode > > genJsScriptsHTML(StringRef InfoPath, const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:288
ProjectName
static llvm::cl::opt< std::string > ProjectName("project-name", llvm::cl::desc("Name of project."), llvm::cl::cat(ClangDocCategory))
clang::doc::FunctionInfo
Definition: Representation.h:307
clang::doc::getAccess
std::string getAccess(AccessSpecifier AS)
Definition: Generators.cpp:30
clang::doc::FunctionInfo::Params
llvm::SmallVector< FieldTypeInfo, 4 > Params
Definition: Representation.h:316
clang::doc::genFileHeadNodes
static std::vector< std::unique_ptr< TagNode > > genFileHeadNodes(StringRef Title, StringRef InfoPath, const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:469
clang::doc::genLink
static std::unique_ptr< TagNode > genLink(const Twine &Text, const Twine &Link)
Definition: HTMLGenerator.cpp:302
clang::doc::genStylesheetsHTML
static std::vector< std::unique_ptr< TagNode > > genStylesheetsHTML(StringRef InfoPath, const ClangDocContext &CDCtx)
Definition: HTMLGenerator.cpp:271
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::EnumInfo::Members
llvm::SmallVector< SmallString< 16 >, 4 > Members
Definition: Representation.h:386
clang::doc::Generator
Definition: Generators.h:24
clang::doc::Info::Description
std::vector< CommentInfo > Description
Definition: Representation.h:256
clang::doc::NamespaceInfo
Definition: Representation.h:271
clang::doc::InfoType
InfoType
Definition: Representation.h:37
clang::doc::ClangDocContext::UserStylesheets
std::vector< std::string > UserStylesheets
Definition: Representation.h:432
clang::doc::RecordInfo
Definition: Representation.h:327
clang::doc::@11::NodeType
NodeType
Definition: HTMLGenerator.cpp:63
clang::doc::getTagType
std::string getTagType(TagTypeKind AS)
Definition: Generators.cpp:44
clang::doc::genFileHeaderNode
static std::unique_ptr< TagNode > genFileHeaderNode(StringRef ProjectName)
Definition: HTMLGenerator.cpp:487
clang::doc::genInfoFileMainNode
static std::unique_ptr< TagNode > genInfoFileMainNode(StringRef InfoPath, std::vector< std::unique_ptr< TagNode >> &MainContentInnerNodes, const Index &InfoIndex)
Definition: HTMLGenerator.cpp:497
clang::doc::Info::Name
SmallString< 16 > Name
Definition: Representation.h:253
clang::doc::writeFileDefinition
static std::unique_ptr< TagNode > writeFileDefinition(const Location &L, llvm::Optional< StringRef > RepositoryUrl=None)
Definition: HTMLGenerator.cpp:437
clang::doc::genReferencesBlock
static std::vector< std::unique_ptr< TagNode > > genReferencesBlock(const std::vector< Reference > &References, llvm::StringRef Title, StringRef ParentPath)
Definition: HTMLGenerator.cpp:418
clang::doc::Info
A base struct for Infos.
Definition: Representation.h:237
clang::doc::FunctionInfo::Access
AccessSpecifier Access
Definition: Representation.h:321
clang::doc::Info::Path
llvm::SmallString< 128 > Path
Definition: Representation.h:257
clang::doc::RecordInfo::Parents
llvm::SmallVector< Reference, 4 > Parents
Definition: Representation.h:343
clang::doc::ClangDocContext::OutDirectory
std::string OutDirectory
Definition: Representation.h:424
clang::doc::Location
Definition: Representation.h:209
clang::doc::Reference::IsInGlobalNamespace
bool IsInGlobalNamespace
Definition: Representation.h:148
clang::doc::HTMLGenerator
Generator for HTML documentation.
Definition: HTMLGenerator.cpp:826
clang::doc::Index::sort
void sort()
Definition: Representation.cpp:270
Children
std::vector< std::unique_ptr< HTMLNode > > Children
Definition: HTMLGenerator.cpp:91
clang::doc::RecordInfo::TagType
TagTypeKind TagType
Definition: Representation.h:337
clang::doc::EnumInfo
Definition: Representation.h:378
Attributes
std::vector< std::pair< std::string, std::string > > Attributes
Definition: HTMLGenerator.cpp:93
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
References
unsigned References
Definition: CodeComplete.cpp:157
clang::doc::genFunctionsBlock
static std::vector< std::unique_ptr< TagNode > > genFunctionsBlock(const std::vector< FunctionInfo > &Functions, const ClangDocContext &CDCtx, StringRef ParentInfoDir)
Definition: HTMLGenerator.cpp:375
clang::doc::genIndexFileMainNode
static std::unique_ptr< TagNode > genIndexFileMainNode()
Definition: HTMLGenerator.cpp:921
clang::doc::NamespaceInfo::ChildNamespaces
std::vector< Reference > ChildNamespaces
Definition: Representation.h:285
clang::doc::NamespaceInfo::ChildRecords
std::vector< Reference > ChildRecords
Definition: Representation.h:286
clang::doc::Location::Filename
SmallString< 32 > Filename
Definition: Representation.h:232
clang::doc::Info::IT
const InfoType IT
Definition: Representation.h:252
clang::doc::RecordInfo::ChildEnums
std::vector< EnumInfo > ChildEnums
Definition: Representation.h:358
clang::doc::ClangDocContext::Idx
Index Idx
Definition: Representation.h:437
clang::doc::FunctionInfo::ReturnType
TypeInfo ReturnType
Definition: Representation.h:315
E
const Expr * E
Definition: AvoidBindCheck.cpp:82
clang::doc::RecordInfo::Members
llvm::SmallVector< MemberTypeInfo, 4 > Members
Definition: Representation.h:342
clang::doc::Info::USR
SymbolID USR
Definition: Representation.h:250
clang::doc::CommentInfo::Kind
SmallString< 16 > Kind
Definition: Representation.h:92
Description
const char * Description
Definition: Dexp.cpp:257
Refs
RefSlab Refs
Definition: SymbolCollectorTests.cpp:296
Base
std::unique_ptr< GlobalCompilationDatabase > Base
Definition: GlobalCompilationDatabaseTests.cpp:83
clang::doc::HTML
static GeneratorRegistry::Add< HTMLGenerator > HTML(HTMLGenerator::Format, "Generator for HTML output.")
clang::doc::CommentInfo::Children
std::vector< std::unique_ptr< CommentInfo > > Children
Definition: Representation.h:112
clang::doc::CommentInfo::Text
SmallString< 64 > Text
Definition: Representation.h:97
clang::doc::Location::IsFileInRootDir
bool IsFileInRootDir
Definition: Representation.h:233
clang::doc::genReferenceList
static std::vector< std::unique_ptr< HTMLNode > > genReferenceList(const llvm::SmallVectorImpl< Reference > &Refs, const StringRef &CurrentDirectory)
Definition: HTMLGenerator.cpp:328
clang::doc::genRecordMembersBlock
static std::vector< std::unique_ptr< TagNode > > genRecordMembersBlock(const llvm::SmallVector< MemberTypeInfo, 4 > &Members, StringRef ParentInfoDir)
Definition: HTMLGenerator.cpp:394
clang::doc::ClangDocContext
Definition: Representation.h:414
clang::doc::Reference::Path
llvm::SmallString< 128 > Path
Definition: Representation.h:145
Type
NodeType Type
Definition: HTMLGenerator.cpp:73
clang::doc::ClangDocContext::FilesToCopy
std::vector< std::string > FilesToCopy
Definition: Representation.h:436
clang::doc::CommentInfo
Definition: Representation.h:46
clang::doc::Location::LineNumber
int LineNumber
Definition: Representation.h:231
clang::doc::genEnumMembersBlock
static std::unique_ptr< TagNode > genEnumMembersBlock(const llvm::SmallVector< SmallString< 16 >, 4 > &Members)
Definition: HTMLGenerator.cpp:364