18#include "clang/Basic/Specifiers.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/Support/JSON.h"
23using namespace llvm::json;
28template <
typename Container,
typename SerializationFunc>
30 const Container &Records, Object &Obj,
const StringRef Key,
31 SerializationFunc SerializeInfo,
const StringRef EndKey =
"End",
32 function_ref<
void(Object &)> UpdateJson = [](Object &Obj) {});
41 json::Object serializeLocation(
const Location &Loc);
42 void serializeCommonAttributes(
const Info &I, json::Object &Obj);
43 void serializeCommonChildren(
45 std::optional<ReferenceFunc> MDReferenceLambda = std::nullopt);
46 void serializeContexts(
Info *I, llvm::StringMap<Info *> &Infos);
48 void serializeInfo(
const TemplateInfo &Template, Object &Obj);
49 void serializeInfo(
const ConceptInfo &I, Object &Obj);
50 void serializeInfo(
const TypeInfo &I, Object &Obj);
52 void serializeInfo(
const FunctionInfo &F, json::Object &Obj);
54 void serializeInfo(
const EnumInfo &I, json::Object &Obj);
55 void serializeInfo(
const TypedefInfo &I, json::Object &Obj);
57 void serializeInfo(
const FriendInfo &I, Object &Obj);
58 void serializeInfo(
const RecordInfo &I, json::Object &Obj);
59 void serializeInfo(
const VarInfo &I, json::Object &Obj);
60 void serializeInfo(
const NamespaceInfo &I, json::Object &Obj);
61 SmallString<16> determineFileName(
Info *I, SmallString<128> &Path);
62 Error serializeIndex(StringRef RootDir);
63 void generateContext(
const Info &I, Object &Obj);
64 void serializeReference(
const Reference &Ref, Object &ReferenceObj);
65 Error serializeAllFiles(
const ClangDocContext &CDCtx, StringRef RootDir);
66 void serializeMDReference(
const Reference &Ref, Object &ReferenceObj,
69 void serializeClassSpecializations(
SymbolID ClassUSR, Object &ReferenceObj);
72 auto serializeInfoLambda() {
73 return [
this](
const auto &
Info, Object &Object) {
74 serializeInfo(
Info, Object);
77 auto serializeReferenceLambda() {
78 return [
this](
const auto &Ref, Object &Object) {
79 serializeReference(Ref, Object);
83 llvm::DenseMap<const Info *, SmallVector<Context, 4>> ContextsMap;
84 llvm::StringMap<doc::Info *> *Infos =
nullptr;
92 llvm::StringMap<doc::Info *> Infos,
94 std::string DirName)
override;
130 llvm_unreachable(
"Unknown InfoType encountered.");
133json::Object JSONGenerator::serializeLocation(
const Location &Loc) {
134 Object LocationObj = Object();
135 LocationObj[
"LineNumber"] = Loc.StartLineNumber;
136 LocationObj[
"Filename"] = Loc.Filename;
141 sys::path::append(FileURL, sys::path::Style::posix, Loc.Filename);
143 std::string LinePrefix;
149 FileURL += LinePrefix + std::to_string(Loc.StartLineNumber);
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();
361 serializeReference(Current, Context);
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));
441 insertNonEmpty(
"DocumentationFileName", I.DocumentationFileName, Obj);
444 if (!I.Namespace.empty()) {
445 Obj[
"Namespace"] = json::Array();
446 for (
const auto &NS : I.Namespace)
447 Obj[
"Namespace"].getAsArray()->push_back(NS.Name);
454 const auto *Symbol =
static_cast<const 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));
494 RecordInfo *ClassInfo =
static_cast<RecordInfo *
>(Class);
495 if (!ClassInfo->Template || !ClassInfo->Template->Specialization)
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));
506 if (!Ref.DocumentationFileName.empty()) {
507 ReferenceObj[
"DocumentationFileName"] = Ref.DocumentationFileName;
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) {
519 serializeReference(Ref, ReferenceObj);
520 SmallString<64>
Path = Ref.getRelativeFilePath(BasePath);
521 sys::path::native(Path, sys::path::Style::posix);
522 sys::path::append(Path, sys::path::Style::posix,
523 Ref.getFileBaseName() +
".md");
524 ReferenceObj[
"BasePath"] =
Path;
529void JSONGenerator::serializeCommonChildren(
531 std::optional<ReferenceFunc> MDReferenceLambda) {
534 Obj[
"HasEnums"] =
true;
539 Obj[
"HasTypedefs"] =
true;
543 ReferenceFunc BaseFunc = MDReferenceLambda ? MDReferenceLambda.value()
544 : serializeReferenceLambda();
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) {
579 serializeReference(I.ConceptRef, Obj);
580 Obj[
"Expression"] = I.ConstraintExpr;
583void JSONGenerator::serializeInfo(
const TemplateInfo &Template, Object &Obj) {
584 json::Value TemplateVal = Object();
585 auto &TemplateObj = *TemplateVal.getAsObject();
587 if (Template.Specialization)
590 if (!Template.Params.empty()) {
594 [VerticalDisplay](Object &JsonObj) {
595 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
599 if (!Template.Constraints.empty())
601 serializeInfoLambda());
603 Obj[
"Template"] = TemplateVal;
606void JSONGenerator::serializeInfo(
const ConceptInfo &I, Object &Obj) {
607 serializeCommonAttributes(I, Obj);
608 Obj[
"IsType"] = I.IsType;
609 Obj[
"ConstraintExpression"] = I.ConstraintExpression;
610 serializeInfo(I.Template, Obj);
613void JSONGenerator::serializeInfo(
const TypeInfo &I, Object &Obj) {
614 Obj[
"Name"] = I.Type.Name;
615 Obj[
"QualName"] = I.Type.QualName;
616 Obj[
"USR"] = toHex(toStringRef(I.Type.USR));
617 Obj[
"IsTemplate"] = I.IsTemplate;
618 Obj[
"IsBuiltIn"] = I.IsBuiltIn;
621void JSONGenerator::serializeInfo(
const FieldTypeInfo &I, Object &Obj) {
622 Obj[
"Name"] = I.Name;
624 json::Value ReferenceVal =
Object();
625 Object &ReferenceObj = *ReferenceVal.getAsObject();
626 serializeReference(I.Type, ReferenceObj);
627 Obj[
"Type"] = ReferenceVal;
630void JSONGenerator::serializeInfo(
const FunctionInfo &F, json::Object &Obj) {
631 serializeCommonAttributes(F, Obj);
632 Obj[
"IsStatic"] = F.IsStatic;
634 auto ReturnTypeObj =
Object();
635 serializeInfo(F.ReturnType, ReturnTypeObj);
636 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
638 if (!F.Params.empty()) {
640 serializeArray(F.Params, Obj,
"Params", serializeInfoLambda(),
"ParamEnd",
641 [VerticalDisplay](Object &JsonObj) {
642 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
647 serializeInfo(F.Template.value(), Obj);
650void JSONGenerator::serializeInfo(
const EnumValueInfo &I, Object &Obj) {
651 Obj[
"Name"] = I.Name;
652 if (!I.ValueExpr.empty())
653 Obj[
"ValueExpr"] = I.ValueExpr;
655 Obj[
"Value"] = I.Value;
660void JSONGenerator::serializeInfo(
const EnumInfo &I, json::Object &Obj) {
661 serializeCommonAttributes(I, Obj);
662 Obj[
"Scoped"] = I.Scoped;
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;
673 if (!I.Members.empty()) {
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);
686 Obj[
"TypeDeclaration"] = I.TypeDeclaration;
687 Obj[
"IsUsing"] = I.IsUsing;
688 json::Value TypeVal =
Object();
689 auto &TypeObj = *TypeVal.getAsObject();
690 serializeInfo(I.Underlying, TypeObj);
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);
698 Obj[
"IsVirtual"] = I.IsVirtual;
699 Obj[
"Access"] = getAccessSpelling(I.Access);
700 Obj[
"IsParent"] = I.IsParent;
703void JSONGenerator::serializeInfo(
const FriendInfo &I, Object &Obj) {
704 auto FriendRef =
Object();
705 serializeReference(I.Ref, FriendRef);
706 Obj[
"Reference"] = std::move(FriendRef);
707 Obj[
"IsClass"] = I.IsClass;
709 serializeInfo(I.Template.value(), Obj);
710 if (!I.Params.empty())
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);
728 Obj[
"IsTypedef"] = I.IsTypeDef;
729 Obj[
"MangledName"] = I.MangledName;
731 if (!I.Children.Functions.empty()) {
732 json::Value PubFunctionsArray = Array();
733 json::Array &PubFunctionsArrayRef = *PubFunctionsArray.getAsArray();
734 json::Value ProtFunctionsArray = Array();
735 json::Array &ProtFunctionsArrayRef = *ProtFunctionsArray.getAsArray();
737 for (
const auto &Function : I.Children.Functions) {
738 json::Value FunctionVal = Object();
739 auto &FunctionObj = *FunctionVal.getAsObject();
740 serializeInfo(Function, FunctionObj);
741 AccessSpecifier Access = Function->Access;
742 if (Access == AccessSpecifier::AS_public)
743 PubFunctionsArrayRef.push_back(FunctionVal);
744 else if (Access == 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");
754 if (!I.Members.empty()) {
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 == AccessSpecifier::AS_public)
771 PubMembersArrayRef.push_back(MemberVal);
772 else if (Member.Access == AccessSpecifier::AS_protected)
773 ProtMembersArrayRef.push_back(MemberVal);
774 else if (Member.Access == 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())
789 if (!I.Parents.empty()) {
790 serializeArray(I.Parents, Obj,
"Parents", serializeReferenceLambda());
791 Obj[
"HasParents"] =
true;
794 if (!I.VirtualParents.empty()) {
796 serializeReferenceLambda());
797 Obj[
"HasVirtualParents"] =
true;
801 serializeInfo(I.Template.value(), Obj);
803 if (!I.Friends.empty()) {
805 Obj[
"HasFriends"] =
true;
808 serializeCommonChildren(I.Children, Obj);
811void JSONGenerator::serializeInfo(
const VarInfo &I, json::Object &Obj) {
812 serializeCommonAttributes(I, Obj);
813 Obj[
"IsStatic"] = I.IsStatic;
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";
824 if (!I.Children.Functions.empty()) {
826 serializeInfoLambda());
827 Obj[
"HasFunctions"] =
true;
830 if (!I.Children.Concepts.empty()) {
831 serializeArray(I.Children.Concepts, Obj,
"Concepts", serializeInfoLambda());
832 Obj[
"HasConcepts"] =
true;
835 if (!I.Children.Variables.empty()) {
837 serializeInfoLambda());
838 Obj[
"HasVariables"] =
true;
843 SmallString<64> BasePath = I.getRelativeFilePath(
"");
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);
857 if (!I.Children.Namespaces.empty()) {
859 SerializeReferenceFunc);
860 Obj[
"HasNamespaces"] =
true;
864SmallString<16> JSONGenerator::determineFileName(
Info *I,
865 SmallString<128> &Path) {
866 SmallString<16> FileName;
868 auto *RecordSymbolInfo =
static_cast<SymbolInfo *
>(I);
869 FileName = RecordSymbolInfo->MangledName;
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();
901 Object &Obj = *ObjVal.getAsObject();
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) {
918 if (CDCtx->Idx.Children.empty())
919 return Error::success();
921 json::Value ObjVal = Object();
922 Object &Obj = *ObjVal.getAsObject();
925 auto IndexCopy = CDCtx->Idx;
927 json::Value IndexArray = json::Array();
928 auto &IndexArrayRef = *IndexArray.getAsArray();
930 if (IndexCopy.Children.empty()) {
936 IndexArrayRef.reserve(CDCtx->Idx.Children.size());
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) = toUppercase(TypeStr.at(0));
949 IdxObj[
"Type"] = TypeStr;
950 serializeReference(*Idx, IdxObj);
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) {
971 auto ParentUSR = I->ParentUSR;
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",
985 SmallString<16>(
"index"));
986 LocalContexts.push_back(GlobalRef);
990 Context ParentRef(*ParentInfo);
991 LocalContexts.push_back(ParentRef);
992 ParentUSR = ParentInfo->ParentUSR;
997 llvm::StringMap<doc::Info *> Infos,
999 std::string DirName) {
1000 this->CDCtx = &CDCtx;
1001 this->Infos = &Infos;
1002 StringSet<> CreatedDirs;
1003 StringMap<std::vector<doc::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);
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);
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()) {
1040 serializeContexts(
Info, Infos);
1046 return serializeIndex(RootDir);
1051 json::Object Obj = Object();
1058 serializeInfo(*
static_cast<RecordInfo *
>(I), Obj);
1068 return createStringError(inconvertibleErrorCode(),
"unexpected info type");
1071 OS << llvm::formatv(
"{0:2}", llvm::json::Value(std::move(Obj)));
1073 OS << llvm::formatv(
"{0}", llvm::json::Value(std::move(Obj)));
1074 return Error::success();
1078 return Error::success();
1082 "Generator for JSON output.");
clang::find_all_symbols::SymbolInfo SymbolInfo
static const char * Format
Error generateDocForInfo(Info *I, llvm::raw_ostream &OS, const ClangDocContext &CDCtx) override
Error createResources(ClangDocContext &CDCtx) override
Error generateDocumentation(StringRef RootDir, llvm::StringMap< doc::Info * > Infos, const ClangDocContext &CDCtx, std::string DirName) override
std::string Path
A typedef to represent a file path.
static constexpr unsigned getMaxParamWrapLimit()
static std::string infoTypeToString(InfoType IT)
static json::Value extractTextComments(Object *ParagraphComment)
Takes the nested "Children" array from a comment Object.
static Object serializeComment(const CommentInfo &I, Object &Description)
@ CK_InlineCommandComment
@ CK_VerbatimBlockLineComment
@ CK_VerbatimBlockComment
@ CK_TParamCommandComment
static void insertComment(Object &Description, json::Value &Comment, StringRef Key)
Insert comments into a key in the Description object.
static void serializeTemplateSpecialization(TemplateInfo Template, Object &TemplateObj)
llvm::simple_ilist< InfoNode< T > > DocList
volatile int JSONGeneratorAnchorSource
llvm::StringRef getTagType(TagTypeKind AS)
static GeneratorRegistry::Add< JSONGenerator > JSON(JSONGenerator::Format, "Generator for JSON output.")
static auto SerializeTemplateParam
std::function< void(const Reference &, Object &)> ReferenceFunc
StringRef internString(const Twine &T)
static void serializeArray(const Container &Records, Object &Obj, const StringRef Key, SerializationFunc SerializeInfo, const StringRef EndKey="End", function_ref< void(Object &)> UpdateJson=[](Object &Obj) {})
constexpr SymbolID GlobalNamespaceID
static json::Value extractVerbatimComments(json::Array VerbatimLines)
static void insertNonEmpty(StringRef Key, StringRef Value, Object &Obj)
std::array< uint8_t, 20 > SymbolID
llvm::StringRef commentKindToString(CommentKind Kind)
static void insertArray(Object &Obj, json::Value &Array, StringRef Key)
static std::vector< Index > preprocessCDCtxIndex(Index CDCtxIndex)
static void serializeDescription(const DocList< CommentInfo > &Description, json::Object &Obj, StringRef Key="")
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Some operations such as code completion produce a set of candidates.
std::optional< std::string > RepositoryUrl
std::optional< std::string > RepositoryLinePrefix
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.
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.