18#include "clang/Basic/Specifiers.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/Support/JSON.h"
23using namespace llvm::json;
26template <
typename Container,
typename SerializationFunc>
28 const Container &Records, Object &Obj,
const StringRef Key,
29 SerializationFunc SerializeInfo,
const StringRef EndKey =
"End",
30 function_ref<
void(Object &)> UpdateJson = [](Object &Obj) {});
37typedef std::function<void(
const Reference &, Object &)> ReferenceFunc;
40 json::Object serializeLocation(
const Location &Loc);
41 void serializeCommonAttributes(
const Info &I, json::Object &Obj);
42 void serializeCommonChildren(
43 const ScopeChildren &Children, json::Object &Obj,
44 std::optional<ReferenceFunc> MDReferenceLambda = std::nullopt);
45 void serializeContexts(Info *I, llvm::StringMap<Info *> &Infos);
46 void serializeInfo(
const ConstraintInfo &I, Object &Obj);
47 void serializeInfo(
const TemplateInfo &Template, Object &Obj);
48 void serializeInfo(
const ConceptInfo &I, Object &Obj);
49 void serializeInfo(
const TypeInfo &I, Object &Obj);
50 void serializeInfo(
const FieldTypeInfo &I, Object &Obj);
51 void serializeInfo(
const FunctionInfo &F, json::Object &Obj);
52 void serializeInfo(
const EnumValueInfo &I, Object &Obj);
53 void serializeInfo(
const EnumInfo &I, json::Object &Obj);
54 void serializeInfo(
const TypedefInfo &I, json::Object &Obj);
55 void serializeInfo(
const BaseRecordInfo &I, Object &Obj);
56 void serializeInfo(
const FriendInfo &I, Object &Obj);
57 void serializeInfo(
const RecordInfo &I, json::Object &Obj);
58 void serializeInfo(
const VarInfo &I, json::Object &Obj);
59 void serializeInfo(
const NamespaceInfo &I, json::Object &Obj);
60 SmallString<16> determineFileName(Info *I, SmallString<128> &Path);
61 Error serializeIndex(StringRef RootDir);
62 void generateContext(
const Info &I, Object &Obj);
63 void serializeReference(
const Reference &Ref, Object &ReferenceObj);
64 Error serializeAllFiles(
const ClangDocContext &CDCtx, StringRef RootDir);
65 void serializeMDReference(
const Reference &Ref, Object &ReferenceObj,
68 void serializeClassSpecializations(
SymbolID ClassUSR, Object &ReferenceObj);
71 auto serializeInfoLambda() {
73 serializeInfo(Info, Object);
76 auto serializeReferenceLambda() {
78 serializeReference(Ref, Object);
82 llvm::DenseMap<const Info *, SmallVector<Context, 4>> ContextsMap;
83 llvm::StringMap<Info *> *Infos =
nullptr;
84 const ClangDocContext *CDCtx;
88 static const char *Format;
90 Error generateDocumentation(StringRef RootDir, llvm::StringMap<Info *> Infos,
91 const ClangDocContext &CDCtx,
92 std::string DirName)
override;
93 Error createResources(ClangDocContext &CDCtx)
override;
96 Error generateDocForInfo(Info *I, llvm::raw_ostream &OS,
97 const ClangDocContext &CDCtx)
override;
102const char *JSONGenerator::Format =
"json";
110 if (LLVM_LIKELY(json::isUTF8(S)))
112 return json::fixUTF8(S);
136 llvm_unreachable(
"Unknown InfoType encountered.");
139json::Object JSONGenerator::serializeLocation(
const Location &Loc) {
142 LocationObj[
"Filename"] = Loc.
Filename;
147 sys::path::append(FileURL, sys::path::Style::posix, Loc.
Filename);
149 std::string LinePrefix;
156 LocationObj[
"FileURL"] = FileURL;
168 if (
auto *Obj = Comment.getAsObject()) {
169 if (
auto *Children = Obj->getArray(
"Children");
170 Children && Children->empty())
174 else if (
auto *Array = Comment.getAsArray(); Array && Array->empty()) {
178 auto DescriptionIt = Description.find(Key);
180 if (DescriptionIt == Description.end()) {
181 auto CommentsArray = json::Array();
182 CommentsArray.push_back(Comment);
183 Description[Key] = std::move(CommentsArray);
184 Description[
"Has" + Key.str()] =
true;
186 DescriptionIt->getSecond().getAsArray()->push_back(Comment);
194 if (!ParagraphComment)
195 return json::Value(
nullptr);
196 json::Value *Children = ParagraphComment->get(
"Children");
198 return json::Value(
nullptr);
199 auto ChildrenArray = *Children->getAsArray();
200 auto ChildrenIt = ChildrenArray.begin();
201 while (ChildrenIt != ChildrenArray.end()) {
202 auto *ChildObj = ChildrenIt->getAsObject();
203 assert(ChildObj &&
"Invalid JSON object in Comment");
204 auto TextComment = ChildObj->getString(
"TextComment");
205 if (!TextComment || TextComment->empty()) {
206 ChildrenIt = ChildrenArray.erase(ChildrenIt);
211 return ChildrenArray;
215 json::Value TextArray = json::Array();
216 auto &TextArrayRef = *TextArray.getAsArray();
217 for (
auto &Line : VerbatimLines)
218 TextArrayRef.push_back(*Line.getAsObject()
219 ->get(
"VerbatimBlockLineComment")
228 Object Obj = Object();
230 json::Value ChildVal = Object();
231 Object &Child = *ChildVal.getAsObject();
233 json::Value ChildArr = Array();
234 auto &CARef = *ChildArr.getAsArray();
248 if (I.
Name ==
"brief")
249 insertComment(Description, TextCommentsArray,
"BriefComments");
250 else if (I.
Name ==
"return")
251 insertComment(Description, TextCommentsArray,
"ReturnComments");
252 else if (I.
Name ==
"throws" || I.
Name ==
"throw") {
253 json::Value ThrowsVal = Object();
254 auto &ThrowsObj = *ThrowsVal.getAsObject();
255 ThrowsObj[
"Exception"] = I.
Args.front();
256 ThrowsObj[
"Children"] = TextCommentsArray;
263 json::Value ArgsArr = Array();
264 auto &ARef = *ArgsArr.getAsArray();
265 ARef.reserve(I.
Args.size());
266 for (
const auto &Arg : I.
Args)
268 Child.insert({
"Command", I.
Name});
269 Child.insert({
"Args", ArgsArr});
270 Child.insert({
"Children", ChildArr});
277 Child.insert({
"ParamName", I.
ParamName});
278 Child.insert({
"Direction", I.
Direction});
279 Child.insert({
"Explicit", I.
Explicit});
281 Child.insert({
"Children", TextCommentsArray});
293 insertComment(Description, TextCommentsArray,
"CodeComments");
302 Child.insert({
"Children", ChildArr});
308 json::Value AttrKeysArray = json::Array();
309 json::Value AttrValuesArray = json::Array();
310 auto &KeyArr = *AttrKeysArray.getAsArray();
311 auto &ValArr = *AttrValuesArray.getAsArray();
315 KeyArr.emplace_back(K);
317 ValArr.emplace_back(V);
318 Child.insert({
"Name", I.
Name});
320 Child.insert({
"AttrKeys", AttrKeysArray});
321 Child.insert({
"AttrValues", AttrValuesArray});
322 Child.insert({
"Children", ChildArr});
328 Child.insert({
"Name", I.
Name});
329 Child.insert({
"Children", ChildArr});
336 Child.insert({
"Children", ChildArr});
337 Child[
"ParagraphComment"] =
true;
346 llvm_unreachable(
"Unknown comment kind encountered.");
350void JSONGenerator::generateContext(
const Info &I, Object &Obj) {
351 Obj[
"Contexts"] = json::Array();
352 Obj[
"HasContexts"] =
true;
354 auto It = ContextsMap.find(&I);
355 if (It == ContextsMap.end() || It->second.empty())
358 auto &ContextArrayRef = *
Obj[
"Contexts"].getAsArray();
359 const auto &Contexts = It->second;
360 ContextArrayRef.reserve(Contexts.size());
362 std::string CurrentRelativePath;
363 bool PreviousRecord =
false;
364 for (
const auto &Current : Contexts) {
365 json::Value ContextVal =
Object();
366 Object &Context = *ContextVal.getAsObject();
367 serializeReference(Current, Context);
369 if (ContextArrayRef.empty() && I.
IT == InfoType::IT_record) {
370 if (Current.DocumentationFileName ==
"index") {
373 PreviousRecord =
false;
374 Context[
"RelativePath"] =
"./";
378 PreviousRecord =
true;
379 CurrentRelativePath +=
"../";
380 Context[
"RelativePath"] = CurrentRelativePath;
382 ContextArrayRef.push_back(ContextVal);
386 if (PreviousRecord && (Current.DocumentationFileName ==
"index")) {
389 PreviousRecord =
false;
390 }
else if (Current.DocumentationFileName !=
"index") {
393 PreviousRecord =
true;
394 CurrentRelativePath +=
"../";
397 PreviousRecord =
false;
398 CurrentRelativePath +=
"../";
401 if (Current.QualName ==
"GlobalNamespace" && Current.RelativePath !=
"./")
402 Context[
"DocumentationFileName"] =
403 SmallString<16>(
"GlobalNamespace/index");
405 Context[
"RelativePath"] = CurrentRelativePath;
406 ContextArrayRef.insert(ContextArrayRef.begin(), ContextVal);
409 ContextArrayRef.back().getAsObject()->insert({
"End",
true});
413 json::Object &Obj, StringRef Key =
"") {
414 if (Description.empty())
418 auto &Comments = Description.front()->Children;
419 Object DescriptionObj = Object();
424 if (
auto *ParagraphComment = Comment.getAsObject();
425 ParagraphComment->get(
"ParagraphComment")) {
427 if (TextCommentsArray.kind() == json::Value::Null ||
428 TextCommentsArray.getAsArray()->empty())
430 insertComment(DescriptionObj, TextCommentsArray,
"ParagraphComments");
433 Obj[
"Description"] = std::move(DescriptionObj);
438void JSONGenerator::serializeCommonAttributes(
const Info &I,
442 Obj[
"USR"] = toHex(toStringRef(I.
USR));
451 Obj[
"Namespace"] = json::Array();
453 Obj[
"Namespace"].getAsArray()->push_back(NS.Name);
459 if (I.
IT != InfoType::IT_namespace) {
460 const auto *Symbol = cast<SymbolInfo>(&I);
462 Obj[
"Location"] = serializeLocation(Symbol->DefLoc.value());
465 auto It = ContextsMap.find(&I);
466 if (It != ContextsMap.end() && !It->second.empty())
467 generateContext(I, Obj);
476 Object &TemplateObj) {
477 json::Value TemplateSpecializationVal = Object();
478 auto &TemplateSpecializationObj = *TemplateSpecializationVal.getAsObject();
479 TemplateSpecializationObj[
"SpecializationOf"] =
480 toHex(toStringRef(Template.Specialization->SpecializationOf));
481 if (!Template.Specialization->Params.empty()) {
482 bool VerticalDisplay =
484 serializeArray(Template.Specialization->Params, TemplateSpecializationObj,
486 [VerticalDisplay](Object &JsonObj) {
487 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
490 TemplateObj[
"Specialization"] = TemplateSpecializationVal;
493void JSONGenerator::serializeClassSpecializations(
SymbolID ClassUSR,
494 Object &ReferenceObj) {
497 auto *
Class = Infos->lookup(toHex(ClassUSR));
498 if (!Class ||
Class->IT != InfoType::IT_record)
500 RecordInfo *ClassInfo = cast<RecordInfo>(Class);
506void JSONGenerator::serializeReference(
const Reference &Ref,
507 Object &ReferenceObj) {
509 ReferenceObj[
"Name"] = Ref.
Name;
510 ReferenceObj[
"QualName"] = Ref.
QualName;
511 ReferenceObj[
"USR"] = toHex(toStringRef(Ref.
USR));
517 if (Ref.
Path !=
"GlobalNamespace" && !Ref.
Path.empty())
518 ReferenceObj[
"PathStem"] = sys::path::stem(Ref.
Path);
522void JSONGenerator::serializeMDReference(
const Reference &Ref,
523 Object &ReferenceObj,
524 StringRef BasePath) {
525 serializeReference(Ref, ReferenceObj);
527 sys::path::native(Path, sys::path::Style::posix);
528 sys::path::append(Path, sys::path::Style::posix,
530 ReferenceObj[
"BasePath"] =
Path;
535void JSONGenerator::serializeCommonChildren(
536 const ScopeChildren &Children, json::Object &Obj,
537 std::optional<ReferenceFunc> MDReferenceLambda) {
540 Obj[
"HasEnums"] =
true;
545 Obj[
"HasTypedefs"] =
true;
549 ReferenceFunc BaseFunc = MDReferenceLambda ? MDReferenceLambda.value()
550 : serializeReferenceLambda();
552 ReferenceFunc SerializeReferenceFunc =
553 [
this, BaseFunc](
const Reference &Ref,
Object &
Object) {
554 BaseFunc(Ref, Object);
555 serializeClassSpecializations(Ref.
USR, Object);
558 Obj[
"HasRecords"] =
true;
562template <
typename Container,
typename SerializationFunc>
564 SerializationFunc SerializeInfo, StringRef EndKey,
565 function_ref<
void(Object &)> UpdateJson) {
566 json::Value RecordsArray = Array();
567 auto &RecordsArrayRef = *RecordsArray.getAsArray();
568 RecordsArrayRef.reserve(Records.size());
570 size_t Size = Records.size();
571 for (
const auto &Item : Records) {
572 json::Value ItemVal = Object();
573 auto &ItemObj = *ItemVal.getAsObject();
574 SerializeInfo(Item, ItemObj);
575 if (
Index == Size - 1)
576 ItemObj[EndKey] =
true;
577 RecordsArrayRef.push_back(ItemVal);
580 Obj[Key] = RecordsArray;
584void JSONGenerator::serializeInfo(
const ConstraintInfo &I, Object &Obj) {
589void JSONGenerator::serializeInfo(
const TemplateInfo &Template, Object &Obj) {
590 json::Value TemplateVal =
Object();
591 auto &TemplateObj = *TemplateVal.getAsObject();
596 if (!Template.
Params.empty()) {
600 [VerticalDisplay](Object &JsonObj) {
601 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
607 serializeInfoLambda());
609 Obj[
"Template"] = TemplateVal;
612void JSONGenerator::serializeInfo(
const ConceptInfo &I, Object &Obj) {
613 serializeCommonAttributes(I, Obj);
619void JSONGenerator::serializeInfo(
const TypeInfo &I, Object &Obj) {
627void JSONGenerator::serializeInfo(
const FieldTypeInfo &I, Object &Obj) {
630 json::Value ReferenceVal =
Object();
631 Object &ReferenceObj = *ReferenceVal.getAsObject();
632 serializeReference(I.
Type, ReferenceObj);
633 Obj[
"Type"] = ReferenceVal;
636void JSONGenerator::serializeInfo(
const FunctionInfo &F, json::Object &Obj) {
637 serializeCommonAttributes(F, Obj);
640 auto ReturnTypeObj =
Object();
642 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
647 [VerticalDisplay](Object &JsonObj) {
648 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
653 serializeInfo(F.
Template.value(), Obj);
656void JSONGenerator::serializeInfo(
const EnumValueInfo &I, Object &Obj) {
666void JSONGenerator::serializeInfo(
const EnumInfo &I, json::Object &Obj) {
667 serializeCommonAttributes(I, Obj);
671 json::Value BaseTypeVal =
Object();
672 auto &BaseTypeObj = *BaseTypeVal.getAsObject();
673 BaseTypeObj[
"Name"] = I.
BaseType->Type.Name;
674 BaseTypeObj[
"QualName"] = I.
BaseType->Type.QualName;
675 BaseTypeObj[
"USR"] = toHex(toStringRef(I.
BaseType->Type.USR));
676 Obj[
"BaseType"] = BaseTypeVal;
680 for (
const auto &Member : I.
Members) {
681 if (!Member.Description.empty()) {
682 Obj[
"HasComments"] =
true;
690void JSONGenerator::serializeInfo(
const TypedefInfo &I, json::Object &Obj) {
691 serializeCommonAttributes(I, Obj);
694 json::Value TypeVal =
Object();
695 auto &TypeObj = *TypeVal.getAsObject();
697 Obj[
"Underlying"] = TypeVal;
699 serializeInfo(I.
Template.value(), Obj);
702void JSONGenerator::serializeInfo(
const BaseRecordInfo &I, Object &Obj) {
703 serializeInfo(
static_cast<const RecordInfo &
>(I), Obj);
705 Obj[
"Access"] = getAccessSpelling(I.
Access);
709void JSONGenerator::serializeInfo(
const FriendInfo &I, Object &Obj) {
710 auto FriendRef =
Object();
711 serializeReference(I.
Ref, FriendRef);
712 Obj[
"Reference"] = std::move(FriendRef);
715 serializeInfo(I.
Template.value(), Obj);
719 auto ReturnTypeObj =
Object();
720 serializeInfo(I.
ReturnType.value(), ReturnTypeObj);
721 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
723 serializeCommonAttributes(I, Obj);
726static void insertArray(Object &Obj, json::Value &Array, StringRef Key) {
728 Obj[
"Has" + Key.str()] =
true;
731void JSONGenerator::serializeInfo(
const RecordInfo &I, json::Object &Obj) {
732 serializeCommonAttributes(I, Obj);
738 json::Value PubFunctionsArray =
Array();
739 json::Array &PubFunctionsArrayRef = *PubFunctionsArray.getAsArray();
740 json::Value ProtFunctionsArray =
Array();
741 json::Array &ProtFunctionsArrayRef = *ProtFunctionsArray.getAsArray();
744 json::Value FunctionVal =
Object();
745 auto &FunctionObj = *FunctionVal.getAsObject();
746 serializeInfo(Function, FunctionObj);
747 clang::AccessSpecifier Access =
Function->Access;
748 if (Access == clang::AccessSpecifier::AS_public)
749 PubFunctionsArrayRef.push_back(FunctionVal);
750 else if (Access == clang::AccessSpecifier::AS_protected)
751 ProtFunctionsArrayRef.push_back(FunctionVal);
754 if (!PubFunctionsArrayRef.empty())
755 insertArray(Obj, PubFunctionsArray,
"PublicMethods");
756 if (!ProtFunctionsArrayRef.empty())
757 insertArray(Obj, ProtFunctionsArray,
"ProtectedMethods");
761 Obj[
"HasMembers"] =
true;
762 json::Value PublicMembersArray =
Array();
763 json::Array &PubMembersArrayRef = *PublicMembersArray.getAsArray();
764 json::Value ProtectedMembersArray =
Array();
765 json::Array &ProtMembersArrayRef = *ProtectedMembersArray.getAsArray();
766 json::Value PrivateMembersArray =
Array();
767 json::Array &PrivateMembersArrayRef = *PrivateMembersArray.getAsArray();
769 for (
const MemberTypeInfo &Member : I.
Members) {
770 json::Value MemberVal =
Object();
771 auto &MemberObj = *MemberVal.getAsObject();
772 MemberObj[
"Name"] = Member.
Name;
773 MemberObj[
"Type"] = Member.
Type.
Name;
774 MemberObj[
"IsStatic"] = Member.
IsStatic;
776 if (Member.
Access == clang::AccessSpecifier::AS_public)
777 PubMembersArrayRef.push_back(MemberVal);
778 else if (Member.
Access == clang::AccessSpecifier::AS_protected)
779 ProtMembersArrayRef.push_back(MemberVal);
780 else if (Member.
Access == clang::AccessSpecifier::AS_private)
781 PrivateMembersArrayRef.push_back(MemberVal);
784 if (!PubMembersArrayRef.empty())
785 insertArray(Obj, PublicMembersArray,
"PublicMembers");
786 if (!ProtMembersArrayRef.empty())
787 insertArray(Obj, ProtectedMembersArray,
"ProtectedMembers");
788 if (!PrivateMembersArrayRef.empty())
789 insertArray(Obj, PrivateMembersArray,
"PrivateMembers");
792 if (!I.
Bases.empty())
797 Obj[
"HasParents"] =
true;
802 serializeReferenceLambda());
803 Obj[
"HasVirtualParents"] =
true;
807 serializeInfo(I.
Template.value(), Obj);
811 Obj[
"HasFriends"] =
true;
814 serializeCommonChildren(I.
Children, Obj);
817void JSONGenerator::serializeInfo(
const VarInfo &I, json::Object &Obj) {
818 serializeCommonAttributes(I, Obj);
821 serializeInfo(I.
Type, TypeObj);
822 Obj[
"Type"] = std::move(TypeObj);
825void JSONGenerator::serializeInfo(
const NamespaceInfo &I, json::Object &Obj) {
826 serializeCommonAttributes(I, Obj);
828 Obj[
"Name"] =
"Global Namespace";
832 serializeInfoLambda());
833 Obj[
"HasFunctions"] =
true;
838 Obj[
"HasConcepts"] =
true;
843 serializeInfoLambda());
844 Obj[
"HasVariables"] =
true;
847 ReferenceFunc SerializeReferenceFunc;
853 SerializeReferenceFunc = [
this, BasePath](
const Reference &Ref,
855 serializeMDReference(Ref, Object, BasePath);
857 serializeCommonChildren(I.
Children, Obj, SerializeReferenceFunc);
859 SerializeReferenceFunc = serializeReferenceLambda();
860 serializeCommonChildren(I.
Children, Obj);
865 SerializeReferenceFunc);
866 Obj[
"HasNamespaces"] =
true;
870SmallString<16> JSONGenerator::determineFileName(Info *I,
871 SmallString<128> &Path) {
872 SmallString<16> FileName;
873 if (I->
IT == InfoType::IT_record) {
874 auto *RecordSymbolInfo = cast<SymbolInfo>(I);
875 FileName = RecordSymbolInfo->MangledName;
876 }
else if (I->
IT == InfoType::IT_namespace) {
880 sys::path::append(Path, FileName +
".json");
888 std::vector<Index> Processed;
889 Processed.reserve(CDCtxIndex.
Children.size());
893 sys::path::native(NewPath, sys::path::Style::posix);
894 sys::path::append(NewPath, sys::path::Style::posix,
897 Processed.push_back(NewIdx);
904Error JSONGenerator::serializeAllFiles(
const ClangDocContext &CDCtx,
906 json::Value ObjVal =
Object();
909 serializeArray(IndexCopy, Obj,
"Index", serializeReferenceLambda());
910 SmallString<128>
Path;
911 sys::path::append(Path, RootDir,
"json",
"all_files.json");
912 std::error_code FileErr;
913 raw_fd_ostream RootOS(Path, FileErr, sys::fs::OF_Text);
915 return createFileError(
"cannot open file " + Path, FileErr);
916 RootOS << llvm::formatv(
"{0:2}", ObjVal);
917 return Error::success();
923Error JSONGenerator::serializeIndex(StringRef RootDir) {
925 return Error::success();
927 json::Value ObjVal =
Object();
931 auto IndexCopy = CDCtx->
Idx;
933 json::Value IndexArray = json::Array();
934 auto &IndexArrayRef = *IndexArray.getAsArray();
936 if (IndexCopy.Children.empty()) {
940 InfoType::IT_namespace,
"GlobalNamespace");
945 auto Children = IndexCopy.getSortedChildren();
947 for (
const auto *Idx : Children) {
948 if (Idx->Children.empty())
951 json::Value IdxVal =
Object();
952 auto &IdxObj = *IdxVal.getAsObject();
954 TypeStr.at(0) = clang::toUppercase(TypeStr.at(0));
955 IdxObj[
"Type"] = TypeStr;
956 serializeReference(*Idx, IdxObj);
957 IndexArrayRef.push_back(IdxVal);
959 Obj[
"Index"] = IndexArray;
961 SmallString<128> IndexFilePath(RootDir);
962 sys::path::append(IndexFilePath,
"/json/index.json");
963 std::error_code FileErr;
964 raw_fd_ostream RootOS(IndexFilePath, FileErr, sys::fs::OF_Text);
966 return createFileError(
"cannot open file " + IndexFilePath, FileErr);
968 RootOS << llvm::formatv(
"{0:2}", ObjVal);
970 RootOS << llvm::formatv(
"{0}", ObjVal);
971 return Error::success();
974void JSONGenerator::serializeContexts(Info *I, StringMap<Info *> &Infos) {
978 auto &LocalContexts = ContextsMap[I];
983 auto Iter = Infos.find(llvm::toHex(ParentUSR));
984 if (Iter == Infos.end())
986 auto &ParentInfo = Iter->second;
989 Context GlobalRef(ParentInfo->USR,
"Global Namespace",
990 InfoType::IT_namespace,
"GlobalNamespace",
"",
991 SmallString<16>(
"index"));
992 LocalContexts.push_back(GlobalRef);
996 Context ParentRef(*ParentInfo);
997 LocalContexts.push_back(ParentRef);
998 ParentUSR = ParentInfo->ParentUSR;
1002Error JSONGenerator::generateDocumentation(StringRef RootDir,
1003 llvm::StringMap<Info *> Infos,
1004 const ClangDocContext &CDCtx,
1005 std::string DirName) {
1006 this->CDCtx = &CDCtx;
1007 this->Infos = &Infos;
1008 StringSet<> CreatedDirs;
1009 StringMap<std::vector<Info *>> FileToInfos;
1010 for (
const auto &Group : Infos) {
1013 SmallString<128>
Path;
1014 auto RootDirStr = RootDir.str() +
"/json";
1015 StringRef JSONDir = StringRef(RootDirStr);
1016 sys::path::native(JSONDir, Path);
1017 sys::path::append(Path,
Info->getRelativeFilePath(
""));
1018 if (!CreatedDirs.contains(Path)) {
1019 if (std::error_code Err = sys::fs::create_directories(Path);
1020 Err != std::error_code())
1021 return createFileError(Twine(Path), Err);
1022 CreatedDirs.insert(Path);
1025 SmallString<16> FileName = determineFileName(Info, Path);
1026 if (FileToInfos.contains(Path))
1028 FileToInfos[
Path].push_back(Info);
1032 if (CDCtx.
Format == OutputFormatTy::md) {
1034 if (
auto Err = serializeAllFiles(CDCtx, RootDir))
1038 for (
const auto &Group : FileToInfos) {
1039 std::error_code FileErr;
1040 raw_fd_ostream InfoOS(Group.getKey(), FileErr, sys::fs::OF_Text);
1042 return createFileError(
"cannot open file " + Group.getKey(), FileErr);
1044 for (
const auto &Info : Group.getValue()) {
1045 if (
Info->IT == InfoType::IT_record ||
Info->IT == InfoType::IT_namespace)
1046 serializeContexts(Info, Infos);
1047 if (Error Err = generateDocForInfo(Info, InfoOS, CDCtx))
1052 return serializeIndex(RootDir);
1055Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
1056 const ClangDocContext &CDCtx) {
1060 case InfoType::IT_namespace:
1061 serializeInfo(*cast<NamespaceInfo>(I), Obj);
1063 case InfoType::IT_record:
1064 serializeInfo(*cast<RecordInfo>(I), Obj);
1066 case InfoType::IT_concept:
1067 case InfoType::IT_enum:
1068 case InfoType::IT_function:
1069 case InfoType::IT_typedef:
1070 case InfoType::IT_variable:
1071 case InfoType::IT_friend:
1073 case InfoType::IT_default:
1074 return createStringError(inconvertibleErrorCode(),
"unexpected info type");
1076 StringRef Fmt = CDCtx.
Pretty ?
"{0:2}" :
"{0}";
1077 OS << llvm::formatv(Fmt.data(), llvm::json::Value(std::move(Obj)));
1078 return Error::success();
1081Error JSONGenerator::createResources(ClangDocContext &CDCtx) {
1082 return Error::success();
1085static GeneratorRegistry::Add<JSONGenerator>
JSON(JSONGenerator::Format,
1086 "Generator for JSON output.");
static json::Value extractVerbatimComments(json::Array VerbatimLines)
static void serializeTemplateSpecialization(TemplateInfo Template, Object &TemplateObj)
static constexpr unsigned getMaxParamWrapLimit()
static void serializeDescription(const DocList< CommentInfo > &Description, json::Object &Obj, StringRef Key="")
static void serializeArray(const Container &Records, Object &Obj, const StringRef Key, SerializationFunc SerializeInfo, const StringRef EndKey="End", function_ref< void(Object &)> UpdateJson=[](Object &Obj) {})
static void insertNonEmpty(StringRef Key, StringRef Value, Object &Obj)
static json::Value extractTextComments(Object *ParagraphComment)
Takes the nested "Children" array from a comment Object.
static void insertComment(Object &Description, json::Value &Comment, StringRef Key)
Insert comments into a key in the Description object.
static std::vector< Index > preprocessCDCtxIndex(Index CDCtxIndex)
static auto SerializeTemplateParam
static std::string infoTypeToString(InfoType IT)
static Object serializeComment(const CommentInfo &I, Object &Description)
static json::Value safeJSONString(StringRef S)
static void insertArray(Object &Obj, json::Value &Array, StringRef Key)
static GeneratorRegistry::Add< JSONGenerator > JSON(JSONGenerator::Format, "Generator for JSON output.")
@ Info
An information message.
std::string Path
A typedef to represent a file path.
@ CK_InlineCommandComment
@ CK_VerbatimBlockLineComment
@ CK_VerbatimBlockComment
@ CK_TParamCommandComment
llvm::simple_ilist< InfoNode< T > > DocList
volatile int JSONGeneratorAnchorSource
llvm::StringRef getTagType(TagTypeKind AS)
StringRef internString(const Twine &T)
constexpr SymbolID GlobalNamespaceID
std::array< uint8_t, 20 > SymbolID
llvm::StringRef commentKindToString(CommentKind Kind)
Some operations such as code completion produce a set of candidates.
std::optional< std::string > RepositoryUrl
std::optional< std::string > RepositoryLinePrefix
StringRef ConstraintExpression
llvm::ArrayRef< EnumValueInfo > Members
std::optional< TypeInfo > BaseType
DocList< CommentInfo > Description
Comment description of this field.
std::optional< TypeInfo > ReturnType
llvm::ArrayRef< FieldTypeInfo > Params
std::optional< TemplateInfo > Template
llvm::ArrayRef< FieldTypeInfo > Params
std::optional< TemplateInfo > Template
llvm::StringMap< Index > Children
std::vector< const Index * > getSortedChildren() const
StringRef getRelativeFilePath(const StringRef &CurrentPath) const
Returns the file path for this Info relative to CurrentPath.
DocList< CommentInfo > Description
llvm::ArrayRef< Reference > Namespace
StringRef DocumentationFileName
llvm::ArrayRef< BaseRecordInfo > Bases
llvm::ArrayRef< FriendInfo > Friends
llvm::ArrayRef< Reference > VirtualParents
std::optional< TemplateInfo > Template
llvm::ArrayRef< Reference > Parents
llvm::ArrayRef< MemberTypeInfo > Members
StringRef DocumentationFileName
StringRef getFileBaseName() const
Returns the basename that should be used for this Reference.
StringRef getRelativeFilePath(const StringRef &CurrentPath) const
Returns the path for this Reference relative to CurrentPath.
DocList< ConceptInfo > Concepts
DocList< VarInfo > Variables
DocList< FunctionInfo > Functions
DocList< Reference > Namespaces
llvm::ArrayRef< TemplateParamInfo > Params
llvm::ArrayRef< ConstraintInfo > Constraints
std::optional< TemplateSpecializationInfo > Specialization
StringRef TypeDeclaration
std::optional< TemplateInfo > Template