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;
465void JSONGenerator::serializeCommonChildren(
467 std::optional<ReferenceFunc> MDReferenceLambda) {
470 Obj[
"HasEnums"] =
true;
475 Obj[
"HasTypedefs"] =
true;
480 ? MDReferenceLambda.value()
481 : serializeReferenceLambda();
483 Obj[
"HasRecords"] =
true;
487template <
typename Container,
typename SerializationFunc>
489 SerializationFunc SerializeInfo, StringRef EndKey,
490 function_ref<
void(Object &)> UpdateJson) {
491 json::Value RecordsArray = Array();
492 auto &RecordsArrayRef = *RecordsArray.getAsArray();
493 RecordsArrayRef.reserve(Records.size());
495 size_t Size = Records.size();
496 for (
const auto &Item : Records) {
497 json::Value ItemVal = Object();
498 auto &ItemObj = *ItemVal.getAsObject();
499 SerializeInfo(Item, ItemObj);
500 if (
Index == Size - 1)
501 ItemObj[EndKey] =
true;
502 RecordsArrayRef.push_back(ItemVal);
505 Obj[Key] = RecordsArray;
509void JSONGenerator::serializeInfo(
const ConstraintInfo &I, Object &Obj) {
510 serializeReference(I.ConceptRef, Obj);
511 Obj[
"Expression"] = I.ConstraintExpr;
514void JSONGenerator::serializeInfo(
const TemplateInfo &Template, Object &Obj) {
515 json::Value TemplateVal = Object();
516 auto &TemplateObj = *TemplateVal.getAsObject();
517 auto SerializeTemplateParam = [](
const TemplateParamInfo &Param,
519 JsonObj[
"Param"] = Param.Contents;
522 if (Template.Specialization) {
523 json::Value TemplateSpecializationVal =
Object();
524 auto &TemplateSpecializationObj = *TemplateSpecializationVal.getAsObject();
525 TemplateSpecializationObj[
"SpecializationOf"] =
526 toHex(toStringRef(Template.Specialization->SpecializationOf));
527 if (!Template.Specialization->Params.empty()) {
528 bool VerticalDisplay =
530 serializeArray(Template.Specialization->Params, TemplateSpecializationObj,
531 "Parameters", SerializeTemplateParam,
"SpecParamEnd",
532 [VerticalDisplay](Object &JsonObj) {
533 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
536 TemplateObj[
"Specialization"] = TemplateSpecializationVal;
539 if (!Template.Params.empty()) {
542 SerializeTemplateParam,
"End",
543 [VerticalDisplay](Object &JsonObj) {
544 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
548 if (!Template.Constraints.empty())
550 serializeInfoLambda());
552 Obj[
"Template"] = TemplateVal;
555void JSONGenerator::serializeInfo(
const ConceptInfo &I, Object &Obj) {
556 serializeCommonAttributes(I, Obj);
557 Obj[
"IsType"] = I.IsType;
558 Obj[
"ConstraintExpression"] = I.ConstraintExpression;
559 serializeInfo(I.Template, Obj);
562void JSONGenerator::serializeInfo(
const TypeInfo &I, Object &Obj) {
563 Obj[
"Name"] = I.Type.Name;
564 Obj[
"QualName"] = I.Type.QualName;
565 Obj[
"USR"] = toHex(toStringRef(I.Type.USR));
566 Obj[
"IsTemplate"] = I.IsTemplate;
567 Obj[
"IsBuiltIn"] = I.IsBuiltIn;
570void JSONGenerator::serializeInfo(
const FieldTypeInfo &I, Object &Obj) {
571 Obj[
"Name"] = I.Name;
573 json::Value ReferenceVal =
Object();
574 Object &ReferenceObj = *ReferenceVal.getAsObject();
575 serializeReference(I.Type, ReferenceObj);
576 Obj[
"Type"] = ReferenceVal;
579void JSONGenerator::serializeInfo(
const FunctionInfo &F, json::Object &Obj) {
580 serializeCommonAttributes(F, Obj);
581 Obj[
"IsStatic"] = F.IsStatic;
583 auto ReturnTypeObj =
Object();
584 serializeInfo(F.ReturnType, ReturnTypeObj);
585 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
587 if (!F.Params.empty()) {
589 serializeArray(F.Params, Obj,
"Params", serializeInfoLambda(),
"ParamEnd",
590 [VerticalDisplay](Object &JsonObj) {
591 JsonObj[
"VerticalDisplay"] = VerticalDisplay;
596 serializeInfo(F.Template.value(), Obj);
599void JSONGenerator::serializeInfo(
const EnumValueInfo &I, Object &Obj) {
600 Obj[
"Name"] = I.Name;
601 if (!I.ValueExpr.empty())
602 Obj[
"ValueExpr"] = I.ValueExpr;
604 Obj[
"Value"] = I.Value;
609void JSONGenerator::serializeInfo(
const EnumInfo &I, json::Object &Obj) {
610 serializeCommonAttributes(I, Obj);
611 Obj[
"Scoped"] = I.Scoped;
614 json::Value BaseTypeVal =
Object();
615 auto &BaseTypeObj = *BaseTypeVal.getAsObject();
616 BaseTypeObj[
"Name"] = I.BaseType->Type.Name;
617 BaseTypeObj[
"QualName"] = I.BaseType->Type.QualName;
618 BaseTypeObj[
"USR"] = toHex(toStringRef(I.BaseType->Type.USR));
619 Obj[
"BaseType"] = BaseTypeVal;
622 if (!I.Members.empty()) {
623 for (
const auto &Member : I.Members) {
624 if (!Member.Description.empty()) {
625 Obj[
"HasComments"] =
true;
633void JSONGenerator::serializeInfo(
const TypedefInfo &I, json::Object &Obj) {
634 serializeCommonAttributes(I, Obj);
635 Obj[
"TypeDeclaration"] = I.TypeDeclaration;
636 Obj[
"IsUsing"] = I.IsUsing;
637 json::Value TypeVal =
Object();
638 auto &TypeObj = *TypeVal.getAsObject();
639 serializeInfo(I.Underlying, TypeObj);
640 Obj[
"Underlying"] = TypeVal;
642 serializeInfo(I.Template.value(), Obj);
645void JSONGenerator::serializeInfo(
const BaseRecordInfo &I, Object &Obj) {
646 serializeInfo(
static_cast<const RecordInfo &
>(I), Obj);
647 Obj[
"IsVirtual"] = I.IsVirtual;
648 Obj[
"Access"] = getAccessSpelling(I.Access);
649 Obj[
"IsParent"] = I.IsParent;
652void JSONGenerator::serializeInfo(
const FriendInfo &I, Object &Obj) {
653 auto FriendRef =
Object();
654 serializeReference(I.Ref, FriendRef);
655 Obj[
"Reference"] = std::move(FriendRef);
656 Obj[
"IsClass"] = I.IsClass;
658 serializeInfo(I.Template.value(), Obj);
659 if (!I.Params.empty())
662 auto ReturnTypeObj =
Object();
663 serializeInfo(I.ReturnType.value(), ReturnTypeObj);
664 Obj[
"ReturnType"] = std::move(ReturnTypeObj);
666 serializeCommonAttributes(I, Obj);
669static void insertArray(Object &Obj, json::Value &Array, StringRef Key) {
671 Obj[
"Has" + Key.str()] =
true;
674void JSONGenerator::serializeInfo(
const RecordInfo &I, json::Object &Obj) {
675 serializeCommonAttributes(I, Obj);
677 Obj[
"IsTypedef"] = I.IsTypeDef;
678 Obj[
"MangledName"] = I.MangledName;
680 if (!I.Children.Functions.empty()) {
681 json::Value PubFunctionsArray = Array();
682 json::Array &PubFunctionsArrayRef = *PubFunctionsArray.getAsArray();
683 json::Value ProtFunctionsArray = Array();
684 json::Array &ProtFunctionsArrayRef = *ProtFunctionsArray.getAsArray();
686 for (
const auto &Function : I.Children.Functions) {
687 json::Value FunctionVal = Object();
688 auto &FunctionObj = *FunctionVal.getAsObject();
689 serializeInfo(Function, FunctionObj);
690 AccessSpecifier Access = Function.Access;
691 if (Access == AccessSpecifier::AS_public)
692 PubFunctionsArrayRef.push_back(FunctionVal);
693 else if (Access == AccessSpecifier::AS_protected)
694 ProtFunctionsArrayRef.push_back(FunctionVal);
697 if (!PubFunctionsArrayRef.empty())
698 insertArray(Obj, PubFunctionsArray,
"PublicMethods");
699 if (!ProtFunctionsArrayRef.empty())
700 insertArray(Obj, ProtFunctionsArray,
"ProtectedMethods");
703 if (!I.Members.empty()) {
704 Obj[
"HasMembers"] =
true;
705 json::Value PublicMembersArray =
Array();
706 json::Array &PubMembersArrayRef = *PublicMembersArray.getAsArray();
707 json::Value ProtectedMembersArray =
Array();
708 json::Array &ProtMembersArrayRef = *ProtectedMembersArray.getAsArray();
709 json::Value PrivateMembersArray =
Array();
710 json::Array &PrivateMembersArrayRef = *PrivateMembersArray.getAsArray();
712 for (
const MemberTypeInfo &Member : I.Members) {
713 json::Value MemberVal =
Object();
714 auto &MemberObj = *MemberVal.getAsObject();
715 MemberObj[
"Name"] = Member.Name;
716 MemberObj[
"Type"] = Member.Type.Name;
717 MemberObj[
"IsStatic"] = Member.IsStatic;
719 if (Member.Access == AccessSpecifier::AS_public)
720 PubMembersArrayRef.push_back(MemberVal);
721 else if (Member.Access == AccessSpecifier::AS_protected)
722 ProtMembersArrayRef.push_back(MemberVal);
723 else if (Member.Access == AccessSpecifier::AS_private)
724 PrivateMembersArrayRef.push_back(MemberVal);
727 if (!PubMembersArrayRef.empty())
728 insertArray(Obj, PublicMembersArray,
"PublicMembers");
729 if (!ProtMembersArrayRef.empty())
730 insertArray(Obj, ProtectedMembersArray,
"ProtectedMembers");
731 if (!PrivateMembersArrayRef.empty())
732 insertArray(Obj, PrivateMembersArray,
"PrivateMembers");
735 if (!I.Bases.empty())
738 if (!I.Parents.empty()) {
739 serializeArray(I.Parents, Obj,
"Parents", serializeReferenceLambda());
740 Obj[
"HasParents"] =
true;
743 if (!I.VirtualParents.empty()) {
745 serializeReferenceLambda());
746 Obj[
"HasVirtualParents"] =
true;
750 serializeInfo(I.Template.value(), Obj);
752 if (!I.Friends.empty()) {
754 Obj[
"HasFriends"] =
true;
757 serializeCommonChildren(I.Children, Obj);
760void JSONGenerator::serializeInfo(
const VarInfo &I, json::Object &Obj) {
761 serializeCommonAttributes(I, Obj);
762 Obj[
"IsStatic"] = I.IsStatic;
764 serializeInfo(I.Type, TypeObj);
765 Obj[
"Type"] = std::move(TypeObj);
768void JSONGenerator::serializeInfo(
const NamespaceInfo &I, json::Object &Obj) {
769 serializeCommonAttributes(I, Obj);
771 Obj[
"Name"] =
"Global Namespace";
773 if (!I.Children.Functions.empty()) {
775 serializeInfoLambda());
776 Obj[
"HasFunctions"] =
true;
779 if (!I.Children.Concepts.empty()) {
780 serializeArray(I.Children.Concepts, Obj,
"Concepts", serializeInfoLambda());
781 Obj[
"HasConcepts"] =
true;
784 if (!I.Children.Variables.empty()) {
786 serializeInfoLambda());
787 Obj[
"HasVariables"] =
true;
792 SmallString<64> BasePath = I.getRelativeFilePath(
"");
796 SerializeReferenceFunc = [
this, BasePath](
const Reference &Ref,
798 serializeMDReference(Ref, Object, BasePath);
800 serializeCommonChildren(I.Children, Obj, SerializeReferenceFunc);
802 SerializeReferenceFunc = serializeReferenceLambda();
803 serializeCommonChildren(I.Children, Obj);
806 if (!I.Children.Namespaces.empty()) {
808 SerializeReferenceFunc);
809 Obj[
"HasNamespaces"] =
true;
813SmallString<16> JSONGenerator::determineFileName(
Info *I,
814 SmallString<128> &Path) {
815 SmallString<16> FileName;
817 auto *RecordSymbolInfo =
static_cast<SymbolInfo *
>(I);
818 FileName = RecordSymbolInfo->MangledName;
823 sys::path::append(Path, FileName +
".json");
832 Processed.reserve(CDCtxIndex.
Children.size());
836 sys::path::native(NewPath, sys::path::Style::posix);
837 sys::path::append(NewPath, sys::path::Style::posix,
840 Processed.push_back(NewIdx);
847Error JSONGenerator::serializeAllFiles(
const ClangDocContext &CDCtx,
849 json::Value ObjVal = Object();
850 Object &Obj = *ObjVal.getAsObject();
852 serializeArray(IndexCopy, Obj,
"Index", serializeReferenceLambda());
853 SmallString<128> Path;
854 sys::path::append(Path, RootDir,
"json",
"all_files.json");
855 std::error_code FileErr;
856 raw_fd_ostream RootOS(Path, FileErr, sys::fs::OF_Text);
858 return createFileError(
"cannot open file " + Path, FileErr);
859 RootOS << llvm::formatv(
"{0:2}", ObjVal);
860 return Error::success();
866Error JSONGenerator::serializeIndex(StringRef RootDir) {
868 return Error::success();
870 json::Value ObjVal = Object();
871 Object &Obj = *ObjVal.getAsObject();
876 json::Value IndexArray = json::Array();
877 auto &IndexArrayRef = *IndexArray.getAsArray();
879 if (IndexCopy.Children.empty()) {
885 IndexArrayRef.reserve(
CDCtx->Idx.Children.size());
888 auto Children = IndexCopy.getSortedChildren();
890 for (
const auto *Idx : Children) {
891 if (Idx->Children.empty())
894 json::Value IdxVal =
Object();
895 auto &IdxObj = *IdxVal.getAsObject();
897 TypeStr.at(0) = toUppercase(TypeStr.at(0));
898 IdxObj[
"Type"] = TypeStr;
899 serializeReference(*Idx, IdxObj);
900 IndexArrayRef.push_back(IdxVal);
902 Obj[
"Index"] = IndexArray;
904 SmallString<128> IndexFilePath(RootDir);
905 sys::path::append(IndexFilePath,
"/json/index.json");
906 std::error_code FileErr;
907 raw_fd_ostream RootOS(IndexFilePath, FileErr, sys::fs::OF_Text);
909 return createFileError(
"cannot open file " + IndexFilePath, FileErr);
910 RootOS << llvm::formatv(
"{0:2}", ObjVal);
911 return Error::success();
922 auto Iter = Infos.find(llvm::toHex(ParentUSR));
923 if (Iter == Infos.end())
925 auto &ParentInfo = Iter->second;
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
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.")
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) {})
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
StringRef getRelativeFilePath(const StringRef &CurrentPath) const
Returns the file path for this Info relative to CurrentPath.
SmallVector< Context, 4 > Contexts
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.