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);
62 void generateContext(
const Info &I, Object &Obj);
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() {
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";
130 llvm_unreachable(
"Unknown InfoType encountered.");
133json::Object JSONGenerator::serializeLocation(
const Location &Loc) {
136 LocationObj[
"Filename"] = Loc.
Filename;
141 sys::path::append(FileURL, sys::path::Style::posix, Loc.
Filename);
143 std::string LinePrefix;
150 LocationObj[
"FileURL"] = FileURL;
162 if (
auto *Obj = Comment.getAsObject()) {
163 if (
auto *Children = Obj->getArray(
"Children");
164 Children && Children->empty())
168 else if (
auto *Array = Comment.getAsArray(); Array && Array->empty()) {
172 auto DescriptionIt = Description.find(Key);
174 if (DescriptionIt == Description.end()) {
175 auto CommentsArray = json::Array();
176 CommentsArray.push_back(Comment);
177 Description[Key] = std::move(CommentsArray);
178 Description[
"Has" + Key.str()] =
true;
180 DescriptionIt->getSecond().getAsArray()->push_back(Comment);
188 if (!ParagraphComment)
189 return json::Value(
nullptr);
190 json::Value *Children = ParagraphComment->get(
"Children");
192 return json::Value(
nullptr);
193 auto ChildrenArray = *Children->getAsArray();
194 auto ChildrenIt = ChildrenArray.begin();
195 while (ChildrenIt != ChildrenArray.end()) {
196 auto *ChildObj = ChildrenIt->getAsObject();
197 assert(ChildObj &&
"Invalid JSON object in Comment");
198 auto TextComment = ChildObj->getString(
"TextComment");
199 if (!TextComment || TextComment->empty()) {
200 ChildrenIt = ChildrenArray.erase(ChildrenIt);
205 return ChildrenArray;
209 json::Value TextArray = json::Array();
210 auto &TextArrayRef = *TextArray.getAsArray();
211 for (
auto &Line : VerbatimLines)
212 TextArrayRef.push_back(*Line.getAsObject()
213 ->get(
"VerbatimBlockLineComment")
222 Object Obj = Object();
224 json::Value ChildVal = Object();
225 Object &Child = *ChildVal.getAsObject();
227 json::Value ChildArr = Array();
228 auto &CARef = *ChildArr.getAsArray();
242 if (I.
Name ==
"brief")
243 insertComment(Description, TextCommentsArray,
"BriefComments");
244 else if (I.
Name ==
"return")
245 insertComment(Description, TextCommentsArray,
"ReturnComments");
246 else if (I.
Name ==
"throws" || I.
Name ==
"throw") {
247 json::Value ThrowsVal = Object();
248 auto &ThrowsObj = *ThrowsVal.getAsObject();
249 ThrowsObj[
"Exception"] = I.
Args.front();
250 ThrowsObj[
"Children"] = TextCommentsArray;
257 json::Value ArgsArr = Array();
258 auto &ARef = *ArgsArr.getAsArray();
259 ARef.reserve(I.
Args.size());
260 for (
const auto &Arg : I.
Args)
261 ARef.emplace_back(Arg);
262 Child.insert({
"Command", I.
Name});
263 Child.insert({
"Args", ArgsArr});
264 Child.insert({
"Children", ChildArr});
271 Child.insert({
"ParamName", I.
ParamName});
272 Child.insert({
"Direction", I.
Direction});
273 Child.insert({
"Explicit", I.
Explicit});
275 Child.insert({
"Children", TextCommentsArray});
287 insertComment(Description, TextCommentsArray,
"CodeComments");
295 Child.insert({
"Text", I.
Text});
296 Child.insert({
"Children", ChildArr});
302 json::Value AttrKeysArray = json::Array();
303 json::Value AttrValuesArray = json::Array();
304 auto &KeyArr = *AttrKeysArray.getAsArray();
305 auto &ValArr = *AttrValuesArray.getAsArray();
309 KeyArr.emplace_back(K);
311 ValArr.emplace_back(V);
312 Child.insert({
"Name", I.
Name});
314 Child.insert({
"AttrKeys", AttrKeysArray});
315 Child.insert({
"AttrValues", AttrValuesArray});
316 Child.insert({
"Children", ChildArr});
322 Child.insert({
"Name", I.
Name});
323 Child.insert({
"Children", ChildArr});
330 Child.insert({
"Children", ChildArr});
331 Child[
"ParagraphComment"] =
true;
340 llvm_unreachable(
"Unknown comment kind encountered.");
344void JSONGenerator::generateContext(
const Info &I, Object &Obj) {
345 Obj[
"Contexts"] = json::Array();
346 Obj[
"HasContexts"] =
true;
348 auto It = ContextsMap.find(&I);
349 if (It == ContextsMap.end() || It->second.empty())
352 auto &ContextArrayRef = *
Obj[
"Contexts"].getAsArray();
353 const auto &Contexts = It->second;
354 ContextArrayRef.reserve(Contexts.size());
356 std::string CurrentRelativePath;
357 bool PreviousRecord =
false;
358 for (
const auto &Current : Contexts) {
359 json::Value ContextVal =
Object();
360 Object &Context = *ContextVal.getAsObject();
363 if (ContextArrayRef.empty() && I.
IT == InfoType::IT_record) {
364 if (Current.DocumentationFileName ==
"index") {
367 PreviousRecord =
false;
368 Context[
"RelativePath"] =
"./";
372 PreviousRecord =
true;
373 CurrentRelativePath +=
"../";
374 Context[
"RelativePath"] = CurrentRelativePath;
376 ContextArrayRef.push_back(ContextVal);
380 if (PreviousRecord && (Current.DocumentationFileName ==
"index")) {
383 PreviousRecord =
false;
384 }
else if (Current.DocumentationFileName !=
"index") {
387 PreviousRecord =
true;
388 CurrentRelativePath +=
"../";
391 PreviousRecord =
false;
392 CurrentRelativePath +=
"../";
395 if (Current.QualName ==
"GlobalNamespace" && Current.RelativePath !=
"./")
396 Context[
"DocumentationFileName"] =
397 SmallString<16>(
"GlobalNamespace/index");
399 Context[
"RelativePath"] = CurrentRelativePath;
400 ContextArrayRef.insert(ContextArrayRef.begin(), ContextVal);
403 ContextArrayRef.back().getAsObject()->insert({
"End",
true});
407 json::Object &Obj, StringRef Key =
"") {
408 if (Description.empty())
412 auto &Comments = Description.front()->Children;
413 Object DescriptionObj = Object();
418 if (
auto *ParagraphComment = Comment.getAsObject();
419 ParagraphComment->get(
"ParagraphComment")) {
421 if (TextCommentsArray.kind() == json::Value::Null ||
422 TextCommentsArray.getAsArray()->empty())
424 insertComment(DescriptionObj, TextCommentsArray,
"ParagraphComments");
427 Obj[
"Description"] = std::move(DescriptionObj);
432void JSONGenerator::serializeCommonAttributes(
const Info &I,
436 Obj[
"USR"] = toHex(toStringRef(I.
USR));
445 Obj[
"Namespace"] = json::Array();
447 Obj[
"Namespace"].getAsArray()->push_back(NS.Name);
453 if (I.
IT != InfoType::IT_namespace) {
454 const auto *Symbol = cast<SymbolInfo>(&I);
456 Obj[
"Location"] = serializeLocation(Symbol->DefLoc.value());
459 auto It = ContextsMap.find(&I);
460 if (It != ContextsMap.end() && !It->second.empty())
461 generateContext(I, Obj);
470 Object &TemplateObj) {
471 json::Value TemplateSpecializationVal = Object();
472 auto &TemplateSpecializationObj = *TemplateSpecializationVal.getAsObject();
473 TemplateSpecializationObj[
"SpecializationOf"] =
474 toHex(toStringRef(Template.Specialization->SpecializationOf));
475 if (!Template.Specialization->Params.empty()) {
476 bool VerticalDisplay =
478 serializeArray(Template.Specialization->Params, TemplateSpecializationObj,
480 [VerticalDisplay](Object &JsonObj) {
481 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
484 TemplateObj[
"Specialization"] = TemplateSpecializationVal;
487void JSONGenerator::serializeClassSpecializations(
SymbolID ClassUSR,
488 Object &ReferenceObj) {
491 auto *
Class = Infos->lookup(toHex(ClassUSR));
492 if (!Class ||
Class->IT != InfoType::IT_record)
494 RecordInfo *ClassInfo = cast<RecordInfo>(Class);
500void JSONGenerator::serializeReference(
const Reference &Ref,
501 Object &ReferenceObj) {
503 ReferenceObj[
"Name"] = Ref.
Name;
504 ReferenceObj[
"QualName"] = Ref.
QualName;
505 ReferenceObj[
"USR"] = toHex(toStringRef(Ref.
USR));
511 if (Ref.
Path !=
"GlobalNamespace" && !Ref.
Path.empty())
512 ReferenceObj[
"PathStem"] = sys::path::stem(Ref.
Path);
516void JSONGenerator::serializeMDReference(
const Reference &Ref,
517 Object &ReferenceObj,
518 StringRef BasePath) {
521 sys::path::native(Path, sys::path::Style::posix);
522 sys::path::append(Path, sys::path::Style::posix,
524 ReferenceObj[
"BasePath"] =
Path;
529void JSONGenerator::serializeCommonChildren(
530 const ScopeChildren &Children, json::Object &Obj,
531 std::optional<ReferenceFunc> MDReferenceLambda) {
534 Obj[
"HasEnums"] =
true;
539 Obj[
"HasTypedefs"] =
true;
543 ReferenceFunc BaseFunc = MDReferenceLambda ? MDReferenceLambda.value()
544 : serializeReferenceLambda();
546 ReferenceFunc SerializeReferenceFunc =
547 [
this, BaseFunc](
const Reference &Ref,
Object &
Object) {
548 BaseFunc(Ref, Object);
549 serializeClassSpecializations(Ref.
USR, Object);
552 Obj[
"HasRecords"] =
true;
556template <
typename Container,
typename SerializationFunc>
558 SerializationFunc SerializeInfo, StringRef EndKey,
559 function_ref<
void(Object &)> UpdateJson) {
560 json::Value RecordsArray = Array();
561 auto &RecordsArrayRef = *RecordsArray.getAsArray();
562 RecordsArrayRef.reserve(Records.size());
564 size_t Size = Records.size();
565 for (
const auto &Item : Records) {
566 json::Value ItemVal = Object();
567 auto &ItemObj = *ItemVal.getAsObject();
568 SerializeInfo(Item, ItemObj);
569 if (
Index == Size - 1)
570 ItemObj[EndKey] =
true;
571 RecordsArrayRef.push_back(ItemVal);
574 Obj[Key] = RecordsArray;
578void JSONGenerator::serializeInfo(
const ConstraintInfo &I, Object &Obj) {
583void JSONGenerator::serializeInfo(
const TemplateInfo &Template, Object &Obj) {
584 json::Value TemplateVal =
Object();
585 auto &TemplateObj = *TemplateVal.getAsObject();
590 if (!Template.
Params.empty()) {
594 [VerticalDisplay](Object &JsonObj) {
595 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
601 serializeInfoLambda());
603 Obj[
"Template"] = TemplateVal;
606void JSONGenerator::serializeInfo(
const ConceptInfo &I, Object &Obj) {
607 serializeCommonAttributes(I, Obj);
613void JSONGenerator::serializeInfo(
const TypeInfo &I, Object &Obj) {
621void JSONGenerator::serializeInfo(
const FieldTypeInfo &I, Object &Obj) {
624 json::Value ReferenceVal =
Object();
625 Object &ReferenceObj = *ReferenceVal.getAsObject();
627 Obj[
"Type"] = ReferenceVal;
630void JSONGenerator::serializeInfo(
const FunctionInfo &F, json::Object &Obj) {
631 serializeCommonAttributes(F, Obj);
634 auto ReturnTypeObj =
Object();
636 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
641 [VerticalDisplay](Object &JsonObj) {
642 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
647 serializeInfo(F.
Template.value(), Obj);
650void JSONGenerator::serializeInfo(
const EnumValueInfo &I, Object &Obj) {
660void JSONGenerator::serializeInfo(
const EnumInfo &I, json::Object &Obj) {
661 serializeCommonAttributes(I, Obj);
665 json::Value BaseTypeVal =
Object();
666 auto &BaseTypeObj = *BaseTypeVal.getAsObject();
667 BaseTypeObj[
"Name"] = I.
BaseType->Type.Name;
668 BaseTypeObj[
"QualName"] = I.
BaseType->Type.QualName;
669 BaseTypeObj[
"USR"] = toHex(toStringRef(I.
BaseType->Type.USR));
670 Obj[
"BaseType"] = BaseTypeVal;
674 for (
const auto &Member : I.
Members) {
675 if (!Member.Description.empty()) {
676 Obj[
"HasComments"] =
true;
684void JSONGenerator::serializeInfo(
const TypedefInfo &I, json::Object &Obj) {
685 serializeCommonAttributes(I, Obj);
688 json::Value TypeVal =
Object();
689 auto &TypeObj = *TypeVal.getAsObject();
691 Obj[
"Underlying"] = TypeVal;
693 serializeInfo(I.
Template.value(), Obj);
696void JSONGenerator::serializeInfo(
const BaseRecordInfo &I, Object &Obj) {
697 serializeInfo(
static_cast<const RecordInfo &
>(I), Obj);
699 Obj[
"Access"] = getAccessSpelling(I.
Access);
703void JSONGenerator::serializeInfo(
const FriendInfo &I, Object &Obj) {
704 auto FriendRef =
Object();
706 Obj[
"Reference"] = std::move(FriendRef);
709 serializeInfo(I.
Template.value(), Obj);
713 auto ReturnTypeObj =
Object();
714 serializeInfo(I.
ReturnType.value(), ReturnTypeObj);
715 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
717 serializeCommonAttributes(I, Obj);
720static void insertArray(Object &Obj, json::Value &Array, StringRef Key) {
722 Obj[
"Has" + Key.str()] =
true;
725void JSONGenerator::serializeInfo(
const RecordInfo &I, json::Object &Obj) {
726 serializeCommonAttributes(I, Obj);
732 json::Value PubFunctionsArray =
Array();
733 json::Array &PubFunctionsArrayRef = *PubFunctionsArray.getAsArray();
734 json::Value ProtFunctionsArray =
Array();
735 json::Array &ProtFunctionsArrayRef = *ProtFunctionsArray.getAsArray();
738 json::Value FunctionVal =
Object();
739 auto &FunctionObj = *FunctionVal.getAsObject();
740 serializeInfo(Function, FunctionObj);
741 clang::AccessSpecifier Access =
Function->Access;
742 if (Access == clang::AccessSpecifier::AS_public)
743 PubFunctionsArrayRef.push_back(FunctionVal);
744 else if (Access == clang::AccessSpecifier::AS_protected)
745 ProtFunctionsArrayRef.push_back(FunctionVal);
748 if (!PubFunctionsArrayRef.empty())
749 insertArray(Obj, PubFunctionsArray,
"PublicMethods");
750 if (!ProtFunctionsArrayRef.empty())
751 insertArray(Obj, ProtFunctionsArray,
"ProtectedMethods");
755 Obj[
"HasMembers"] =
true;
756 json::Value PublicMembersArray =
Array();
757 json::Array &PubMembersArrayRef = *PublicMembersArray.getAsArray();
758 json::Value ProtectedMembersArray =
Array();
759 json::Array &ProtMembersArrayRef = *ProtectedMembersArray.getAsArray();
760 json::Value PrivateMembersArray =
Array();
761 json::Array &PrivateMembersArrayRef = *PrivateMembersArray.getAsArray();
763 for (
const MemberTypeInfo &Member : I.
Members) {
764 json::Value MemberVal =
Object();
765 auto &MemberObj = *MemberVal.getAsObject();
766 MemberObj[
"Name"] = Member.
Name;
767 MemberObj[
"Type"] = Member.
Type.
Name;
768 MemberObj[
"IsStatic"] = Member.
IsStatic;
770 if (Member.
Access == clang::AccessSpecifier::AS_public)
771 PubMembersArrayRef.push_back(MemberVal);
772 else if (Member.
Access == clang::AccessSpecifier::AS_protected)
773 ProtMembersArrayRef.push_back(MemberVal);
774 else if (Member.
Access == clang::AccessSpecifier::AS_private)
775 PrivateMembersArrayRef.push_back(MemberVal);
778 if (!PubMembersArrayRef.empty())
779 insertArray(Obj, PublicMembersArray,
"PublicMembers");
780 if (!ProtMembersArrayRef.empty())
781 insertArray(Obj, ProtectedMembersArray,
"ProtectedMembers");
782 if (!PrivateMembersArrayRef.empty())
783 insertArray(Obj, PrivateMembersArray,
"PrivateMembers");
786 if (!I.
Bases.empty())
791 Obj[
"HasParents"] =
true;
796 serializeReferenceLambda());
797 Obj[
"HasVirtualParents"] =
true;
801 serializeInfo(I.
Template.value(), Obj);
805 Obj[
"HasFriends"] =
true;
808 serializeCommonChildren(I.
Children, Obj);
811void JSONGenerator::serializeInfo(
const VarInfo &I, json::Object &Obj) {
812 serializeCommonAttributes(I, Obj);
815 serializeInfo(I.
Type, TypeObj);
816 Obj[
"Type"] = std::move(TypeObj);
819void JSONGenerator::serializeInfo(
const NamespaceInfo &I, json::Object &Obj) {
820 serializeCommonAttributes(I, Obj);
822 Obj[
"Name"] =
"Global Namespace";
826 serializeInfoLambda());
827 Obj[
"HasFunctions"] =
true;
832 Obj[
"HasConcepts"] =
true;
837 serializeInfoLambda());
838 Obj[
"HasVariables"] =
true;
841 ReferenceFunc SerializeReferenceFunc;
847 SerializeReferenceFunc = [
this, BasePath](
const Reference &Ref,
849 serializeMDReference(Ref, Object, BasePath);
851 serializeCommonChildren(I.
Children, Obj, SerializeReferenceFunc);
853 SerializeReferenceFunc = serializeReferenceLambda();
854 serializeCommonChildren(I.
Children, Obj);
859 SerializeReferenceFunc);
860 Obj[
"HasNamespaces"] =
true;
864SmallString<16> JSONGenerator::determineFileName(Info *I,
865 SmallString<128> &Path) {
866 SmallString<16> FileName;
867 if (I->
IT == InfoType::IT_record) {
868 auto *RecordSymbolInfo = cast<SymbolInfo>(I);
869 FileName = RecordSymbolInfo->MangledName;
870 }
else if (I->
IT == InfoType::IT_namespace) {
874 sys::path::append(Path, FileName +
".json");
882 std::vector<Index> Processed;
883 Processed.reserve(CDCtxIndex.
Children.size());
887 sys::path::native(NewPath, sys::path::Style::posix);
888 sys::path::append(NewPath, sys::path::Style::posix,
891 Processed.push_back(NewIdx);
898Error JSONGenerator::serializeAllFiles(
const ClangDocContext &CDCtx,
900 json::Value ObjVal =
Object();
903 serializeArray(IndexCopy, Obj,
"Index", serializeReferenceLambda());
904 SmallString<128>
Path;
905 sys::path::append(Path, RootDir,
"json",
"all_files.json");
906 std::error_code FileErr;
907 raw_fd_ostream RootOS(Path, FileErr, sys::fs::OF_Text);
909 return createFileError(
"cannot open file " + Path, FileErr);
910 RootOS << llvm::formatv(
"{0:2}", ObjVal);
911 return Error::success();
917Error JSONGenerator::serializeIndex(StringRef RootDir) {
919 return Error::success();
921 json::Value ObjVal =
Object();
925 auto IndexCopy = CDCtx->
Idx;
927 json::Value IndexArray = json::Array();
928 auto &IndexArrayRef = *IndexArray.getAsArray();
930 if (IndexCopy.Children.empty()) {
934 InfoType::IT_namespace,
"GlobalNamespace");
939 auto Children = IndexCopy.getSortedChildren();
941 for (
const auto *Idx : Children) {
942 if (Idx->Children.empty())
945 json::Value IdxVal =
Object();
946 auto &IdxObj = *IdxVal.getAsObject();
948 TypeStr.at(0) = clang::toUppercase(TypeStr.at(0));
949 IdxObj[
"Type"] = TypeStr;
951 IndexArrayRef.push_back(IdxVal);
953 Obj[
"Index"] = IndexArray;
955 SmallString<128> IndexFilePath(RootDir);
956 sys::path::append(IndexFilePath,
"/json/index.json");
957 std::error_code FileErr;
958 raw_fd_ostream RootOS(IndexFilePath, FileErr, sys::fs::OF_Text);
960 return createFileError(
"cannot open file " + IndexFilePath, FileErr);
962 RootOS << llvm::formatv(
"{0:2}", ObjVal);
964 RootOS << llvm::formatv(
"{0}", ObjVal);
965 return Error::success();
968void JSONGenerator::serializeContexts(Info *I, StringMap<Info *> &Infos) {
972 auto &LocalContexts = ContextsMap[I];
977 auto Iter = Infos.find(llvm::toHex(ParentUSR));
978 if (Iter == Infos.end())
980 auto &ParentInfo = Iter->second;
983 Context GlobalRef(ParentInfo->USR,
"Global Namespace",
984 InfoType::IT_namespace,
"GlobalNamespace",
"",
985 SmallString<16>(
"index"));
986 LocalContexts.push_back(GlobalRef);
990 Context ParentRef(*ParentInfo);
991 LocalContexts.push_back(ParentRef);
992 ParentUSR = ParentInfo->ParentUSR;
996Error JSONGenerator::generateDocumentation(StringRef RootDir,
997 llvm::StringMap<Info *> Infos,
998 const ClangDocContext &CDCtx,
999 std::string DirName) {
1000 this->CDCtx = &CDCtx;
1001 this->Infos = &Infos;
1002 StringSet<> CreatedDirs;
1003 StringMap<std::vector<Info *>> FileToInfos;
1004 for (
const auto &Group : Infos) {
1007 SmallString<128>
Path;
1008 auto RootDirStr = RootDir.str() +
"/json";
1009 StringRef JSONDir = StringRef(RootDirStr);
1010 sys::path::native(JSONDir, Path);
1011 sys::path::append(Path,
Info->getRelativeFilePath(
""));
1012 if (!CreatedDirs.contains(Path)) {
1013 if (std::error_code Err = sys::fs::create_directories(Path);
1014 Err != std::error_code())
1015 return createFileError(Twine(Path), Err);
1016 CreatedDirs.insert(Path);
1019 SmallString<16> FileName = determineFileName(Info, Path);
1020 if (FileToInfos.contains(Path))
1022 FileToInfos[
Path].push_back(Info);
1026 if (CDCtx.
Format == OutputFormatTy::md_mustache) {
1028 if (
auto Err = serializeAllFiles(CDCtx, RootDir))
1032 for (
const auto &Group : FileToInfos) {
1033 std::error_code FileErr;
1034 raw_fd_ostream InfoOS(Group.getKey(), FileErr, sys::fs::OF_Text);
1036 return createFileError(
"cannot open file " + Group.getKey(), FileErr);
1038 for (
const auto &Info : Group.getValue()) {
1039 if (
Info->IT == InfoType::IT_record ||
Info->IT == InfoType::IT_namespace)
1040 serializeContexts(Info, Infos);
1041 if (Error Err = generateDocForInfo(Info, InfoOS, CDCtx))
1049Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
1050 const ClangDocContext &CDCtx) {
1054 case InfoType::IT_namespace:
1055 serializeInfo(*cast<NamespaceInfo>(I), Obj);
1057 case InfoType::IT_record:
1058 serializeInfo(*cast<RecordInfo>(I), Obj);
1060 case InfoType::IT_concept:
1061 case InfoType::IT_enum:
1062 case InfoType::IT_function:
1063 case InfoType::IT_typedef:
1064 case InfoType::IT_variable:
1065 case InfoType::IT_friend:
1067 case InfoType::IT_default:
1068 return createStringError(inconvertibleErrorCode(),
"unexpected info type");
1070 StringRef Fmt = CDCtx.
Pretty ?
"{0:2}" :
"{0}";
1071 OS << llvm::formatv(Fmt.data(), llvm::json::Value(std::move(Obj)));
1072 return Error::success();
1075Error JSONGenerator::createResources(ClangDocContext &CDCtx) {
1076 return Error::success();
1079static GeneratorRegistry::Add<JSONGenerator>
JSON(JSONGenerator::Format,
1080 "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 void insertArray(Object &Obj, json::Value &Array, StringRef Key)
static GeneratorRegistry::Add< JSONGenerator > JSON(JSONGenerator::Format, "Generator for JSON output.")
static void serializeReference(llvm::raw_fd_ostream &OS, const Index &I, int Level)
static llvm::Error serializeIndex(ClangDocContext &CDCtx)
@ 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