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);
31 void serializeInfo(
const TemplateInfo &Template, Object &Obj);
32 void serializeInfo(
const ConceptInfo &I, Object &Obj);
33 void serializeInfo(
const TypeInfo &I, Object &Obj);
35 void serializeInfo(
const FunctionInfo &F, json::Object &Obj);
37 void serializeInfo(
const EnumInfo &I, json::Object &Obj);
38 void serializeInfo(
const TypedefInfo &I, json::Object &Obj);
40 void serializeInfo(
const FriendInfo &I, Object &Obj);
41 void serializeInfo(
const RecordInfo &I, json::Object &Obj);
42 void serializeInfo(
const VarInfo &I, json::Object &Obj);
43 void serializeInfo(
const NamespaceInfo &I, json::Object &Obj);
44 SmallString<16> determineFileName(
Info *I, SmallString<128> &Path);
45 Error serializeIndex(StringRef RootDir);
46 void generateContext(
const Info &I, Object &Obj);
47 void serializeReference(
const Reference &Ref, Object &ReferenceObj);
49 void serializeMDReference(
const Reference &Ref, Object &ReferenceObj,
53 auto serializeInfoLambda() {
54 return [
this](
const auto &
Info, Object &Object) {
55 serializeInfo(
Info, Object);
58 auto serializeReferenceLambda() {
59 return [
this](
const auto &Ref, Object &Object) {
60 serializeReference(Ref, Object);
72 std::string DirName)
override;
108 llvm_unreachable(
"Unknown InfoType encountered.");
111json::Object JSONGenerator::serializeLocation(
const Location &Loc) {
112 Object LocationObj = Object();
113 LocationObj[
"LineNumber"] = Loc.StartLineNumber;
114 LocationObj[
"Filename"] = Loc.Filename;
119 sys::path::append(FileURL, sys::path::Style::posix, Loc.Filename);
121 std::string LinePrefix;
127 FileURL += LinePrefix + std::to_string(Loc.StartLineNumber);
128 LocationObj[
"FileURL"] = FileURL;
140 if (
auto *Obj = Comment.getAsObject()) {
141 if (
auto *Children = Obj->getArray(
"Children");
142 Children && Children->empty())
146 else if (
auto *Array = Comment.getAsArray(); Array && Array->empty()) {
150 auto DescriptionIt = Description.find(Key);
152 if (DescriptionIt == Description.end()) {
153 auto CommentsArray = json::Array();
154 CommentsArray.push_back(Comment);
155 Description[Key] = std::move(CommentsArray);
156 Description[
"Has" + Key.str()] =
true;
158 DescriptionIt->getSecond().getAsArray()->push_back(Comment);
166 if (!ParagraphComment)
167 return json::Value(
nullptr);
168 json::Value *Children = ParagraphComment->get(
"Children");
170 return json::Value(
nullptr);
171 auto ChildrenArray = *Children->getAsArray();
172 auto ChildrenIt = ChildrenArray.begin();
173 while (ChildrenIt != ChildrenArray.end()) {
174 auto *ChildObj = ChildrenIt->getAsObject();
175 assert(ChildObj &&
"Invalid JSON object in Comment");
176 auto TextComment = ChildObj->getString(
"TextComment");
177 if (!TextComment || TextComment->empty()) {
178 ChildrenIt = ChildrenArray.erase(ChildrenIt);
183 return ChildrenArray;
187 json::Value TextArray = json::Array();
188 auto &TextArrayRef = *TextArray.getAsArray();
189 for (
auto &Line : VerbatimLines)
190 TextArrayRef.push_back(*Line.getAsObject()
191 ->get(
"VerbatimBlockLineComment")
200 Object Obj = Object();
202 json::Value ChildVal = Object();
203 Object &Child = *ChildVal.getAsObject();
205 json::Value ChildArr = Array();
206 auto &CARef = *ChildArr.getAsArray();
220 if (I.
Name ==
"brief")
221 insertComment(Description, TextCommentsArray,
"BriefComments");
222 else if (I.
Name ==
"return")
223 insertComment(Description, TextCommentsArray,
"ReturnComments");
224 else if (I.
Name ==
"throws" || I.
Name ==
"throw") {
225 json::Value ThrowsVal = Object();
226 auto &ThrowsObj = *ThrowsVal.getAsObject();
227 ThrowsObj[
"Exception"] = I.
Args.front();
228 ThrowsObj[
"Children"] = TextCommentsArray;
235 json::Value ArgsArr = Array();
236 auto &ARef = *ArgsArr.getAsArray();
237 ARef.reserve(I.
Args.size());
238 for (
const auto &Arg : I.
Args)
239 ARef.emplace_back(Arg);
240 Child.insert({
"Command", I.
Name});
241 Child.insert({
"Args", ArgsArr});
242 Child.insert({
"Children", ChildArr});
249 Child.insert({
"ParamName", I.
ParamName});
250 Child.insert({
"Direction", I.
Direction});
251 Child.insert({
"Explicit", I.
Explicit});
253 Child.insert({
"Children", TextCommentsArray});
265 insertComment(Description, TextCommentsArray,
"CodeComments");
273 Child.insert({
"Text", I.
Text});
274 Child.insert({
"Children", ChildArr});
280 json::Value AttrKeysArray = json::Array();
281 json::Value AttrValuesArray = json::Array();
282 auto &KeyArr = *AttrKeysArray.getAsArray();
283 auto &ValArr = *AttrValuesArray.getAsArray();
287 KeyArr.emplace_back(K);
289 ValArr.emplace_back(V);
290 Child.insert({
"Name", I.
Name});
292 Child.insert({
"AttrKeys", AttrKeysArray});
293 Child.insert({
"AttrValues", AttrValuesArray});
294 Child.insert({
"Children", ChildArr});
300 Child.insert({
"Name", I.
Name});
301 Child.insert({
"Children", ChildArr});
308 Child.insert({
"Children", ChildArr});
309 Child[
"ParagraphComment"] =
true;
318 llvm_unreachable(
"Unknown comment kind encountered.");
322void JSONGenerator::generateContext(
const Info &I, Object &Obj) {
323 json::Value ContextArray = json::Array();
324 auto &ContextArrayRef = *ContextArray.getAsArray();
325 ContextArrayRef.reserve(I.Contexts.size());
327 std::string CurrentRelativePath;
328 bool PreviousRecord =
false;
329 for (
const auto &Current : I.Contexts) {
330 json::Value ContextVal = Object();
331 Object &Context = *ContextVal.getAsObject();
332 serializeReference(Current, Context);
335 if (Current.DocumentationFileName ==
"index") {
338 PreviousRecord =
false;
339 Context[
"RelativePath"] =
"./";
343 PreviousRecord =
true;
344 CurrentRelativePath +=
"../";
345 Context[
"RelativePath"] = CurrentRelativePath;
347 ContextArrayRef.push_back(ContextVal);
351 if (PreviousRecord && (Current.DocumentationFileName ==
"index")) {
354 PreviousRecord =
false;
355 }
else if (Current.DocumentationFileName !=
"index") {
358 PreviousRecord =
true;
359 CurrentRelativePath +=
"../";
362 PreviousRecord =
false;
363 CurrentRelativePath +=
"../";
366 if (Current.QualName ==
"GlobalNamespace" && Current.RelativePath !=
"./")
367 Context[
"DocumentationFileName"] =
368 SmallString<16>(
"GlobalNamespace/index");
370 Context[
"RelativePath"] = CurrentRelativePath;
371 ContextArrayRef.insert(ContextArrayRef.begin(), ContextVal);
374 ContextArrayRef.back().getAsObject()->insert({
"End",
true});
375 Obj[
"Contexts"] = ContextArray;
376 Obj[
"HasContexts"] =
true;
380 json::Object &Obj, StringRef Key =
"") {
381 if (Description.empty())
385 auto &Comments = Description.front().Children;
386 Object DescriptionObj = Object();
391 if (
auto *ParagraphComment = Comment.getAsObject();
392 ParagraphComment->get(
"ParagraphComment")) {
394 if (TextCommentsArray.kind() == json::Value::Null ||
395 TextCommentsArray.getAsArray()->empty())
397 insertComment(DescriptionObj, TextCommentsArray,
"ParagraphComments");
400 Obj[
"Description"] = std::move(DescriptionObj);
405void JSONGenerator::serializeCommonAttributes(
const Info &I,
409 Obj[
"USR"] = toHex(toStringRef(I.USR));
414 insertNonEmpty(
"DocumentationFileName", I.DocumentationFileName, Obj);
417 if (!I.Namespace.empty()) {
418 Obj[
"Namespace"] = json::Array();
419 for (
const auto &NS : I.Namespace)
420 Obj[
"Namespace"].getAsArray()->push_back(NS.Name);
427 const auto *Symbol =
static_cast<const SymbolInfo *
>(&I);
429 Obj[
"Location"] = serializeLocation(Symbol->DefLoc.value());
432 if (!I.Contexts.empty())
433 generateContext(I, Obj);
436void JSONGenerator::serializeReference(
const Reference &Ref,
437 Object &ReferenceObj) {
439 ReferenceObj[
"Name"] = Ref.Name;
440 ReferenceObj[
"QualName"] = Ref.QualName;
441 ReferenceObj[
"USR"] = toHex(toStringRef(Ref.USR));
442 if (!Ref.DocumentationFileName.empty()) {
443 ReferenceObj[
"DocumentationFileName"] = Ref.DocumentationFileName;
447 if (Ref.Path !=
"GlobalNamespace" && !Ref.Path.empty())
448 ReferenceObj[
"PathStem"] = sys::path::stem(Ref.Path);
452void JSONGenerator::serializeMDReference(
const Reference &Ref,
453 Object &ReferenceObj,
454 StringRef BasePath) {
455 serializeReference(Ref, ReferenceObj);
456 SmallString<64>
Path = Ref.getRelativeFilePath(BasePath);
457 sys::path::native(Path, sys::path::Style::posix);
458 sys::path::append(Path, sys::path::Style::posix,
459 Ref.getFileBaseName() +
".md");
460 ReferenceObj[
"BasePath"] =
Path;
467void JSONGenerator::serializeCommonChildren(
469 std::optional<ReferenceFunc> MDReferenceLambda) {
472 Obj[
"HasEnums"] =
true;
477 Obj[
"HasTypedefs"] =
true;
482 ? MDReferenceLambda.value()
483 : serializeReferenceLambda();
485 Obj[
"HasRecords"] =
true;
489template <
typename Container,
typename SerializationFunc>
491 SerializationFunc SerializeInfo, StringRef EndKey,
492 function_ref<
void(Object &)> UpdateJson) {
493 json::Value RecordsArray = Array();
494 auto &RecordsArrayRef = *RecordsArray.getAsArray();
495 RecordsArrayRef.reserve(Records.size());
497 json::Value ItemVal = Object();
498 auto &ItemObj = *ItemVal.getAsObject();
499 SerializeInfo(Records[
Index], ItemObj);
500 if (
Index == Records.size() - 1)
501 ItemObj[EndKey] =
true;
502 RecordsArrayRef.push_back(ItemVal);
504 Obj[Key] = RecordsArray;
508void JSONGenerator::serializeInfo(
const ConstraintInfo &I, Object &Obj) {
509 serializeReference(I.ConceptRef, Obj);
510 Obj[
"Expression"] = I.ConstraintExpr;
513void JSONGenerator::serializeInfo(
const TemplateInfo &Template, Object &Obj) {
514 json::Value TemplateVal = Object();
515 auto &TemplateObj = *TemplateVal.getAsObject();
516 auto SerializeTemplateParam = [](
const TemplateParamInfo &Param,
518 JsonObj[
"Param"] = Param.Contents;
521 if (Template.Specialization) {
522 json::Value TemplateSpecializationVal =
Object();
523 auto &TemplateSpecializationObj = *TemplateSpecializationVal.getAsObject();
524 TemplateSpecializationObj[
"SpecializationOf"] =
525 toHex(toStringRef(Template.Specialization->SpecializationOf));
526 if (!Template.Specialization->Params.empty()) {
527 bool VerticalDisplay =
529 serializeArray(Template.Specialization->Params, TemplateSpecializationObj,
530 "Parameters", SerializeTemplateParam,
"SpecParamEnd",
531 [VerticalDisplay](Object &JsonObj) {
532 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
535 TemplateObj[
"Specialization"] = TemplateSpecializationVal;
538 if (!Template.Params.empty()) {
541 SerializeTemplateParam,
"End",
542 [VerticalDisplay](Object &JsonObj) {
543 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
547 if (!Template.Constraints.empty())
549 serializeInfoLambda());
551 Obj[
"Template"] = TemplateVal;
554void JSONGenerator::serializeInfo(
const ConceptInfo &I, Object &Obj) {
555 serializeCommonAttributes(I, Obj);
556 Obj[
"IsType"] = I.IsType;
557 Obj[
"ConstraintExpression"] = I.ConstraintExpression;
558 serializeInfo(I.Template, Obj);
561void JSONGenerator::serializeInfo(
const TypeInfo &I, Object &Obj) {
562 Obj[
"Name"] = I.Type.Name;
563 Obj[
"QualName"] = I.Type.QualName;
564 Obj[
"USR"] = toHex(toStringRef(I.Type.USR));
565 Obj[
"IsTemplate"] = I.IsTemplate;
566 Obj[
"IsBuiltIn"] = I.IsBuiltIn;
569void JSONGenerator::serializeInfo(
const FieldTypeInfo &I, Object &Obj) {
570 Obj[
"Name"] = I.Name;
572 json::Value ReferenceVal =
Object();
573 Object &ReferenceObj = *ReferenceVal.getAsObject();
574 serializeReference(I.Type, ReferenceObj);
575 Obj[
"Type"] = ReferenceVal;
578void JSONGenerator::serializeInfo(
const FunctionInfo &F, json::Object &Obj) {
579 serializeCommonAttributes(F, Obj);
580 Obj[
"IsStatic"] = F.IsStatic;
582 auto ReturnTypeObj =
Object();
583 serializeInfo(F.ReturnType, ReturnTypeObj);
584 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
586 if (!F.Params.empty()) {
588 serializeArray(F.Params, Obj,
"Params", serializeInfoLambda(),
"ParamEnd",
589 [VerticalDisplay](Object &JsonObj) {
590 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
595 serializeInfo(F.Template.value(), Obj);
598void JSONGenerator::serializeInfo(
const EnumValueInfo &I, Object &Obj) {
599 Obj[
"Name"] = I.Name;
600 if (!I.ValueExpr.empty())
601 Obj[
"ValueExpr"] = I.ValueExpr;
603 Obj[
"Value"] = I.Value;
608void JSONGenerator::serializeInfo(
const EnumInfo &I, json::Object &Obj) {
609 serializeCommonAttributes(I, Obj);
610 Obj[
"Scoped"] = I.Scoped;
613 json::Value BaseTypeVal =
Object();
614 auto &BaseTypeObj = *BaseTypeVal.getAsObject();
615 BaseTypeObj[
"Name"] = I.BaseType->Type.Name;
616 BaseTypeObj[
"QualName"] = I.BaseType->Type.QualName;
617 BaseTypeObj[
"USR"] = toHex(toStringRef(I.BaseType->Type.USR));
618 Obj[
"BaseType"] = BaseTypeVal;
621 if (!I.Members.empty()) {
622 for (
const auto &Member : I.Members) {
623 if (!Member.Description.empty()) {
624 Obj[
"HasComments"] =
true;
632void JSONGenerator::serializeInfo(
const TypedefInfo &I, json::Object &Obj) {
633 serializeCommonAttributes(I, Obj);
634 Obj[
"TypeDeclaration"] = I.TypeDeclaration;
635 Obj[
"IsUsing"] = I.IsUsing;
636 json::Value TypeVal =
Object();
637 auto &TypeObj = *TypeVal.getAsObject();
638 serializeInfo(I.Underlying, TypeObj);
639 Obj[
"Underlying"] = TypeVal;
641 serializeInfo(I.Template.value(), Obj);
644void JSONGenerator::serializeInfo(
const BaseRecordInfo &I, Object &Obj) {
645 serializeInfo(
static_cast<const RecordInfo &
>(I), Obj);
646 Obj[
"IsVirtual"] = I.IsVirtual;
647 Obj[
"Access"] = getAccessSpelling(I.Access);
648 Obj[
"IsParent"] = I.IsParent;
651void JSONGenerator::serializeInfo(
const FriendInfo &I, Object &Obj) {
652 auto FriendRef =
Object();
653 serializeReference(I.Ref, FriendRef);
654 Obj[
"Reference"] = std::move(FriendRef);
655 Obj[
"IsClass"] = I.IsClass;
657 serializeInfo(I.Template.value(), Obj);
659 serializeArray(I.Params.value(), Obj,
"Params", serializeInfoLambda());
661 auto ReturnTypeObj =
Object();
662 serializeInfo(I.ReturnType.value(), ReturnTypeObj);
663 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
665 serializeCommonAttributes(I, Obj);
668static void insertArray(Object &Obj, json::Value &Array, StringRef Key) {
670 Obj[
"Has" + Key.str()] =
true;
673void JSONGenerator::serializeInfo(
const RecordInfo &I, json::Object &Obj) {
674 serializeCommonAttributes(I, Obj);
676 Obj[
"IsTypedef"] = I.IsTypeDef;
677 Obj[
"MangledName"] = I.MangledName;
679 if (!I.Children.Functions.empty()) {
680 json::Value PubFunctionsArray = Array();
681 json::Array &PubFunctionsArrayRef = *PubFunctionsArray.getAsArray();
682 json::Value ProtFunctionsArray = Array();
683 json::Array &ProtFunctionsArrayRef = *ProtFunctionsArray.getAsArray();
685 for (
const auto &Function : I.Children.Functions) {
686 json::Value FunctionVal = Object();
687 auto &FunctionObj = *FunctionVal.getAsObject();
688 serializeInfo(Function, FunctionObj);
689 AccessSpecifier Access = Function.Access;
690 if (Access == AccessSpecifier::AS_public)
691 PubFunctionsArrayRef.push_back(FunctionVal);
692 else if (Access == AccessSpecifier::AS_protected)
693 ProtFunctionsArrayRef.push_back(FunctionVal);
696 if (!PubFunctionsArrayRef.empty())
697 insertArray(Obj, PubFunctionsArray,
"PublicMethods");
698 if (!ProtFunctionsArrayRef.empty())
699 insertArray(Obj, ProtFunctionsArray,
"ProtectedMethods");
702 if (!I.Members.empty()) {
703 Obj[
"HasMembers"] =
true;
704 json::Value PublicMembersArray =
Array();
705 json::Array &PubMembersArrayRef = *PublicMembersArray.getAsArray();
706 json::Value ProtectedMembersArray =
Array();
707 json::Array &ProtMembersArrayRef = *ProtectedMembersArray.getAsArray();
708 json::Value PrivateMembersArray =
Array();
709 json::Array &PrivateMembersArrayRef = *PrivateMembersArray.getAsArray();
711 for (
const MemberTypeInfo &Member : I.Members) {
712 json::Value MemberVal =
Object();
713 auto &MemberObj = *MemberVal.getAsObject();
714 MemberObj[
"Name"] = Member.Name;
715 MemberObj[
"Type"] = Member.Type.Name;
716 MemberObj[
"IsStatic"] = Member.IsStatic;
718 if (Member.Access == AccessSpecifier::AS_public)
719 PubMembersArrayRef.push_back(MemberVal);
720 else if (Member.Access == AccessSpecifier::AS_protected)
721 ProtMembersArrayRef.push_back(MemberVal);
722 else if (Member.Access == AccessSpecifier::AS_private)
723 PrivateMembersArrayRef.push_back(MemberVal);
726 if (!PubMembersArrayRef.empty())
727 insertArray(Obj, PublicMembersArray,
"PublicMembers");
728 if (!ProtMembersArrayRef.empty())
729 insertArray(Obj, ProtectedMembersArray,
"ProtectedMembers");
730 if (!PrivateMembersArrayRef.empty())
731 insertArray(Obj, PrivateMembersArray,
"PrivateMembers");
734 if (!I.Bases.empty())
737 if (!I.Parents.empty()) {
738 serializeArray(I.Parents, Obj,
"Parents", serializeReferenceLambda());
739 Obj[
"HasParents"] =
true;
742 if (!I.VirtualParents.empty()) {
744 serializeReferenceLambda());
745 Obj[
"HasVirtualParents"] =
true;
749 serializeInfo(I.Template.value(), Obj);
751 if (!I.Friends.empty()) {
753 Obj[
"HasFriends"] =
true;
756 serializeCommonChildren(I.Children, Obj);
759void JSONGenerator::serializeInfo(
const VarInfo &I, json::Object &Obj) {
760 serializeCommonAttributes(I, Obj);
761 Obj[
"IsStatic"] = I.IsStatic;
763 serializeInfo(I.Type, TypeObj);
764 Obj[
"Type"] = std::move(TypeObj);
767void JSONGenerator::serializeInfo(
const NamespaceInfo &I, json::Object &Obj) {
768 serializeCommonAttributes(I, Obj);
770 Obj[
"Name"] =
"Global Namespace";
772 if (!I.Children.Namespaces.empty()) {
774 serializeReferenceLambda());
775 Obj[
"HasNamespaces"] =
true;
778 if (!I.Children.Functions.empty()) {
780 serializeInfoLambda());
781 Obj[
"HasFunctions"] =
true;
784 if (!I.Children.Concepts.empty()) {
785 serializeArray(I.Children.Concepts, Obj,
"Concepts", serializeInfoLambda());
786 Obj[
"HasConcepts"] =
true;
789 if (!I.Children.Variables.empty()) {
791 serializeInfoLambda());
792 Obj[
"HasVariables"] =
true;
797 SmallString<64> BasePath = I.getRelativeFilePath(
"");
801 SerializeReferenceFunc = [
this, BasePath](
const Reference &Ref,
803 serializeMDReference(Ref, Object, BasePath);
805 serializeCommonChildren(I.Children, Obj, SerializeReferenceFunc);
807 SerializeReferenceFunc = serializeReferenceLambda();
808 serializeCommonChildren(I.Children, Obj);
811 if (!I.Children.Namespaces.empty()) {
813 SerializeReferenceFunc);
814 Obj[
"HasNamespaces"] =
true;
818SmallString<16> JSONGenerator::determineFileName(
Info *I,
819 SmallString<128> &Path) {
820 SmallString<16> FileName;
822 auto *RecordSymbolInfo =
static_cast<SymbolInfo *
>(I);
823 FileName = RecordSymbolInfo->MangledName;
828 sys::path::append(Path, FileName +
".json");
837 Processed.reserve(CDCtxIndex.
Children.size());
841 sys::path::native(NewPath, sys::path::Style::posix);
842 sys::path::append(NewPath, sys::path::Style::posix,
844 NewIdx.
Path = NewPath;
845 Processed.push_back(NewIdx);
852Error JSONGenerator::serializeAllFiles(
const ClangDocContext &CDCtx,
854 json::Value ObjVal = Object();
855 Object &Obj = *ObjVal.getAsObject();
857 serializeArray(IndexCopy, Obj,
"Index", serializeReferenceLambda());
858 SmallString<128> Path;
859 sys::path::append(Path, RootDir,
"json",
"all_files.json");
860 std::error_code FileErr;
861 raw_fd_ostream RootOS(Path, FileErr, sys::fs::OF_Text);
863 return createFileError(
"cannot open file " + Path, FileErr);
864 RootOS << llvm::formatv(
"{0:2}", ObjVal);
865 return Error::success();
871Error JSONGenerator::serializeIndex(StringRef RootDir) {
873 return Error::success();
875 json::Value ObjVal = Object();
876 Object &Obj = *ObjVal.getAsObject();
881 json::Value IndexArray = json::Array();
882 auto &IndexArrayRef = *IndexArray.getAsArray();
884 if (IndexCopy.Children.empty()) {
890 IndexArrayRef.reserve(
CDCtx->Idx.Children.size());
893 auto Children = IndexCopy.getSortedChildren();
895 for (
const auto *Idx : Children) {
896 if (Idx->Children.empty())
899 json::Value IdxVal =
Object();
900 auto &IdxObj = *IdxVal.getAsObject();
902 TypeStr.at(0) = toUppercase(TypeStr.at(0));
903 IdxObj[
"Type"] = TypeStr;
904 serializeReference(*Idx, IdxObj);
905 IndexArrayRef.push_back(IdxVal);
907 Obj[
"Index"] = IndexArray;
909 SmallString<128> IndexFilePath(RootDir);
910 sys::path::append(IndexFilePath,
"/json/index.json");
911 std::error_code FileErr;
912 raw_fd_ostream RootOS(IndexFilePath, FileErr, sys::fs::OF_Text);
914 return createFileError(
"cannot open file " + IndexFilePath, FileErr);
915 RootOS << llvm::formatv(
"{0:2}", ObjVal);
916 return Error::success();
925 auto &ParentInfo = Infos.at(llvm::toHex(ParentUSR));
928 Context GlobalRef(ParentInfo->USR,
"Global Namespace",
930 SmallString<16>(
"index"));
935 Context ParentRef(*ParentInfo);
937 ParentUSR = ParentInfo->ParentUSR;
944 this->CDCtx = &
CDCtx;
945 StringSet<> CreatedDirs;
946 StringMap<std::vector<doc::Info *>> FileToInfos;
947 for (
const auto &Group : Infos) {
950 SmallString<128> Path;
951 auto RootDirStr = RootDir.str() +
"/json";
952 StringRef JSONDir = StringRef(RootDirStr);
953 sys::path::native(JSONDir, Path);
955 if (!CreatedDirs.contains(Path)) {
956 if (std::error_code Err = sys::fs::create_directories(Path);
957 Err != std::error_code())
958 return createFileError(Twine(Path), Err);
959 CreatedDirs.insert(Path);
962 SmallString<16> FileName = determineFileName(
Info, Path);
963 if (FileToInfos.contains(Path))
965 FileToInfos[Path].push_back(
Info);
971 if (
auto Err = serializeAllFiles(
CDCtx, RootDir))
975 for (
const auto &Group : FileToInfos) {
976 std::error_code FileErr;
977 raw_fd_ostream InfoOS(Group.getKey(), FileErr, sys::fs::OF_Text);
979 return createFileError(
"cannot open file " + Group.getKey(), FileErr);
981 for (
const auto &
Info : Group.getValue()) {
989 return serializeIndex(RootDir);
994 json::Object Obj = Object();
1001 serializeInfo(*
static_cast<RecordInfo *
>(I), Obj);
1011 return createStringError(inconvertibleErrorCode(),
"unexpected info type");
1013 OS << llvm::formatv(
"{0:2}", llvm::json::Value(std::move(Obj)));
1014 return Error::success();
1018 return Error::success();
1022 "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
const ClangDocContext * CDCtx
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.
std::unique_ptr< T > OwnedPtr
std::function< void(const Reference &, Object &)> ReferenceFunc
volatile int JSONGeneratorAnchorSource
T * getPtr(const OwnedPtr< T > &O)
llvm::StringRef getTagType(TagTypeKind AS)
static OwningVec< Index > preprocessCDCtxIndex(Index CDCtxIndex)
static GeneratorRegistry::Add< JSONGenerator > JSON(JSONGenerator::Format, "Generator for JSON output.")
static void serializeArray(const Container &Records, Object &Obj, const StringRef Key, SerializationFunc SerializeInfo, const StringRef EndKey="End", function_ref< void(Object &)> UpdateJson=[](Object &Obj) {})
std::vector< T > OwningVec
constexpr SymbolID GlobalNamespaceID
static json::Value extractVerbatimComments(json::Array VerbatimLines)
static void insertNonEmpty(StringRef Key, StringRef Value, Object &Obj)
static void serializeDescription(llvm::ArrayRef< CommentInfo > Description, json::Object &Obj, StringRef Key="")
llvm::StringRef commentKindToString(CommentKind Kind)
static void insertArray(Object &Obj, json::Value &Array, StringRef Key)
static void serializeContexts(Info *I, StringMap< OwnedPtr< Info > > &Infos)
===– 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
OwningVec< const Index * > getSortedChildren() const
llvm::StringMap< Index > Children
SmallString< 16 > DocumentationFileName
SmallVector< Context, 4 > Contexts
llvm::SmallString< 64 > getRelativeFilePath(const StringRef &CurrentPath) const
Returns the file path for this Info relative to CurrentPath.
llvm::SmallString< 128 > Path
llvm::SmallString< 64 > getRelativeFilePath(const StringRef &CurrentPath) const
Returns the path for this Reference relative to CurrentPath.
llvm::SmallString< 16 > getFileBaseName() const
Returns the basename that should be used for this Reference.