[clang-tools-extra] [clang-doc] add a JSON generator (PR #142483)
Paul Kirth via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 6 13:25:11 PDT 2025
================
@@ -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)
+ DescArrayRef.push_back(serializeComment(Comment));
+ Obj["Description"] = DescArray;
+ }
+
+ // Namespaces aren't SymbolInfos, so they dont have a DefLoc
+ if (I.IT != InfoType::IT_namespace) {
+ const auto *Symbol = static_cast<const SymbolInfo *>(&I);
+ if (Symbol->DefLoc)
+ Obj["Location"] =
+ serializeLocation(Symbol->DefLoc.value(), RepositoryUrl);
+ }
+}
+
+static void serializeReference(const Reference &Ref, Object &ReferenceObj,
+ SmallString<64> CurrentDirectory) {
+ SmallString<64> Path = Ref.getRelativeFilePath(CurrentDirectory);
+ sys::path::append(Path, Ref.getFileBaseName() + ".json");
+ sys::path::native(Path, sys::path::Style::posix);
+ ReferenceObj["Link"] = Path;
+ ReferenceObj["Name"] = Ref.Name;
+ ReferenceObj["QualName"] = Ref.QualName;
+ ReferenceObj["USR"] = toHex(toStringRef(Ref.USR));
+}
+
+static void serializeReference(const SmallVector<Reference, 4> &References,
+ Object &Obj, std::string Key) {
+ json::Value ReferencesArray = Array();
+ json::Array &ReferencesArrayRef = *ReferencesArray.getAsArray();
+ for (const auto& Reference : References) {
----------------
ilovepi wrote:
ditto on reserving the size upfront. I need to go through the Mustache impl and do the same thing I'm sure.
https://github.com/llvm/llvm-project/pull/142483
More information about the cfe-commits
mailing list