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" 51 constexpr HTMLTag(TagType Value) : Value(Value) {}
53 operator TagType()
const {
return Value; }
54 operator bool() =
delete;
56 bool IsSelfClosing()
const;
57 llvm::SmallString<16> ToString()
const;
70 virtual ~HTMLNode() =
default;
72 virtual void Render(llvm::raw_ostream &OS,
int IndentationLevel) = 0;
76 struct TextNode :
public HTMLNode {
77 TextNode(
const Twine &
Text)
78 : HTMLNode(NodeType::NODE_TEXT), Text(Text.str()) {}
81 void Render(llvm::raw_ostream &OS,
int IndentationLevel)
override;
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()));
91 std::vector<std::unique_ptr<HTMLNode>>
Children;
92 std::vector<std::pair<std::string, std::string>>
95 void Render(llvm::raw_ostream &OS,
int IndentationLevel)
override;
98 constexpr
const char *kDoctypeDecl =
"<!DOCTYPE html>";
101 std::vector<std::unique_ptr<HTMLNode>>
Children;
102 void Render(llvm::raw_ostream &OS) {
103 OS << kDoctypeDecl <<
"\n";
104 for (
const auto &C : Children) {
113 bool HTMLTag::IsSelfClosing()
const {
115 case HTMLTag::TAG_META:
116 case HTMLTag::TAG_LINK:
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:
129 case HTMLTag::TAG_SCRIPT:
130 case HTMLTag::TAG_SPAN:
131 case HTMLTag::TAG_TITLE:
132 case HTMLTag::TAG_UL:
135 llvm_unreachable(
"Unhandled HTMLTag::TagType");
138 llvm::SmallString<16> HTMLTag::ToString()
const {
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");
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");
175 llvm_unreachable(
"Unhandled HTMLTag::TagType");
178 void TextNode::Render(llvm::raw_ostream &OS,
int IndentationLevel) {
179 OS.indent(IndentationLevel * 2);
180 printHTMLEscaped(Text, OS);
183 void TagNode::Render(llvm::raw_ostream &OS,
int IndentationLevel) {
185 bool InlineChildren =
true;
186 for (
const auto &C : Children)
187 if (C->Type == NodeType::NODE_TAG) {
188 InlineChildren =
false;
191 OS.indent(IndentationLevel * 2);
192 OS <<
"<" << Tag.ToString();
194 OS <<
" " << A.first <<
"=\"" << A.second <<
"\"";
195 if (Tag.IsSelfClosing()) {
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))) {
211 NewLineRendered =
true;
213 NewLineRendered =
false;
216 OS.indent(IndentationLevel * 2);
217 OS <<
"</" << Tag.ToString() <<
">";
220 template <
typename Derived,
typename Base,
221 typename = std::enable_if<std::is_base_of<Derived, Base>::value>>
223 std::vector<Base> &Original) {
224 std::move(New.begin(), New.end(), std::back_inserter(Original));
236 if (Destination == Origin)
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);
249 while (FileI != FileE && DirI != DirE && *FileI == *DirI) {
253 SmallString<128> Result;
256 while (DirI != DirE) {
257 llvm::sys::path::append(Result,
"..");
261 while (FileI != FileE) {
262 llvm::sys::path::append(Result, *FileI);
270 static std::vector<std::unique_ptr<TagNode>>
272 std::vector<std::unique_ptr<TagNode>> Out;
274 auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_LINK);
275 LinkNode->Attributes.emplace_back(
"rel",
"stylesheet");
277 llvm::sys::path::append(StylesheetPath,
278 llvm::sys::path::filename(FilePath));
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));
287 static std::vector<std::unique_ptr<TagNode>>
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);
293 llvm::sys::path::append(ScriptPath, llvm::sys::path::filename(FilePath));
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));
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());
308 static std::unique_ptr<HTMLNode>
310 llvm::Optional<StringRef> JumpToSection = None) {
313 return std::make_unique<TextNode>(Type.
Name);
315 return genLink(Type.
Name,
"#" + JumpToSection.getValue());
317 llvm::SmallString<128>
Path =
319 llvm::sys::path::append(Path, Type.
Name +
".html");
321 llvm::sys::path::native(Path, llvm::sys::path::Style::posix);
323 Path += (
"#" + JumpToSection.getValue()).str();
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>(
", "));
339 static std::vector<std::unique_ptr<TagNode>>
341 static std::vector<std::unique_ptr<TagNode>>
343 StringRef ParentInfoDir);
345 static std::vector<std::unique_ptr<TagNode>>
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);
363 static std::unique_ptr<TagNode>
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));
374 static std::vector<std::unique_ptr<TagNode>>
377 if (Functions.empty())
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);
393 static std::vector<std::unique_ptr<TagNode>>
395 StringRef ParentInfoDir) {
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);
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));
417 static std::vector<std::unique_ptr<TagNode>>
419 llvm::StringRef Title, StringRef ParentPath) {
420 if (References.empty())
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));
436 static std::unique_ptr<TagNode>
440 return std::make_unique<TagNode>(
441 HTMLTag::TAG_P,
"Defined at line " + std::to_string(L.
LineNumber) +
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 "));
448 std::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.
LineNumber));
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));
462 static std::vector<std::unique_ptr<TagNode>>
468 static std::vector<std::unique_ptr<TagNode>>
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 =
479 std::vector<std::unique_ptr<TagNode>> JsNodes =
488 auto HeaderNode = std::make_unique<TagNode>(HTMLTag::TAG_HEADER,
ProjectName);
489 HeaderNode->Attributes.emplace_back(
"id",
"project-title");
499 std::vector<std::unique_ptr<TagNode>> &MainContentInnerNodes,
500 const Index &InfoIndex) {
501 auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
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");
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);
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);
523 MainNode->Children.emplace_back(std::move(LeftSidebarNode));
524 MainNode->Children.emplace_back(std::move(MainContentNode));
525 MainNode->Children.emplace_back(std::move(RightSidebarNode));
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));
544 std::vector<std::unique_ptr<TagNode>> &MainContentNodes,
548 std::vector<std::unique_ptr<TagNode>> HeadNodes =
551 std::unique_ptr<TagNode> MainNode =
556 F.Children.emplace_back(std::move(HeaderNode));
557 F.Children.emplace_back(std::move(MainNode));
558 F.Children.emplace_back(std::move(FooterNode));
563 template <
typename T,
564 typename = std::enable_if<std::is_base_of<T, Info>::value>>
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)));
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();
580 SpanBody->Children.emplace_back(
genReference(Index, InfoPath));
583 Index, InfoPath, StringRef{Index.
JumpToSection.getValue()}));
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);
595 UlBody->Children.emplace_back(std::move(LiBody));
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);
606 FullComment->Children.emplace_back(std::move(Node));
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);
614 ParagraphComment->Children.emplace_back(std::move(Node));
616 if (ParagraphComment->Children.empty())
618 return std::move(ParagraphComment);
619 }
else if (I.
Kind ==
"TextComment") {
622 return std::make_unique<TextNode>(I.
Text);
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));
636 static std::vector<std::unique_ptr<TagNode>>
638 std::vector<std::unique_ptr<TagNode>> Out;
639 std::string EnumType;
641 EnumType =
"enum class ";
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)));
652 Out.emplace_back(std::move(Node));
669 static std::vector<std::unique_ptr<TagNode>>
671 StringRef ParentInfoDir) {
672 std::vector<std::unique_ptr<TagNode>> Out;
673 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H3, I.
Name));
676 Out.back()->Attributes.emplace_back(
"id",
677 llvm::toHex(llvm::toStringRef(I.
USR)));
679 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
680 auto &FunctionHeader = Out.back();
684 FunctionHeader->Children.emplace_back(
685 std::make_unique<TextNode>(Access +
" "));
687 FunctionHeader->Children.emplace_back(
689 FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(
" "));
691 FunctionHeader->Children.emplace_back(
692 std::make_unique<TextNode>(I.
Name +
"("));
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));
701 FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(
")"));
718 static std::vector<std::unique_ptr<TagNode>>
720 std::string &InfoTitle) {
721 std::vector<std::unique_ptr<TagNode>> Out;
722 if (I.
Name.str() ==
"")
723 InfoTitle =
"Global Namespace";
725 InfoTitle = (
"namespace " + I.
Name).str();
727 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
733 std::vector<std::unique_ptr<TagNode>> ChildNamespaces =
736 std::vector<std::unique_ptr<TagNode>> ChildRecords =
740 std::vector<std::unique_ptr<TagNode>> ChildFunctions =
743 std::vector<std::unique_ptr<TagNode>> ChildEnums =
748 InfoIndex.
Children.emplace_back(
"Namespaces",
"Namespaces");
750 InfoIndex.
Children.emplace_back(
"Records",
"Records");
760 static std::vector<std::unique_ptr<TagNode>>
762 std::string &InfoTitle) {
763 std::vector<std::unique_ptr<TagNode>> Out;
765 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
779 std::vector<std::unique_ptr<HTMLNode>> Parents =
781 std::vector<std::unique_ptr<HTMLNode>> VParents =
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 "));
789 else if (VParents.empty())
793 PBody->Children.emplace_back(std::make_unique<TextNode>(
", "));
798 std::vector<std::unique_ptr<TagNode>> Members =
801 std::vector<std::unique_ptr<TagNode>> ChildRecords =
805 std::vector<std::unique_ptr<TagNode>> ChildFunctions =
808 std::vector<std::unique_ptr<TagNode>> ChildEnums =
813 InfoIndex.
Children.emplace_back(
"Members",
"Members");
815 InfoIndex.
Children.emplace_back(
"Records",
"Records");
830 llvm::Error generateDocForInfo(
Info *I, llvm::raw_ostream &OS,
835 const char *HTMLGenerator::Format =
"html";
837 llvm::Error HTMLGenerator::generateDocForInfo(
Info *I, llvm::raw_ostream &OS,
839 std::string InfoTitle;
840 std::vector<std::unique_ptr<TagNode>> MainContentNodes;
843 case InfoType::IT_namespace:
844 MainContentNodes =
genHTML(*static_cast<clang::doc::NamespaceInfo *>(I),
845 InfoIndex, CDCtx, InfoTitle);
847 case InfoType::IT_record:
848 MainContentNodes =
genHTML(*static_cast<clang::doc::RecordInfo *>(I),
849 InfoIndex, CDCtx, InfoTitle);
851 case InfoType::IT_enum:
852 MainContentNodes =
genHTML(*static_cast<clang::doc::EnumInfo *>(I), CDCtx);
854 case InfoType::IT_function:
856 genHTML(*static_cast<clang::doc::FunctionInfo *>(I), CDCtx,
"");
858 case InfoType::IT_default:
859 return llvm::createStringError(llvm::inconvertibleErrorCode(),
860 "unexpected info type");
867 return llvm::Error::success();
872 case InfoType::IT_default:
874 case InfoType::IT_namespace:
876 case InfoType::IT_record:
878 case InfoType::IT_function:
880 case InfoType::IT_enum:
883 llvm_unreachable(
"Unknown InfoType");
888 std::error_code FileErr;
889 llvm::SmallString<128> FilePath;
891 llvm::sys::path::append(FilePath,
"index_json.js");
892 llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);
894 return llvm::createStringError(llvm::inconvertibleErrorCode(),
895 "error creating index file: " +
899 llvm::json::OStream J(OS, 2);
900 std::function<void(Index)> IndexToJSON = [&](Index I) {
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)
912 OS <<
"var JsonIndex = `\n";
913 IndexToJSON(CDCtx.
Idx);
915 return llvm::Error::success();
922 auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
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%;");
931 MainNode->Children.emplace_back(std::move(LeftSidebarNode));
937 std::error_code FileErr, OK;
938 llvm::SmallString<128> IndexPath;
940 llvm::sys::path::append(IndexPath,
"index.html");
941 llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_None);
943 return llvm::createStringError(llvm::inconvertibleErrorCode(),
944 "error creating main index: " +
950 std::vector<std::unique_ptr<TagNode>> HeadNodes =
957 F.Children.emplace_back(std::move(HeaderNode));
958 F.Children.emplace_back(std::move(MainNode));
959 F.Children.emplace_back(std::move(FooterNode));
963 return llvm::Error::success();
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);
973 std::error_code FileErr = llvm::sys::fs::copy_file(PathRead, PathWrite);
975 return llvm::createStringError(llvm::inconvertibleErrorCode(),
976 "error creating file " +
977 llvm::sys::path::filename(FilePath) +
978 ": " + FileErr.message() +
"\n");
980 return llvm::Error::success();
1001 return llvm::Error::success();
1004 static GeneratorRegistry::Add<HTMLGenerator>
HTML(HTMLGenerator::Format,
1005 "Generator for HTML output.");
static std::unique_ptr< TagNode > genFileFooterNode()
std::vector< Index > Children
Some operations such as code completion produce a set of candidates.
static llvm::Error GenIndex(const ClangDocContext &CDCtx)
volatile int HTMLGeneratorAnchorSource
llvm::Optional< std::string > RepositoryUrl
static std::vector< std::unique_ptr< TagNode > > genEnumsBlock(const std::vector< EnumInfo > &Enums, const ClangDocContext &CDCtx)
static llvm::Error CopyFile(StringRef FilePath, StringRef OutDirectory)
static Index genInfoIndexItem(const std::vector< T > &Infos, StringRef Title)
static std::unique_ptr< HTMLNode > genReference(const Reference &Type, StringRef CurrentDirectory, llvm::Optional< StringRef > JumpToSection=None)
llvm::Optional< Location > DefLoc
std::vector< std::string > JsScripts
std::vector< FunctionInfo > ChildFunctions
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))
static std::string getRefType(InfoType IT)
llvm::Optional< SmallString< 16 > > JumpToSection
std::vector< FunctionInfo > ChildFunctions
static HTMLFile genInfoFile(StringRef Title, StringRef InfoPath, std::vector< std::unique_ptr< TagNode >> &MainContentNodes, const Index &InfoIndex, const ClangDocContext &CDCtx)
std::vector< EnumInfo > ChildEnums
std::vector< HeaderHandle > Path
static std::vector< std::unique_ptr< TagNode > > genHTML(const RecordInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx, std::string &InfoTitle)
std::vector< Reference > ChildRecords
static const char * Format
static void AppendVector(std::vector< Derived > &&New, std::vector< Base > &Original)
static llvm::Error SerializeIndex(ClangDocContext &CDCtx)
llvm::SmallVector< Reference, 4 > VirtualParents
static SmallString< 128 > computeRelativePath(StringRef Destination, StringRef Origin)
static std::vector< std::unique_ptr< TagNode > > genJsScriptsHTML(StringRef InfoPath, const ClangDocContext &CDCtx)
static llvm::cl::opt< std::string > ProjectName("project-name", llvm::cl::desc("Name of project."), llvm::cl::cat(ClangDocCategory))
std::string getAccess(AccessSpecifier AS)
llvm::SmallVector< FieldTypeInfo, 4 > Params
static std::vector< std::unique_ptr< TagNode > > genFileHeadNodes(StringRef Title, StringRef InfoPath, const ClangDocContext &CDCtx)
static std::unique_ptr< TagNode > genLink(const Twine &Text, const Twine &Link)
static std::vector< std::unique_ptr< TagNode > > genStylesheetsHTML(StringRef InfoPath, const ClangDocContext &CDCtx)
static llvm::cl::opt< std::string > OutDirectory("output", llvm::cl::desc("Directory for outputting generated files."), llvm::cl::init("docs"), llvm::cl::cat(ClangDocCategory))
llvm::SmallVector< SmallString< 16 >, 4 > Members
std::vector< CommentInfo > Description
std::vector< std::string > UserStylesheets
std::string getTagType(TagTypeKind AS)
static std::unique_ptr< TagNode > genFileHeaderNode(StringRef ProjectName)
static std::unique_ptr< TagNode > genInfoFileMainNode(StringRef InfoPath, std::vector< std::unique_ptr< TagNode >> &MainContentInnerNodes, const Index &InfoIndex)
static std::unique_ptr< TagNode > writeFileDefinition(const Location &L, llvm::Optional< StringRef > RepositoryUrl=None)
static std::vector< std::unique_ptr< TagNode > > genReferencesBlock(const std::vector< Reference > &References, llvm::StringRef Title, StringRef ParentPath)
llvm::SmallString< 128 > Path
llvm::SmallVector< Reference, 4 > Parents
Generator for HTML documentation.
std::vector< std::unique_ptr< HTMLNode > > Children
std::vector< std::pair< std::string, std::string > > Attributes
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static std::vector< std::unique_ptr< TagNode > > genFunctionsBlock(const std::vector< FunctionInfo > &Functions, const ClangDocContext &CDCtx, StringRef ParentInfoDir)
static std::unique_ptr< TagNode > genIndexFileMainNode()
std::vector< Reference > ChildNamespaces
std::vector< Reference > ChildRecords
SmallString< 32 > Filename
std::vector< EnumInfo > ChildEnums
llvm::SmallVector< MemberTypeInfo, 4 > Members
std::unique_ptr< GlobalCompilationDatabase > Base
static GeneratorRegistry::Add< HTMLGenerator > HTML(HTMLGenerator::Format, "Generator for HTML output.")
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
std::vector< std::string > FilesToCopy
static std::unique_ptr< TagNode > genEnumMembersBlock(const llvm::SmallVector< SmallString< 16 >, 4 > &Members)