-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[clang-doc] refactor JSONGenerator array usage #145595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
b5af9be
to
df4ddc4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Glad to see so much code getting deleted! Overall great cleanups. Left a couple small comments inline.
Improve code reuse by calling serializeArray in more generic cases instead of creating and reserving arrays on their own.
df4ddc4
to
19569ab
Compare
@llvm/pr-subscribers-clang-tools-extra Author: Erick Velez (evelez7) ChangesImprove code reuse by calling serializeArray in more generic cases Full diff: https://github.com/llvm/llvm-project/pull/145595.diff 1 Files Affected:
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index 91f5ba4080619..1f6167f7f9b8d 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -22,22 +22,31 @@ class JSONGenerator : public Generator {
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 void serializeInfo(const ConstraintInfo &I, Object &Obj);
+static void serializeInfo(const RecordInfo &I, Object &Obj,
+ const std::optional<StringRef> &RepositoryUrl);
+
+static void serializeReference(const Reference &Ref, Object &ReferenceObj);
+
+template <typename Container, typename SerializationFunc>
+static void serializeArray(const Container &Records, Object &Obj,
+ const std::string &Key,
+ SerializationFunc SerializeInfo);
// Convenience lambda to pass to serializeArray.
// If a serializeInfo needs a RepositoryUrl, create a local lambda that captures
// the optional.
-static auto SerializeInfoLambda = [](const ConstraintInfo &Info,
- Object &Object) {
+static auto SerializeInfoLambda = [](const auto &Info, Object &Object) {
serializeInfo(Info, Object);
};
+static auto SerializeReferenceLambda = [](const Reference &Ref,
+ Object &Object) {
+ serializeReference(Ref, Object);
+};
-static json::Object serializeLocation(const Location &Loc,
- std::optional<StringRef> RepositoryUrl) {
+static json::Object
+serializeLocation(const Location &Loc,
+ const std::optional<StringRef> &RepositoryUrl) {
Object LocationObj = Object();
LocationObj["LineNumber"] = Loc.StartLineNumber;
LocationObj["Filename"] = Loc.Filename;
@@ -159,8 +168,9 @@ static json::Value serializeComment(const CommentInfo &I) {
llvm_unreachable("Unknown comment kind encountered.");
}
-static void serializeCommonAttributes(const Info &I, json::Object &Obj,
- std::optional<StringRef> RepositoryUrl) {
+static void
+serializeCommonAttributes(const Info &I, json::Object &Obj,
+ const std::optional<StringRef> &RepositoryUrl) {
Obj["Name"] = I.Name;
Obj["USR"] = toHex(toStringRef(I.USR));
@@ -198,67 +208,28 @@ static void serializeReference(const Reference &Ref, Object &ReferenceObj) {
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();
- ReferencesArrayRef.reserve(References.size());
- for (const auto &Reference : References) {
- json::Value ReferenceVal = Object();
- auto &ReferenceObj = *ReferenceVal.getAsObject();
- serializeReference(Reference, ReferenceObj);
- ReferencesArrayRef.push_back(ReferenceVal);
- }
- Obj[Key] = ReferencesArray;
-}
-
// Although namespaces and records both have ScopeChildren, they serialize them
// differently. Only enums, records, and typedefs are handled here.
-static void serializeCommonChildren(const ScopeChildren &Children,
- json::Object &Obj,
- std::optional<StringRef> RepositoryUrl) {
- if (!Children.Enums.empty()) {
- json::Value EnumsArray = Array();
- auto &EnumsArrayRef = *EnumsArray.getAsArray();
- EnumsArrayRef.reserve(Children.Enums.size());
- for (const auto &Enum : Children.Enums) {
- json::Value EnumVal = Object();
- auto &EnumObj = *EnumVal.getAsObject();
- serializeInfo(Enum, EnumObj, RepositoryUrl);
- EnumsArrayRef.push_back(EnumVal);
- }
- Obj["Enums"] = EnumsArray;
- }
+static void
+serializeCommonChildren(const ScopeChildren &Children, json::Object &Obj,
+ const std::optional<StringRef> &RepositoryUrl) {
+ static auto SerializeInfo = [&RepositoryUrl](const auto &Info,
+ Object &Object) {
+ serializeInfo(Info, Object, RepositoryUrl);
+ };
- if (!Children.Typedefs.empty()) {
- json::Value TypedefsArray = Array();
- auto &TypedefsArrayRef = *TypedefsArray.getAsArray();
- TypedefsArrayRef.reserve(Children.Typedefs.size());
- for (const auto &Typedef : Children.Typedefs) {
- json::Value TypedefVal = Object();
- auto &TypedefObj = *TypedefVal.getAsObject();
- serializeInfo(Typedef, TypedefObj, RepositoryUrl);
- TypedefsArrayRef.push_back(TypedefVal);
- }
- Obj["Typedefs"] = TypedefsArray;
- }
+ if (!Children.Enums.empty())
+ serializeArray(Children.Enums, Obj, "Enums", SerializeInfo);
- if (!Children.Records.empty()) {
- json::Value RecordsArray = Array();
- auto &RecordsArrayRef = *RecordsArray.getAsArray();
- RecordsArrayRef.reserve(Children.Records.size());
- for (const auto &Record : Children.Records) {
- json::Value RecordVal = Object();
- auto &RecordObj = *RecordVal.getAsObject();
- serializeReference(Record, RecordObj);
- RecordsArrayRef.push_back(RecordVal);
- }
- Obj["Records"] = RecordsArray;
- }
+ if (!Children.Typedefs.empty())
+ serializeArray(Children.Typedefs, Obj, "Typedefs", SerializeInfo);
+
+ if (!Children.Records.empty())
+ serializeArray(Children.Records, Obj, "Records", SerializeReferenceLambda);
}
-template <typename T, typename SerializationFunc>
-static void serializeArray(const std::vector<T> &Records, Object &Obj,
+template <typename Container, typename SerializationFunc>
+static void serializeArray(const Container &Records, Object &Obj,
const std::string &Key,
SerializationFunc SerializeInfo) {
json::Value RecordsArray = Array();
@@ -278,6 +249,16 @@ static void serializeInfo(const ConstraintInfo &I, Object &Obj) {
Obj["Expression"] = I.ConstraintExpr;
}
+static void serializeInfo(const ArrayRef<TemplateParamInfo> &Params,
+ Object &Obj) {
+ json::Value ParamsArray = Array();
+ auto &ParamsArrayRef = *ParamsArray.getAsArray();
+ ParamsArrayRef.reserve(Params.size());
+ for (const auto &Param : Params)
+ ParamsArrayRef.push_back(Param.Contents);
+ Obj["Parameters"] = ParamsArray;
+}
+
static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
json::Value TemplateVal = Object();
auto &TemplateObj = *TemplateVal.getAsObject();
@@ -287,25 +268,13 @@ static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
auto &TemplateSpecializationObj = *TemplateSpecializationVal.getAsObject();
TemplateSpecializationObj["SpecializationOf"] =
toHex(toStringRef(Template.Specialization->SpecializationOf));
- if (!Template.Specialization->Params.empty()) {
- json::Value ParamsArray = Array();
- auto &ParamsArrayRef = *ParamsArray.getAsArray();
- ParamsArrayRef.reserve(Template.Specialization->Params.size());
- for (const auto &Param : Template.Specialization->Params)
- ParamsArrayRef.push_back(Param.Contents);
- TemplateSpecializationObj["Parameters"] = ParamsArray;
- }
+ if (!Template.Specialization->Params.empty())
+ serializeInfo(Template.Specialization->Params, TemplateSpecializationObj);
TemplateObj["Specialization"] = TemplateSpecializationVal;
}
- if (!Template.Params.empty()) {
- json::Value ParamsArray = Array();
- auto &ParamsArrayRef = *ParamsArray.getAsArray();
- ParamsArrayRef.reserve(Template.Params.size());
- for (const auto &Param : Template.Params)
- ParamsArrayRef.push_back(Param.Contents);
- TemplateObj["Parameters"] = ParamsArray;
- }
+ if (!Template.Params.empty())
+ serializeInfo(Template.Params, TemplateObj);
if (!Template.Constraints.empty())
serializeArray(Template.Constraints, TemplateObj, "Constraints",
@@ -315,7 +284,7 @@ static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
}
static void serializeInfo(const ConceptInfo &I, Object &Obj,
- std::optional<StringRef> RepositoryUrl) {
+ const std::optional<StringRef> &RepositoryUrl) {
serializeCommonAttributes(I, Obj, RepositoryUrl);
Obj["IsType"] = I.IsType;
Obj["ConstraintExpression"] = I.ConstraintExpression;
@@ -330,8 +299,13 @@ static void serializeInfo(const TypeInfo &I, Object &Obj) {
Obj["IsBuiltIn"] = I.IsBuiltIn;
}
+static void serializeInfo(const FieldTypeInfo &I, Object &Obj) {
+ Obj["Name"] = I.Name;
+ Obj["Type"] = I.Type.Name;
+}
+
static void serializeInfo(const FunctionInfo &F, json::Object &Obj,
- std::optional<StringRef> RepositoryURL) {
+ const std::optional<StringRef> &RepositoryURL) {
serializeCommonAttributes(F, Obj, RepositoryURL);
Obj["IsStatic"] = F.IsStatic;
@@ -339,26 +313,23 @@ static void serializeInfo(const FunctionInfo &F, json::Object &Obj,
serializeInfo(F.ReturnType, ReturnTypeObj);
Obj["ReturnType"] = std::move(ReturnTypeObj);
- if (!F.Params.empty()) {
- json::Value ParamsArray = json::Array();
- auto &ParamsArrayRef = *ParamsArray.getAsArray();
- ParamsArrayRef.reserve(F.Params.size());
- for (const auto &Param : F.Params) {
- json::Value ParamVal = Object();
- auto &ParamObj = *ParamVal.getAsObject();
- ParamObj["Name"] = Param.Name;
- ParamObj["Type"] = Param.Type.Name;
- ParamsArrayRef.push_back(ParamVal);
- }
- Obj["Params"] = ParamsArray;
- }
+ if (!F.Params.empty())
+ serializeArray(F.Params, Obj, "Params", SerializeInfoLambda);
if (F.Template)
serializeInfo(F.Template.value(), Obj);
}
+static void serializeInfo(const EnumValueInfo &I, Object &Obj) {
+ Obj["Name"] = I.Name;
+ if (!I.ValueExpr.empty())
+ Obj["ValueExpr"] = I.ValueExpr;
+ else
+ Obj["Value"] = I.Value;
+}
+
static void serializeInfo(const EnumInfo &I, json::Object &Obj,
- std::optional<StringRef> RepositoryUrl) {
+ const std::optional<StringRef> &RepositoryUrl) {
serializeCommonAttributes(I, Obj, RepositoryUrl);
Obj["Scoped"] = I.Scoped;
@@ -371,26 +342,12 @@ static void serializeInfo(const EnumInfo &I, json::Object &Obj,
Obj["BaseType"] = BaseTypeVal;
}
- if (!I.Members.empty()) {
- json::Value MembersArray = Array();
- auto &MembersArrayRef = *MembersArray.getAsArray();
- MembersArrayRef.reserve(I.Members.size());
- for (const auto &Member : I.Members) {
- json::Value MemberVal = Object();
- auto &MemberObj = *MemberVal.getAsObject();
- MemberObj["Name"] = Member.Name;
- if (!Member.ValueExpr.empty())
- MemberObj["ValueExpr"] = Member.ValueExpr;
- else
- MemberObj["Value"] = Member.Value;
- MembersArrayRef.push_back(MemberVal);
- }
- Obj["Members"] = MembersArray;
- }
+ if (!I.Members.empty())
+ serializeArray(I.Members, Obj, "Members", SerializeInfoLambda);
}
static void serializeInfo(const TypedefInfo &I, json::Object &Obj,
- std::optional<StringRef> RepositoryUrl) {
+ const std::optional<StringRef> &RepositoryUrl) {
serializeCommonAttributes(I, Obj, RepositoryUrl);
Obj["TypeDeclaration"] = I.TypeDeclaration;
Obj["IsUsing"] = I.IsUsing;
@@ -400,8 +357,16 @@ static void serializeInfo(const TypedefInfo &I, json::Object &Obj,
Obj["Underlying"] = TypeVal;
}
+static void serializeInfo(const BaseRecordInfo &I, Object &Obj,
+ const std::optional<StringRef> &RepositoryUrl) {
+ serializeInfo(static_cast<const RecordInfo &>(I), Obj, RepositoryUrl);
+ Obj["IsVirtual"] = I.IsVirtual;
+ Obj["Access"] = getAccessSpelling(I.Access);
+ Obj["IsParent"] = I.IsParent;
+}
+
static void serializeInfo(const RecordInfo &I, json::Object &Obj,
- std::optional<StringRef> RepositoryUrl) {
+ const std::optional<StringRef> &RepositoryUrl) {
serializeCommonAttributes(I, Obj, RepositoryUrl);
Obj["FullName"] = I.FullName;
Obj["TagType"] = getTagType(I.TagType);
@@ -454,27 +419,19 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
Obj["ProtectedMembers"] = ProtectedMembersArray;
}
- if (!I.Bases.empty()) {
- json::Value BasesArray = Array();
- json::Array &BasesArrayRef = *BasesArray.getAsArray();
- BasesArrayRef.reserve(I.Bases.size());
- for (const auto &BaseInfo : I.Bases) {
- json::Value BaseInfoVal = Object();
- auto &BaseInfoObj = *BaseInfoVal.getAsObject();
- serializeInfo(BaseInfo, BaseInfoObj, RepositoryUrl);
- BaseInfoObj["IsVirtual"] = BaseInfo.IsVirtual;
- BaseInfoObj["Access"] = getAccessSpelling(BaseInfo.Access);
- BaseInfoObj["IsParent"] = BaseInfo.IsParent;
- BasesArrayRef.push_back(BaseInfoVal);
- }
- Obj["Bases"] = BasesArray;
- }
+ if (!I.Bases.empty())
+ serializeArray(
+ I.Bases, Obj, "Bases",
+ [&RepositoryUrl](const BaseRecordInfo &Base, Object &BaseObj) {
+ serializeInfo(Base, BaseObj, RepositoryUrl);
+ });
if (!I.Parents.empty())
- serializeReference(I.Parents, Obj, "Parents");
+ serializeArray(I.Parents, Obj, "Parents", SerializeReferenceLambda);
if (!I.VirtualParents.empty())
- serializeReference(I.VirtualParents, Obj, "VirtualParents");
+ serializeArray(I.VirtualParents, Obj, "VirtualParents",
+ SerializeReferenceLambda);
if (I.Template)
serializeInfo(I.Template.value(), Obj);
@@ -483,7 +440,7 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
}
static void serializeInfo(const VarInfo &I, json::Object &Obj,
- std::optional<StringRef> RepositoryUrl) {
+ const std::optional<StringRef> &RepositoryUrl) {
serializeCommonAttributes(I, Obj, RepositoryUrl);
Obj["IsStatic"] = I.IsStatic;
auto TypeObj = Object();
@@ -492,45 +449,26 @@ static void serializeInfo(const VarInfo &I, json::Object &Obj,
}
static void serializeInfo(const NamespaceInfo &I, json::Object &Obj,
- std::optional<StringRef> RepositoryUrl) {
+ const std::optional<StringRef> &RepositoryUrl) {
serializeCommonAttributes(I, Obj, RepositoryUrl);
- if (!I.Children.Namespaces.empty()) {
- json::Value NamespacesArray = Array();
- auto &NamespacesArrayRef = *NamespacesArray.getAsArray();
- NamespacesArrayRef.reserve(I.Children.Namespaces.size());
- for (auto &Namespace : I.Children.Namespaces) {
- json::Value NamespaceVal = Object();
- auto &NamespaceObj = *NamespaceVal.getAsObject();
- serializeReference(Namespace, NamespaceObj);
- NamespacesArrayRef.push_back(NamespaceVal);
- }
- Obj["Namespaces"] = NamespacesArray;
- }
+ if (!I.Children.Namespaces.empty())
+ serializeArray(I.Children.Namespaces, Obj, "Namespaces",
+ SerializeReferenceLambda);
- auto SerializeInfo = [RepositoryUrl](const auto &Info, Object &Object) {
+ static auto SerializeInfo = [&RepositoryUrl](const auto &Info,
+ Object &Object) {
serializeInfo(Info, Object, RepositoryUrl);
};
- if (!I.Children.Functions.empty()) {
- json::Value FunctionsArray = Array();
- auto &FunctionsArrayRef = *FunctionsArray.getAsArray();
- FunctionsArrayRef.reserve(I.Children.Functions.size());
- for (const auto &Function : I.Children.Functions) {
- json::Value FunctionVal = Object();
- auto &FunctionObj = *FunctionVal.getAsObject();
- serializeInfo(Function, FunctionObj, RepositoryUrl);
- FunctionsArrayRef.push_back(FunctionVal);
- }
- Obj["Functions"] = FunctionsArray;
- }
+ if (!I.Children.Functions.empty())
+ serializeArray(I.Children.Functions, Obj, "Functions", SerializeInfo);
if (!I.Children.Concepts.empty())
serializeArray(I.Children.Concepts, Obj, "Concepts", SerializeInfo);
- if (!I.Children.Variables.empty()) {
+ if (!I.Children.Variables.empty())
serializeArray(I.Children.Variables, Obj, "Variables", SerializeInfo);
- }
serializeCommonChildren(I.Children, Obj, RepositoryUrl);
}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! One idea for future improvement would be to wrap std::optional<StringRef> RepositoryUrl
in a object (e.g. SerializationContext
) so in the future if we need to pass around more information beside the URL, we don't need to modify every one of these functions and lambdas.
Improve code reuse by calling serializeArray in more generic cases instead of creating and reserving arrays on their own.
Improve code reuse by calling serializeArray in more generic cases instead of creating and reserving arrays on their own.
Improve code reuse by calling serializeArray in more generic cases
instead of creating and reserving arrays on their own.