Skip to content

Commit df4ddc4

Browse files
committed
[clang-doc] refactor JSONGenerator array usage
Improve code reuse by calling serializeArray in more generic cases instead of creating and reserving arrays on their own.
1 parent 5ff6c8e commit df4ddc4

File tree

1 file changed

+83
-147
lines changed

1 file changed

+83
-147
lines changed

clang-tools-extra/clang-doc/JSONGenerator.cpp

Lines changed: 83 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,27 @@ class JSONGenerator : public Generator {
2222

2323
const char *JSONGenerator::Format = "json";
2424

25-
static void serializeInfo(const TypedefInfo &I, json::Object &Obj,
26-
std::optional<StringRef> RepositoryUrl);
27-
static void serializeInfo(const EnumInfo &I, json::Object &Obj,
28-
std::optional<StringRef> RepositoryUrl);
2925
static void serializeInfo(const ConstraintInfo &I, Object &Obj);
26+
static void serializeInfo(const RecordInfo &I, Object &Obj,
27+
std::optional<StringRef> RepositoryUrl);
28+
29+
static void serializeReference(const Reference &Ref, Object &ReferenceObj);
30+
31+
template <typename Container, typename SerializationFunc>
32+
static void serializeArray(const Container &Records, Object &Obj,
33+
const std::string &Key,
34+
SerializationFunc SerializeInfo);
3035

3136
// Convenience lambda to pass to serializeArray.
3237
// If a serializeInfo needs a RepositoryUrl, create a local lambda that captures
3338
// the optional.
34-
static auto SerializeInfoLambda = [](const ConstraintInfo &Info,
35-
Object &Object) {
39+
static auto SerializeInfoLambda = [](const auto &Info, Object &Object) {
3640
serializeInfo(Info, Object);
3741
};
42+
static auto SerializeReferenceLambda = [](const Reference &Ref,
43+
Object &Object) {
44+
serializeReference(Ref, Object);
45+
};
3846

3947
static json::Object serializeLocation(const Location &Loc,
4048
std::optional<StringRef> RepositoryUrl) {
@@ -198,67 +206,28 @@ static void serializeReference(const Reference &Ref, Object &ReferenceObj) {
198206
ReferenceObj["USR"] = toHex(toStringRef(Ref.USR));
199207
}
200208

201-
static void serializeReference(const SmallVector<Reference, 4> &References,
202-
Object &Obj, std::string Key) {
203-
json::Value ReferencesArray = Array();
204-
json::Array &ReferencesArrayRef = *ReferencesArray.getAsArray();
205-
ReferencesArrayRef.reserve(References.size());
206-
for (const auto &Reference : References) {
207-
json::Value ReferenceVal = Object();
208-
auto &ReferenceObj = *ReferenceVal.getAsObject();
209-
serializeReference(Reference, ReferenceObj);
210-
ReferencesArrayRef.push_back(ReferenceVal);
211-
}
212-
Obj[Key] = ReferencesArray;
213-
}
214-
215209
// Although namespaces and records both have ScopeChildren, they serialize them
216210
// differently. Only enums, records, and typedefs are handled here.
217211
static void serializeCommonChildren(const ScopeChildren &Children,
218212
json::Object &Obj,
219213
std::optional<StringRef> RepositoryUrl) {
220-
if (!Children.Enums.empty()) {
221-
json::Value EnumsArray = Array();
222-
auto &EnumsArrayRef = *EnumsArray.getAsArray();
223-
EnumsArrayRef.reserve(Children.Enums.size());
224-
for (const auto &Enum : Children.Enums) {
225-
json::Value EnumVal = Object();
226-
auto &EnumObj = *EnumVal.getAsObject();
227-
serializeInfo(Enum, EnumObj, RepositoryUrl);
228-
EnumsArrayRef.push_back(EnumVal);
229-
}
230-
Obj["Enums"] = EnumsArray;
231-
}
214+
static auto SerializeInfo = [RepositoryUrl](const auto &Info,
215+
Object &Object) {
216+
serializeInfo(Info, Object, RepositoryUrl);
217+
};
232218

233-
if (!Children.Typedefs.empty()) {
234-
json::Value TypedefsArray = Array();
235-
auto &TypedefsArrayRef = *TypedefsArray.getAsArray();
236-
TypedefsArrayRef.reserve(Children.Typedefs.size());
237-
for (const auto &Typedef : Children.Typedefs) {
238-
json::Value TypedefVal = Object();
239-
auto &TypedefObj = *TypedefVal.getAsObject();
240-
serializeInfo(Typedef, TypedefObj, RepositoryUrl);
241-
TypedefsArrayRef.push_back(TypedefVal);
242-
}
243-
Obj["Typedefs"] = TypedefsArray;
244-
}
219+
if (!Children.Enums.empty())
220+
serializeArray(Children.Enums, Obj, "Enums", SerializeInfo);
245221

246-
if (!Children.Records.empty()) {
247-
json::Value RecordsArray = Array();
248-
auto &RecordsArrayRef = *RecordsArray.getAsArray();
249-
RecordsArrayRef.reserve(Children.Records.size());
250-
for (const auto &Record : Children.Records) {
251-
json::Value RecordVal = Object();
252-
auto &RecordObj = *RecordVal.getAsObject();
253-
serializeReference(Record, RecordObj);
254-
RecordsArrayRef.push_back(RecordVal);
255-
}
256-
Obj["Records"] = RecordsArray;
257-
}
222+
if (!Children.Typedefs.empty())
223+
serializeArray(Children.Typedefs, Obj, "Typedefs", SerializeInfo);
224+
225+
if (!Children.Records.empty())
226+
serializeArray(Children.Records, Obj, "Records", SerializeReferenceLambda);
258227
}
259228

260-
template <typename T, typename SerializationFunc>
261-
static void serializeArray(const std::vector<T> &Records, Object &Obj,
229+
template <typename Container, typename SerializationFunc>
230+
static void serializeArray(const Container &Records, Object &Obj,
262231
const std::string &Key,
263232
SerializationFunc SerializeInfo) {
264233
json::Value RecordsArray = Array();
@@ -278,6 +247,16 @@ static void serializeInfo(const ConstraintInfo &I, Object &Obj) {
278247
Obj["Expression"] = I.ConstraintExpr;
279248
}
280249

250+
static void serializeInfo(const std::vector<TemplateParamInfo> &Params,
251+
Object &Obj) {
252+
json::Value ParamsArray = Array();
253+
auto &ParamsArrayRef = *ParamsArray.getAsArray();
254+
ParamsArrayRef.reserve(Params.size());
255+
for (const auto &Param : Params)
256+
ParamsArrayRef.push_back(Param.Contents);
257+
Obj["Parameters"] = ParamsArray;
258+
}
259+
281260
static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
282261
json::Value TemplateVal = Object();
283262
auto &TemplateObj = *TemplateVal.getAsObject();
@@ -287,25 +266,13 @@ static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
287266
auto &TemplateSpecializationObj = *TemplateSpecializationVal.getAsObject();
288267
TemplateSpecializationObj["SpecializationOf"] =
289268
toHex(toStringRef(Template.Specialization->SpecializationOf));
290-
if (!Template.Specialization->Params.empty()) {
291-
json::Value ParamsArray = Array();
292-
auto &ParamsArrayRef = *ParamsArray.getAsArray();
293-
ParamsArrayRef.reserve(Template.Specialization->Params.size());
294-
for (const auto &Param : Template.Specialization->Params)
295-
ParamsArrayRef.push_back(Param.Contents);
296-
TemplateSpecializationObj["Parameters"] = ParamsArray;
297-
}
269+
if (!Template.Specialization->Params.empty())
270+
serializeInfo(Template.Specialization->Params, TemplateSpecializationObj);
298271
TemplateObj["Specialization"] = TemplateSpecializationVal;
299272
}
300273

301-
if (!Template.Params.empty()) {
302-
json::Value ParamsArray = Array();
303-
auto &ParamsArrayRef = *ParamsArray.getAsArray();
304-
ParamsArrayRef.reserve(Template.Params.size());
305-
for (const auto &Param : Template.Params)
306-
ParamsArrayRef.push_back(Param.Contents);
307-
TemplateObj["Parameters"] = ParamsArray;
308-
}
274+
if (!Template.Params.empty())
275+
serializeInfo(Template.Params, TemplateObj);
309276

310277
if (!Template.Constraints.empty())
311278
serializeArray(Template.Constraints, TemplateObj, "Constraints",
@@ -330,6 +297,11 @@ static void serializeInfo(const TypeInfo &I, Object &Obj) {
330297
Obj["IsBuiltIn"] = I.IsBuiltIn;
331298
}
332299

300+
static void serializeInfo(const FieldTypeInfo &I, Object &Obj) {
301+
Obj["Name"] = I.Name;
302+
Obj["Type"] = I.Type.Name;
303+
}
304+
333305
static void serializeInfo(const FunctionInfo &F, json::Object &Obj,
334306
std::optional<StringRef> RepositoryURL) {
335307
serializeCommonAttributes(F, Obj, RepositoryURL);
@@ -339,24 +311,21 @@ static void serializeInfo(const FunctionInfo &F, json::Object &Obj,
339311
serializeInfo(F.ReturnType, ReturnTypeObj);
340312
Obj["ReturnType"] = std::move(ReturnTypeObj);
341313

342-
if (!F.Params.empty()) {
343-
json::Value ParamsArray = json::Array();
344-
auto &ParamsArrayRef = *ParamsArray.getAsArray();
345-
ParamsArrayRef.reserve(F.Params.size());
346-
for (const auto &Param : F.Params) {
347-
json::Value ParamVal = Object();
348-
auto &ParamObj = *ParamVal.getAsObject();
349-
ParamObj["Name"] = Param.Name;
350-
ParamObj["Type"] = Param.Type.Name;
351-
ParamsArrayRef.push_back(ParamVal);
352-
}
353-
Obj["Params"] = ParamsArray;
354-
}
314+
if (!F.Params.empty())
315+
serializeArray(F.Params, Obj, "Params", SerializeInfoLambda);
355316

356317
if (F.Template)
357318
serializeInfo(F.Template.value(), Obj);
358319
}
359320

321+
static void serializeInfo(const EnumValueInfo &I, Object &Obj) {
322+
Obj["Name"] = I.Name;
323+
if (!I.ValueExpr.empty())
324+
Obj["ValueExpr"] = I.ValueExpr;
325+
else
326+
Obj["Value"] = I.Value;
327+
}
328+
360329
static void serializeInfo(const EnumInfo &I, json::Object &Obj,
361330
std::optional<StringRef> RepositoryUrl) {
362331
serializeCommonAttributes(I, Obj, RepositoryUrl);
@@ -371,22 +340,8 @@ static void serializeInfo(const EnumInfo &I, json::Object &Obj,
371340
Obj["BaseType"] = BaseTypeVal;
372341
}
373342

374-
if (!I.Members.empty()) {
375-
json::Value MembersArray = Array();
376-
auto &MembersArrayRef = *MembersArray.getAsArray();
377-
MembersArrayRef.reserve(I.Members.size());
378-
for (const auto &Member : I.Members) {
379-
json::Value MemberVal = Object();
380-
auto &MemberObj = *MemberVal.getAsObject();
381-
MemberObj["Name"] = Member.Name;
382-
if (!Member.ValueExpr.empty())
383-
MemberObj["ValueExpr"] = Member.ValueExpr;
384-
else
385-
MemberObj["Value"] = Member.Value;
386-
MembersArrayRef.push_back(MemberVal);
387-
}
388-
Obj["Members"] = MembersArray;
389-
}
343+
if (!I.Members.empty())
344+
serializeArray(I.Members, Obj, "Members", SerializeInfoLambda);
390345
}
391346

392347
static void serializeInfo(const TypedefInfo &I, json::Object &Obj,
@@ -400,6 +355,14 @@ static void serializeInfo(const TypedefInfo &I, json::Object &Obj,
400355
Obj["Underlying"] = TypeVal;
401356
}
402357

358+
static void serializeInfo(const BaseRecordInfo &I, Object &Obj,
359+
const std::optional<StringRef> &RepositoryUrl) {
360+
serializeInfo(static_cast<const RecordInfo &>(I), Obj, RepositoryUrl);
361+
Obj["IsVirtual"] = I.IsVirtual;
362+
Obj["Access"] = getAccessSpelling(I.Access);
363+
Obj["IsParent"] = I.IsParent;
364+
}
365+
403366
static void serializeInfo(const RecordInfo &I, json::Object &Obj,
404367
std::optional<StringRef> RepositoryUrl) {
405368
serializeCommonAttributes(I, Obj, RepositoryUrl);
@@ -454,27 +417,19 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
454417
Obj["ProtectedMembers"] = ProtectedMembersArray;
455418
}
456419

457-
if (!I.Bases.empty()) {
458-
json::Value BasesArray = Array();
459-
json::Array &BasesArrayRef = *BasesArray.getAsArray();
460-
BasesArrayRef.reserve(I.Bases.size());
461-
for (const auto &BaseInfo : I.Bases) {
462-
json::Value BaseInfoVal = Object();
463-
auto &BaseInfoObj = *BaseInfoVal.getAsObject();
464-
serializeInfo(BaseInfo, BaseInfoObj, RepositoryUrl);
465-
BaseInfoObj["IsVirtual"] = BaseInfo.IsVirtual;
466-
BaseInfoObj["Access"] = getAccessSpelling(BaseInfo.Access);
467-
BaseInfoObj["IsParent"] = BaseInfo.IsParent;
468-
BasesArrayRef.push_back(BaseInfoVal);
469-
}
470-
Obj["Bases"] = BasesArray;
471-
}
420+
if (!I.Bases.empty())
421+
serializeArray(
422+
I.Bases, Obj, "Bases",
423+
[RepositoryUrl](const BaseRecordInfo &Base, Object &BaseObj) {
424+
serializeInfo(Base, BaseObj, RepositoryUrl);
425+
});
472426

473427
if (!I.Parents.empty())
474-
serializeReference(I.Parents, Obj, "Parents");
428+
serializeArray(I.Parents, Obj, "Parents", SerializeReferenceLambda);
475429

476430
if (!I.VirtualParents.empty())
477-
serializeReference(I.VirtualParents, Obj, "VirtualParents");
431+
serializeArray(I.VirtualParents, Obj, "VirtualParents",
432+
SerializeReferenceLambda);
478433

479434
if (I.Template)
480435
serializeInfo(I.Template.value(), Obj);
@@ -495,42 +450,23 @@ static void serializeInfo(const NamespaceInfo &I, json::Object &Obj,
495450
std::optional<StringRef> RepositoryUrl) {
496451
serializeCommonAttributes(I, Obj, RepositoryUrl);
497452

498-
if (!I.Children.Namespaces.empty()) {
499-
json::Value NamespacesArray = Array();
500-
auto &NamespacesArrayRef = *NamespacesArray.getAsArray();
501-
NamespacesArrayRef.reserve(I.Children.Namespaces.size());
502-
for (auto &Namespace : I.Children.Namespaces) {
503-
json::Value NamespaceVal = Object();
504-
auto &NamespaceObj = *NamespaceVal.getAsObject();
505-
serializeReference(Namespace, NamespaceObj);
506-
NamespacesArrayRef.push_back(NamespaceVal);
507-
}
508-
Obj["Namespaces"] = NamespacesArray;
509-
}
453+
if (!I.Children.Namespaces.empty())
454+
serializeArray(I.Children.Namespaces, Obj, "Namespaces",
455+
SerializeReferenceLambda);
510456

511-
auto SerializeInfo = [RepositoryUrl](const auto &Info, Object &Object) {
457+
static auto SerializeInfo = [RepositoryUrl](const auto &Info,
458+
Object &Object) {
512459
serializeInfo(Info, Object, RepositoryUrl);
513460
};
514461

515-
if (!I.Children.Functions.empty()) {
516-
json::Value FunctionsArray = Array();
517-
auto &FunctionsArrayRef = *FunctionsArray.getAsArray();
518-
FunctionsArrayRef.reserve(I.Children.Functions.size());
519-
for (const auto &Function : I.Children.Functions) {
520-
json::Value FunctionVal = Object();
521-
auto &FunctionObj = *FunctionVal.getAsObject();
522-
serializeInfo(Function, FunctionObj, RepositoryUrl);
523-
FunctionsArrayRef.push_back(FunctionVal);
524-
}
525-
Obj["Functions"] = FunctionsArray;
526-
}
462+
if (!I.Children.Functions.empty())
463+
serializeArray(I.Children.Functions, Obj, "Functions", SerializeInfo);
527464

528465
if (!I.Children.Concepts.empty())
529466
serializeArray(I.Children.Concepts, Obj, "Concepts", SerializeInfo);
530467

531-
if (!I.Children.Variables.empty()) {
468+
if (!I.Children.Variables.empty())
532469
serializeArray(I.Children.Variables, Obj, "Variables", SerializeInfo);
533-
}
534470

535471
serializeCommonChildren(I.Children, Obj, RepositoryUrl);
536472
}

0 commit comments

Comments
 (0)