2#include "clang/Basic/Specifiers.h"
3#include "llvm/ADT/ArrayRef.h"
4#include "llvm/Support/JSON.h"
7using namespace llvm::json;
12template <
typename Container,
typename SerializationFunc>
14 const Container &Records, Object &Obj,
const StringRef Key,
15 SerializationFunc SerializeInfo,
const StringRef EndKey =
"End",
16 function_ref<
void(Object &)> UpdateJson = [](Object &Obj) {});
25 json::Object serializeLocation(
const Location &Loc);
26 void serializeCommonAttributes(
const Info &I, json::Object &Obj);
27 void serializeCommonChildren(
29 std::optional<ReferenceFunc> MDReferenceLambda = std::nullopt);
32 void serializeInfo(
const TemplateInfo &Template, Object &Obj);
33 void serializeInfo(
const ConceptInfo &I, Object &Obj);
34 void serializeInfo(
const TypeInfo &I, Object &Obj);
36 void serializeInfo(
const FunctionInfo &F, json::Object &Obj);
38 void serializeInfo(
const EnumInfo &I, json::Object &Obj);
39 void serializeInfo(
const TypedefInfo &I, json::Object &Obj);
41 void serializeInfo(
const FriendInfo &I, Object &Obj);
42 void serializeInfo(
const RecordInfo &I, json::Object &Obj);
43 void serializeInfo(
const VarInfo &I, json::Object &Obj);
44 void serializeInfo(
const NamespaceInfo &I, json::Object &Obj);
45 SmallString<16> determineFileName(
Info *I, SmallString<128> &Path);
46 Error serializeIndex(StringRef RootDir);
47 void generateContext(
const Info &I, Object &Obj);
48 void serializeReference(
const Reference &Ref, Object &ReferenceObj);
49 Error serializeAllFiles(
const ClangDocContext &CDCtx, StringRef RootDir);
50 void serializeMDReference(
const Reference &Ref, Object &ReferenceObj,
54 auto serializeInfoLambda() {
55 return [
this](
const auto &
Info, Object &Object) {
56 serializeInfo(
Info, Object);
59 auto serializeReferenceLambda() {
60 return [
this](
const auto &Ref, Object &Object) {
61 serializeReference(Ref, Object);
65 llvm::DenseMap<const Info *, SmallVector<Context, 4>> ContextsMap;
75 std::string DirName)
override;
111 llvm_unreachable(
"Unknown InfoType encountered.");
114json::Object JSONGenerator::serializeLocation(
const Location &Loc) {
115 Object LocationObj = Object();
116 LocationObj[
"LineNumber"] = Loc.StartLineNumber;
117 LocationObj[
"Filename"] = Loc.Filename;
122 sys::path::append(FileURL, sys::path::Style::posix, Loc.Filename);
124 std::string LinePrefix;
130 FileURL += LinePrefix + std::to_string(Loc.StartLineNumber);
131 LocationObj[
"FileURL"] = FileURL;
143 if (
auto *Obj = Comment.getAsObject()) {
144 if (
auto *Children = Obj->getArray(
"Children");
145 Children && Children->empty())
149 else if (
auto *Array = Comment.getAsArray(); Array && Array->empty()) {
153 auto DescriptionIt = Description.find(Key);
155 if (DescriptionIt == Description.end()) {
156 auto CommentsArray = json::Array();
157 CommentsArray.push_back(Comment);
158 Description[Key] = std::move(CommentsArray);
159 Description[
"Has" + Key.str()] =
true;
161 DescriptionIt->getSecond().getAsArray()->push_back(Comment);
169 if (!ParagraphComment)
170 return json::Value(
nullptr);
171 json::Value *Children = ParagraphComment->get(
"Children");
173 return json::Value(
nullptr);
174 auto ChildrenArray = *Children->getAsArray();
175 auto ChildrenIt = ChildrenArray.begin();
176 while (ChildrenIt != ChildrenArray.end()) {
177 auto *ChildObj = ChildrenIt->getAsObject();
178 assert(ChildObj &&
"Invalid JSON object in Comment");
179 auto TextComment = ChildObj->getString(
"TextComment");
180 if (!TextComment || TextComment->empty()) {
181 ChildrenIt = ChildrenArray.erase(ChildrenIt);
186 return ChildrenArray;
190 json::Value TextArray = json::Array();
191 auto &TextArrayRef = *TextArray.getAsArray();
192 for (
auto &Line : VerbatimLines)
193 TextArrayRef.push_back(*Line.getAsObject()
194 ->get(
"VerbatimBlockLineComment")
203 Object Obj = Object();
205 json::Value ChildVal = Object();
206 Object &Child = *ChildVal.getAsObject();
208 json::Value ChildArr = Array();
209 auto &CARef = *ChildArr.getAsArray();
223 if (I.
Name ==
"brief")
224 insertComment(Description, TextCommentsArray,
"BriefComments");
225 else if (I.
Name ==
"return")
226 insertComment(Description, TextCommentsArray,
"ReturnComments");
227 else if (I.
Name ==
"throws" || I.
Name ==
"throw") {
228 json::Value ThrowsVal = Object();
229 auto &ThrowsObj = *ThrowsVal.getAsObject();
230 ThrowsObj[
"Exception"] = I.
Args.front();
231 ThrowsObj[
"Children"] = TextCommentsArray;
238 json::Value ArgsArr = Array();
239 auto &ARef = *ArgsArr.getAsArray();
240 ARef.reserve(I.
Args.size());
241 for (
const auto &Arg : I.
Args)
242 ARef.emplace_back(Arg);
243 Child.insert({
"Command", I.
Name});
244 Child.insert({
"Args", ArgsArr});
245 Child.insert({
"Children", ChildArr});
252 Child.insert({
"ParamName", I.
ParamName});
253 Child.insert({
"Direction", I.
Direction});
254 Child.insert({
"Explicit", I.
Explicit});
256 Child.insert({
"Children", TextCommentsArray});
268 insertComment(Description, TextCommentsArray,
"CodeComments");
276 Child.insert({
"Text", I.
Text});
277 Child.insert({
"Children", ChildArr});
283 json::Value AttrKeysArray = json::Array();
284 json::Value AttrValuesArray = json::Array();
285 auto &KeyArr = *AttrKeysArray.getAsArray();
286 auto &ValArr = *AttrValuesArray.getAsArray();
290 KeyArr.emplace_back(K);
292 ValArr.emplace_back(V);
293 Child.insert({
"Name", I.
Name});
295 Child.insert({
"AttrKeys", AttrKeysArray});
296 Child.insert({
"AttrValues", AttrValuesArray});
297 Child.insert({
"Children", ChildArr});
303 Child.insert({
"Name", I.
Name});
304 Child.insert({
"Children", ChildArr});
311 Child.insert({
"Children", ChildArr});
312 Child[
"ParagraphComment"] =
true;
321 llvm_unreachable(
"Unknown comment kind encountered.");
325void JSONGenerator::generateContext(
const Info &I, Object &Obj) {
326 Obj[
"Contexts"] = json::Array();
327 Obj[
"HasContexts"] =
true;
329 auto It = ContextsMap.find(&I);
330 if (It == ContextsMap.end() || It->second.empty())
333 auto &ContextArrayRef = *Obj[
"Contexts"].getAsArray();
334 const auto &Contexts = It->second;
335 ContextArrayRef.reserve(Contexts.size());
337 std::string CurrentRelativePath;
338 bool PreviousRecord =
false;
339 for (
const auto &Current : Contexts) {
340 json::Value ContextVal = Object();
341 Object &Context = *ContextVal.getAsObject();
342 serializeReference(Current, Context);
345 if (Current.DocumentationFileName ==
"index") {
348 PreviousRecord =
false;
349 Context[
"RelativePath"] =
"./";
353 PreviousRecord =
true;
354 CurrentRelativePath +=
"../";
355 Context[
"RelativePath"] = CurrentRelativePath;
357 ContextArrayRef.push_back(ContextVal);
361 if (PreviousRecord && (Current.DocumentationFileName ==
"index")) {
364 PreviousRecord =
false;
365 }
else if (Current.DocumentationFileName !=
"index") {
368 PreviousRecord =
true;
369 CurrentRelativePath +=
"../";
372 PreviousRecord =
false;
373 CurrentRelativePath +=
"../";
376 if (Current.QualName ==
"GlobalNamespace" && Current.RelativePath !=
"./")
377 Context[
"DocumentationFileName"] =
378 SmallString<16>(
"GlobalNamespace/index");
380 Context[
"RelativePath"] = CurrentRelativePath;
381 ContextArrayRef.insert(ContextArrayRef.begin(), ContextVal);
384 ContextArrayRef.back().getAsObject()->insert({
"End",
true});
388 json::Object &Obj, StringRef Key =
"") {
389 if (Description.empty())
393 auto &Comments = Description.front()->Children;
394 Object DescriptionObj = Object();
399 if (
auto *ParagraphComment = Comment.getAsObject();
400 ParagraphComment->get(
"ParagraphComment")) {
402 if (TextCommentsArray.kind() == json::Value::Null ||
403 TextCommentsArray.getAsArray()->empty())
405 insertComment(DescriptionObj, TextCommentsArray,
"ParagraphComments");
408 Obj[
"Description"] = std::move(DescriptionObj);
413void JSONGenerator::serializeCommonAttributes(
const Info &I,
417 Obj[
"USR"] = toHex(toStringRef(I.USR));
422 insertNonEmpty(
"DocumentationFileName", I.DocumentationFileName, Obj);
425 if (!I.Namespace.empty()) {
426 Obj[
"Namespace"] = json::Array();
427 for (
const auto &NS : I.Namespace)
428 Obj[
"Namespace"].getAsArray()->push_back(NS.Name);
435 const auto *Symbol =
static_cast<const SymbolInfo *
>(&I);
437 Obj[
"Location"] = serializeLocation(Symbol->DefLoc.value());
440 auto It = ContextsMap.find(&I);
441 if (It != ContextsMap.end() && !It->second.empty())
442 generateContext(I, Obj);
445void JSONGenerator::serializeReference(
const Reference &Ref,
446 Object &ReferenceObj) {
448 ReferenceObj[
"Name"] = Ref.Name;
449 ReferenceObj[
"QualName"] = Ref.QualName;
450 ReferenceObj[
"USR"] = toHex(toStringRef(Ref.USR));
451 if (!Ref.DocumentationFileName.empty()) {
452 ReferenceObj[
"DocumentationFileName"] = Ref.DocumentationFileName;
456 if (Ref.Path !=
"GlobalNamespace" && !Ref.Path.empty())
457 ReferenceObj[
"PathStem"] = sys::path::stem(Ref.Path);
461void JSONGenerator::serializeMDReference(
const Reference &Ref,
462 Object &ReferenceObj,
463 StringRef BasePath) {
464 serializeReference(Ref, ReferenceObj);
465 SmallString<64>
Path = Ref.getRelativeFilePath(BasePath);
466 sys::path::native(Path, sys::path::Style::posix);
467 sys::path::append(Path, sys::path::Style::posix,
468 Ref.getFileBaseName() +
".md");
469 ReferenceObj[
"BasePath"] =
Path;
474void JSONGenerator::serializeCommonChildren(
476 std::optional<ReferenceFunc> MDReferenceLambda) {
479 Obj[
"HasEnums"] =
true;
484 Obj[
"HasTypedefs"] =
true;
489 ? MDReferenceLambda.value()
490 : serializeReferenceLambda();
492 Obj[
"HasRecords"] =
true;
496template <
typename Container,
typename SerializationFunc>
498 SerializationFunc SerializeInfo, StringRef EndKey,
499 function_ref<
void(Object &)> UpdateJson) {
500 json::Value RecordsArray = Array();
501 auto &RecordsArrayRef = *RecordsArray.getAsArray();
502 RecordsArrayRef.reserve(Records.size());
504 size_t Size = Records.size();
505 for (
const auto &Item : Records) {
506 json::Value ItemVal = Object();
507 auto &ItemObj = *ItemVal.getAsObject();
508 SerializeInfo(Item, ItemObj);
509 if (
Index == Size - 1)
510 ItemObj[EndKey] =
true;
511 RecordsArrayRef.push_back(ItemVal);
514 Obj[Key] = RecordsArray;
518void JSONGenerator::serializeInfo(
const ConstraintInfo &I, Object &Obj) {
519 serializeReference(I.ConceptRef, Obj);
520 Obj[
"Expression"] = I.ConstraintExpr;
523void JSONGenerator::serializeInfo(
const TemplateInfo &Template, Object &Obj) {
524 json::Value TemplateVal = Object();
525 auto &TemplateObj = *TemplateVal.getAsObject();
526 auto SerializeTemplateParam = [](
const TemplateParamInfo &Param,
528 JsonObj[
"Param"] = Param.Contents;
531 if (Template.Specialization) {
532 json::Value TemplateSpecializationVal =
Object();
533 auto &TemplateSpecializationObj = *TemplateSpecializationVal.getAsObject();
534 TemplateSpecializationObj[
"SpecializationOf"] =
535 toHex(toStringRef(Template.Specialization->SpecializationOf));
536 if (!Template.Specialization->Params.empty()) {
537 bool VerticalDisplay =
539 serializeArray(Template.Specialization->Params, TemplateSpecializationObj,
540 "Parameters", SerializeTemplateParam,
"SpecParamEnd",
541 [VerticalDisplay](Object &JsonObj) {
542 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
545 TemplateObj[
"Specialization"] = TemplateSpecializationVal;
548 if (!Template.Params.empty()) {
551 SerializeTemplateParam,
"End",
552 [VerticalDisplay](Object &JsonObj) {
553 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
557 if (!Template.Constraints.empty())
559 serializeInfoLambda());
561 Obj[
"Template"] = TemplateVal;
564void JSONGenerator::serializeInfo(
const ConceptInfo &I, Object &Obj) {
565 serializeCommonAttributes(I, Obj);
566 Obj[
"IsType"] = I.IsType;
567 Obj[
"ConstraintExpression"] = I.ConstraintExpression;
568 serializeInfo(I.Template, Obj);
571void JSONGenerator::serializeInfo(
const TypeInfo &I, Object &Obj) {
572 Obj[
"Name"] = I.Type.Name;
573 Obj[
"QualName"] = I.Type.QualName;
574 Obj[
"USR"] = toHex(toStringRef(I.Type.USR));
575 Obj[
"IsTemplate"] = I.IsTemplate;
576 Obj[
"IsBuiltIn"] = I.IsBuiltIn;
579void JSONGenerator::serializeInfo(
const FieldTypeInfo &I, Object &Obj) {
580 Obj[
"Name"] = I.Name;
582 json::Value ReferenceVal =
Object();
583 Object &ReferenceObj = *ReferenceVal.getAsObject();
584 serializeReference(I.Type, ReferenceObj);
585 Obj[
"Type"] = ReferenceVal;
588void JSONGenerator::serializeInfo(
const FunctionInfo &F, json::Object &Obj) {
589 serializeCommonAttributes(F, Obj);
590 Obj[
"IsStatic"] = F.IsStatic;
592 auto ReturnTypeObj =
Object();
593 serializeInfo(F.ReturnType, ReturnTypeObj);
594 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
596 if (!F.Params.empty()) {
598 serializeArray(F.Params, Obj,
"Params", serializeInfoLambda(),
"ParamEnd",
599 [VerticalDisplay](Object &JsonObj) {
600 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
605 serializeInfo(F.Template.value(), Obj);
608void JSONGenerator::serializeInfo(
const EnumValueInfo &I, Object &Obj) {
609 Obj[
"Name"] = I.Name;
610 if (!I.ValueExpr.empty())
611 Obj[
"ValueExpr"] = I.ValueExpr;
613 Obj[
"Value"] = I.Value;
618void JSONGenerator::serializeInfo(
const EnumInfo &I, json::Object &Obj) {
619 serializeCommonAttributes(I, Obj);
620 Obj[
"Scoped"] = I.Scoped;
623 json::Value BaseTypeVal =
Object();
624 auto &BaseTypeObj = *BaseTypeVal.getAsObject();
625 BaseTypeObj[
"Name"] = I.BaseType->Type.Name;
626 BaseTypeObj[
"QualName"] = I.BaseType->Type.QualName;
627 BaseTypeObj[
"USR"] = toHex(toStringRef(I.BaseType->Type.USR));
628 Obj[
"BaseType"] = BaseTypeVal;
631 if (!I.Members.empty()) {
632 for (
const auto &Member : I.Members) {
633 if (!Member.Description.empty()) {
634 Obj[
"HasComments"] =
true;
642void JSONGenerator::serializeInfo(
const TypedefInfo &I, json::Object &Obj) {
643 serializeCommonAttributes(I, Obj);
644 Obj[
"TypeDeclaration"] = I.TypeDeclaration;
645 Obj[
"IsUsing"] = I.IsUsing;
646 json::Value TypeVal =
Object();
647 auto &TypeObj = *TypeVal.getAsObject();
648 serializeInfo(I.Underlying, TypeObj);
649 Obj[
"Underlying"] = TypeVal;
651 serializeInfo(I.Template.value(), Obj);
654void JSONGenerator::serializeInfo(
const BaseRecordInfo &I, Object &Obj) {
655 serializeInfo(
static_cast<const RecordInfo &
>(I), Obj);
656 Obj[
"IsVirtual"] = I.IsVirtual;
657 Obj[
"Access"] = getAccessSpelling(I.Access);
658 Obj[
"IsParent"] = I.IsParent;
661void JSONGenerator::serializeInfo(
const FriendInfo &I, Object &Obj) {
662 auto FriendRef =
Object();
663 serializeReference(I.Ref, FriendRef);
664 Obj[
"Reference"] = std::move(FriendRef);
665 Obj[
"IsClass"] = I.IsClass;
667 serializeInfo(I.Template.value(), Obj);
668 if (!I.Params.empty())
671 auto ReturnTypeObj =
Object();
672 serializeInfo(I.ReturnType.value(), ReturnTypeObj);
673 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
675 serializeCommonAttributes(I, Obj);
678static void insertArray(Object &Obj, json::Value &Array, StringRef Key) {
680 Obj[
"Has" + Key.str()] =
true;
683void JSONGenerator::serializeInfo(
const RecordInfo &I, json::Object &Obj) {
684 serializeCommonAttributes(I, Obj);
686 Obj[
"IsTypedef"] = I.IsTypeDef;
687 Obj[
"MangledName"] = I.MangledName;
689 if (!I.Children.Functions.empty()) {
690 json::Value PubFunctionsArray = Array();
691 json::Array &PubFunctionsArrayRef = *PubFunctionsArray.getAsArray();
692 json::Value ProtFunctionsArray = Array();
693 json::Array &ProtFunctionsArrayRef = *ProtFunctionsArray.getAsArray();
695 for (
const auto &Function : I.Children.Functions) {
696 json::Value FunctionVal = Object();
697 auto &FunctionObj = *FunctionVal.getAsObject();
698 serializeInfo(Function, FunctionObj);
699 AccessSpecifier Access = Function->Access;
700 if (Access == AccessSpecifier::AS_public)
701 PubFunctionsArrayRef.push_back(FunctionVal);
702 else if (Access == AccessSpecifier::AS_protected)
703 ProtFunctionsArrayRef.push_back(FunctionVal);
706 if (!PubFunctionsArrayRef.empty())
707 insertArray(Obj, PubFunctionsArray,
"PublicMethods");
708 if (!ProtFunctionsArrayRef.empty())
709 insertArray(Obj, ProtFunctionsArray,
"ProtectedMethods");
712 if (!I.Members.empty()) {
713 Obj[
"HasMembers"] =
true;
714 json::Value PublicMembersArray =
Array();
715 json::Array &PubMembersArrayRef = *PublicMembersArray.getAsArray();
716 json::Value ProtectedMembersArray =
Array();
717 json::Array &ProtMembersArrayRef = *ProtectedMembersArray.getAsArray();
718 json::Value PrivateMembersArray =
Array();
719 json::Array &PrivateMembersArrayRef = *PrivateMembersArray.getAsArray();
721 for (
const MemberTypeInfo &Member : I.Members) {
722 json::Value MemberVal =
Object();
723 auto &MemberObj = *MemberVal.getAsObject();
724 MemberObj[
"Name"] = Member.Name;
725 MemberObj[
"Type"] = Member.Type.Name;
726 MemberObj[
"IsStatic"] = Member.IsStatic;
728 if (Member.Access == AccessSpecifier::AS_public)
729 PubMembersArrayRef.push_back(MemberVal);
730 else if (Member.Access == AccessSpecifier::AS_protected)
731 ProtMembersArrayRef.push_back(MemberVal);
732 else if (Member.Access == AccessSpecifier::AS_private)
733 PrivateMembersArrayRef.push_back(MemberVal);
736 if (!PubMembersArrayRef.empty())
737 insertArray(Obj, PublicMembersArray,
"PublicMembers");
738 if (!ProtMembersArrayRef.empty())
739 insertArray(Obj, ProtectedMembersArray,
"ProtectedMembers");
740 if (!PrivateMembersArrayRef.empty())
741 insertArray(Obj, PrivateMembersArray,
"PrivateMembers");
744 if (!I.Bases.empty())
747 if (!I.Parents.empty()) {
748 serializeArray(I.Parents, Obj,
"Parents", serializeReferenceLambda());
749 Obj[
"HasParents"] =
true;
752 if (!I.VirtualParents.empty()) {
754 serializeReferenceLambda());
755 Obj[
"HasVirtualParents"] =
true;
759 serializeInfo(I.Template.value(), Obj);
761 if (!I.Friends.empty()) {
763 Obj[
"HasFriends"] =
true;
766 serializeCommonChildren(I.Children, Obj);
769void JSONGenerator::serializeInfo(
const VarInfo &I, json::Object &Obj) {
770 serializeCommonAttributes(I, Obj);
771 Obj[
"IsStatic"] = I.IsStatic;
773 serializeInfo(I.Type, TypeObj);
774 Obj[
"Type"] = std::move(TypeObj);
777void JSONGenerator::serializeInfo(
const NamespaceInfo &I, json::Object &Obj) {
778 serializeCommonAttributes(I, Obj);
780 Obj[
"Name"] =
"Global Namespace";
782 if (!I.Children.Functions.empty()) {
784 serializeInfoLambda());
785 Obj[
"HasFunctions"] =
true;
788 if (!I.Children.Concepts.empty()) {
789 serializeArray(I.Children.Concepts, Obj,
"Concepts", serializeInfoLambda());
790 Obj[
"HasConcepts"] =
true;
793 if (!I.Children.Variables.empty()) {
795 serializeInfoLambda());
796 Obj[
"HasVariables"] =
true;
801 SmallString<64> BasePath = I.getRelativeFilePath(
"");
805 SerializeReferenceFunc = [
this, BasePath](
const Reference &Ref,
807 serializeMDReference(Ref, Object, BasePath);
809 serializeCommonChildren(I.Children, Obj, SerializeReferenceFunc);
811 SerializeReferenceFunc = serializeReferenceLambda();
812 serializeCommonChildren(I.Children, Obj);
815 if (!I.Children.Namespaces.empty()) {
817 SerializeReferenceFunc);
818 Obj[
"HasNamespaces"] =
true;
822SmallString<16> JSONGenerator::determineFileName(
Info *I,
823 SmallString<128> &Path) {
824 SmallString<16> FileName;
826 auto *RecordSymbolInfo =
static_cast<SymbolInfo *
>(I);
827 FileName = RecordSymbolInfo->MangledName;
832 sys::path::append(Path, FileName +
".json");
840 std::vector<Index> Processed;
841 Processed.reserve(CDCtxIndex.
Children.size());
845 sys::path::native(NewPath, sys::path::Style::posix);
846 sys::path::append(NewPath, sys::path::Style::posix,
849 Processed.push_back(NewIdx);
856Error JSONGenerator::serializeAllFiles(
const ClangDocContext &CDCtx,
858 json::Value ObjVal = Object();
859 Object &Obj = *ObjVal.getAsObject();
861 serializeArray(IndexCopy, Obj,
"Index", serializeReferenceLambda());
862 SmallString<128> Path;
863 sys::path::append(Path, RootDir,
"json",
"all_files.json");
864 std::error_code FileErr;
865 raw_fd_ostream RootOS(Path, FileErr, sys::fs::OF_Text);
867 return createFileError(
"cannot open file " + Path, FileErr);
868 RootOS << llvm::formatv(
"{0:2}", ObjVal);
869 return Error::success();
875Error JSONGenerator::serializeIndex(StringRef RootDir) {
876 if (CDCtx->Idx.Children.empty())
877 return Error::success();
879 json::Value ObjVal = Object();
880 Object &Obj = *ObjVal.getAsObject();
883 auto IndexCopy = CDCtx->Idx;
885 json::Value IndexArray = json::Array();
886 auto &IndexArrayRef = *IndexArray.getAsArray();
888 if (IndexCopy.Children.empty()) {
894 IndexArrayRef.reserve(CDCtx->Idx.Children.size());
897 auto Children = IndexCopy.getSortedChildren();
899 for (
const auto *Idx : Children) {
900 if (Idx->Children.empty())
903 json::Value IdxVal =
Object();
904 auto &IdxObj = *IdxVal.getAsObject();
906 TypeStr.at(0) = toUppercase(TypeStr.at(0));
907 IdxObj[
"Type"] = TypeStr;
908 serializeReference(*Idx, IdxObj);
909 IndexArrayRef.push_back(IdxVal);
911 Obj[
"Index"] = IndexArray;
913 SmallString<128> IndexFilePath(RootDir);
914 sys::path::append(IndexFilePath,
"/json/index.json");
915 std::error_code FileErr;
916 raw_fd_ostream RootOS(IndexFilePath, FileErr, sys::fs::OF_Text);
918 return createFileError(
"cannot open file " + IndexFilePath, FileErr);
919 RootOS << llvm::formatv(
"{0:2}", ObjVal);
920 return Error::success();
923void JSONGenerator::serializeContexts(
Info *I,
927 auto ParentUSR = I->ParentUSR;
928 auto &LocalContexts = ContextsMap[I];
933 auto Iter = Infos.find(llvm::toHex(ParentUSR));
934 if (Iter == Infos.end())
936 auto &ParentInfo = Iter->second;
939 Context GlobalRef(ParentInfo->USR,
"Global Namespace",
941 SmallString<16>(
"index"));
942 LocalContexts.push_back(GlobalRef);
946 Context ParentRef(*ParentInfo);
947 LocalContexts.push_back(ParentRef);
948 ParentUSR = ParentInfo->ParentUSR;
955 this->CDCtx = &CDCtx;
956 StringSet<> CreatedDirs;
957 StringMap<std::vector<doc::Info *>> FileToInfos;
958 for (
const auto &Group : Infos) {
961 SmallString<128> Path;
962 auto RootDirStr = RootDir.str() +
"/json";
963 StringRef JSONDir = StringRef(RootDirStr);
964 sys::path::native(JSONDir, Path);
966 if (!CreatedDirs.contains(Path)) {
967 if (std::error_code Err = sys::fs::create_directories(Path);
968 Err != std::error_code())
969 return createFileError(Twine(Path), Err);
970 CreatedDirs.insert(Path);
973 SmallString<16> FileName = determineFileName(
Info, Path);
974 if (FileToInfos.contains(Path))
976 FileToInfos[Path].push_back(
Info);
982 if (
auto Err = serializeAllFiles(CDCtx, RootDir))
986 for (
const auto &Group : FileToInfos) {
987 std::error_code FileErr;
988 raw_fd_ostream InfoOS(Group.getKey(), FileErr, sys::fs::OF_Text);
990 return createFileError(
"cannot open file " + Group.getKey(), FileErr);
992 for (
const auto &
Info : Group.getValue()) {
994 serializeContexts(
Info, Infos);
1000 return serializeIndex(RootDir);
1005 json::Object Obj = Object();
1012 serializeInfo(*
static_cast<RecordInfo *
>(I), Obj);
1022 return createStringError(inconvertibleErrorCode(),
"unexpected info type");
1024 OS << llvm::formatv(
"{0:2}", llvm::json::Value(std::move(Obj)));
1025 return Error::success();
1029 return Error::success();
1033 "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< OwnedPtr< 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.
volatile int JSONGeneratorAnchorSource
T * getPtr(const OwnedPtr< T > &O)
llvm::StringRef getTagType(TagTypeKind AS)
static void serializeDescription(const OwningVec< CommentInfo > &Description, json::Object &Obj, StringRef Key="")
llvm::simple_ilist< InfoNode< T > > OwningVec
static GeneratorRegistry::Add< JSONGenerator > JSON(JSONGenerator::Format, "Generator for JSON output.")
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)
llvm::StringRef commentKindToString(CommentKind Kind)
static void insertArray(Object &Obj, json::Value &Array, StringRef Key)
static std::vector< Index > preprocessCDCtxIndex(Index CDCtxIndex)
===– 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.