================ @@ -0,0 +1,430 @@ +#include "Generators.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/Support/JSON.h" + +using namespace llvm; +using namespace llvm::json; + +namespace clang { +namespace doc { + +class JSONGenerator : public Generator { +public: + static const char *Format; + + Error generateDocs(StringRef RootDir, + llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const ClangDocContext &CDCtx) override; + Error createResources(ClangDocContext &CDCtx) override; + Error generateDocForInfo(Info *I, llvm::raw_ostream &OS, + const ClangDocContext &CDCtx) override; +}; + +const char *JSONGenerator::Format = "json"; + +static void serializeInfo(const TypedefInfo &I, json::Object &Obj, + std::optional<StringRef> RepositoryUrl); +static void serializeInfo(const EnumInfo &I, json::Object &Obj, + std::optional<StringRef> RepositoryUrl); + +static json::Object serializeLocation(const Location &Loc, + std::optional<StringRef> RepositoryUrl) { + Object LocationObj = Object(); + LocationObj["LineNumber"] = Loc.StartLineNumber; + LocationObj["Filename"] = Loc.Filename; + + if (!Loc.IsFileInRootDir || !RepositoryUrl) + return LocationObj; + SmallString<128> FileURL(*RepositoryUrl); + sys::path::append(FileURL, sys::path::Style::posix, Loc.Filename); + FileURL += "#" + std::to_string(Loc.StartLineNumber); + LocationObj["FileURL"] = FileURL; + return LocationObj; +} + +static json::Value serializeComment(const CommentInfo &Comment) { + assert((Comment.Kind == "BlockCommandComment" || + Comment.Kind == "FullComment" || Comment.Kind == "ParagraphComment" || + Comment.Kind == "TextComment") && + "Unknown Comment type in CommentInfo."); + + Object Obj = Object(); + json::Value Child = Object(); + + // TextComment has no children, so return it. + if (Comment.Kind == "TextComment") { + Obj["TextComment"] = Comment.Text; + return Obj; + } + + // BlockCommandComment needs to generate a Command key. + if (Comment.Kind == "BlockCommandComment") + Child.getAsObject()->insert({"Command", Comment.Name}); + + // Use the same handling for everything else. + // Only valid for: + // - BlockCommandComment + // - FullComment + // - ParagraphComment + json::Value ChildArr = Array(); + auto &CARef = *ChildArr.getAsArray(); + CARef.reserve(Comment.Children.size()); + for (const auto &C : Comment.Children) + CARef.emplace_back(serializeComment(*C)); + Child.getAsObject()->insert({"Children", ChildArr}); + Obj.insert({Comment.Kind, Child}); + return Obj; +} + +static void serializeCommonAttributes(const Info &I, json::Object &Obj, + std::optional<StringRef> RepositoryUrl) { + Obj["Name"] = I.Name; + Obj["USR"] = toHex(toStringRef(I.USR)); + + if (!I.Path.empty()) + Obj["Path"] = I.Path; + + if (!I.Namespace.empty()) { + Obj["Namespace"] = json::Array(); + for (const auto &NS : I.Namespace) + Obj["Namespace"].getAsArray()->push_back(NS.Name); + } + + if (!I.Description.empty()) { + json::Value DescArray = json::Array(); + auto &DescArrayRef = *DescArray.getAsArray(); + for (const auto &Comment : I.Description) ---------------- ilovepi wrote:
can we reserve `I.Description.size()` to avoid realloc? https://github.com/llvm/llvm-project/pull/142483 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits