Skip to content

Commit 066a14d

Browse files
authored
[clang-doc] refactor JSONGenerator array usage (#145595)
Improve code reuse by calling serializeArray in more generic cases instead of creating and reserving arrays on their own.
1 parent e0c7136 commit 066a14d

File tree

1 file changed

+99
-161
lines changed

1 file changed

+99
-161
lines changed

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

Lines changed: 99 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,31 @@ 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+
const 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

39-
static json::Object serializeLocation(const Location &Loc,
40-
std::optional<StringRef> RepositoryUrl) {
47+
static json::Object
48+
serializeLocation(const Location &Loc,
49+
const std::optional<StringRef> &RepositoryUrl) {
4150
Object LocationObj = Object();
4251
LocationObj["LineNumber"] = Loc.StartLineNumber;
4352
LocationObj["Filename"] = Loc.Filename;
@@ -159,8 +168,9 @@ static json::Value serializeComment(const CommentInfo &I) {
159168
llvm_unreachable("Unknown comment kind encountered.");
160169
}
161170

162-
static void serializeCommonAttributes(const Info &I, json::Object &Obj,
163-
std::optional<StringRef> RepositoryUrl) {
171+
static void
172+
serializeCommonAttributes(const Info &I, json::Object &Obj,
173+
const std::optional<StringRef> &RepositoryUrl) {
164174
Obj["Name"] = I.Name;
165175
Obj["USR"] = toHex(toStringRef(I.USR));
166176

@@ -198,67 +208,28 @@ static void serializeReference(const Reference &Ref, Object &ReferenceObj) {
198208
ReferenceObj["USR"] = toHex(toStringRef(Ref.USR));
199209
}
200210

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-
215211
// Although namespaces and records both have ScopeChildren, they serialize them
216212
// differently. Only enums, records, and typedefs are handled here.
217-
static void serializeCommonChildren(const ScopeChildren &Children,
218-
json::Object &Obj,
219-
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-
}
213+
static void
214+
serializeCommonChildren(const ScopeChildren &Children, json::Object &Obj,
215+
const std::optional<StringRef> &RepositoryUrl) {
216+
static auto SerializeInfo = [&RepositoryUrl](const auto &Info,
217+
Object &Object) {
218+
serializeInfo(Info, Object, RepositoryUrl);
219+
};
232220

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-
}
221+
if (!Children.Enums.empty())
222+
serializeArray(Children.Enums, Obj, "Enums", SerializeInfo);
245223

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-
}
224+
if (!Children.Typedefs.empty())
225+
serializeArray(Children.Typedefs, Obj, "Typedefs", SerializeInfo);
226+
227+
if (!Children.Records.empty())
228+
serializeArray(Children.Records, Obj, "Records", SerializeReferenceLambda);
258229
}
259230

260-
template <typename T, typename SerializationFunc>
261-
static void serializeArray(const std::vector<T> &Records, Object &Obj,
231+
template <typename Container, typename SerializationFunc>
232+
static void serializeArray(const Container &Records, Object &Obj,
262233
const std::string &Key,
263234
SerializationFunc SerializeInfo) {
264235
json::Value RecordsArray = Array();
@@ -278,6 +249,16 @@ static void serializeInfo(const ConstraintInfo &I, Object &Obj) {
278249
Obj["Expression"] = I.ConstraintExpr;
279250
}
280251

252+
static void serializeInfo(const ArrayRef<TemplateParamInfo> &Params,
253+
Object &Obj) {
254+
json::Value ParamsArray = Array();
255+
auto &ParamsArrayRef = *ParamsArray.getAsArray();
256+
ParamsArrayRef.reserve(Params.size());
257+
for (const auto &Param : Params)
258+
ParamsArrayRef.push_back(Param.Contents);
259+
Obj["Parameters"] = ParamsArray;
260+
}
261+
281262
static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
282263
json::Value TemplateVal = Object();
283264
auto &TemplateObj = *TemplateVal.getAsObject();
@@ -287,25 +268,13 @@ static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
287268
auto &TemplateSpecializationObj = *TemplateSpecializationVal.getAsObject();
288269
TemplateSpecializationObj["SpecializationOf"] =
289270
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-
}
271+
if (!Template.Specialization->Params.empty())
272+
serializeInfo(Template.Specialization->Params, TemplateSpecializationObj);
298273
TemplateObj["Specialization"] = TemplateSpecializationVal;
299274
}
300275

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-
}
276+
if (!Template.Params.empty())
277+
serializeInfo(Template.Params, TemplateObj);
309278

310279
if (!Template.Constraints.empty())
311280
serializeArray(Template.Constraints, TemplateObj, "Constraints",
@@ -315,7 +284,7 @@ static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
315284
}
316285

317286
static void serializeInfo(const ConceptInfo &I, Object &Obj,
318-
std::optional<StringRef> RepositoryUrl) {
287+
const std::optional<StringRef> &RepositoryUrl) {
319288
serializeCommonAttributes(I, Obj, RepositoryUrl);
320289
Obj["IsType"] = I.IsType;
321290
Obj["ConstraintExpression"] = I.ConstraintExpression;
@@ -330,35 +299,37 @@ static void serializeInfo(const TypeInfo &I, Object &Obj) {
330299
Obj["IsBuiltIn"] = I.IsBuiltIn;
331300
}
332301

302+
static void serializeInfo(const FieldTypeInfo &I, Object &Obj) {
303+
Obj["Name"] = I.Name;
304+
Obj["Type"] = I.Type.Name;
305+
}
306+
333307
static void serializeInfo(const FunctionInfo &F, json::Object &Obj,
334-
std::optional<StringRef> RepositoryURL) {
308+
const std::optional<StringRef> &RepositoryURL) {
335309
serializeCommonAttributes(F, Obj, RepositoryURL);
336310
Obj["IsStatic"] = F.IsStatic;
337311

338312
auto ReturnTypeObj = Object();
339313
serializeInfo(F.ReturnType, ReturnTypeObj);
340314
Obj["ReturnType"] = std::move(ReturnTypeObj);
341315

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-
}
316+
if (!F.Params.empty())
317+
serializeArray(F.Params, Obj, "Params", SerializeInfoLambda);
355318

356319
if (F.Template)
357320
serializeInfo(F.Template.value(), Obj);
358321
}
359322

323+
static void serializeInfo(const EnumValueInfo &I, Object &Obj) {
324+
Obj["Name"] = I.Name;
325+
if (!I.ValueExpr.empty())
326+
Obj["ValueExpr"] = I.ValueExpr;
327+
else
328+
Obj["Value"] = I.Value;
329+
}
330+
360331
static void serializeInfo(const EnumInfo &I, json::Object &Obj,
361-
std::optional<StringRef> RepositoryUrl) {
332+
const std::optional<StringRef> &RepositoryUrl) {
362333
serializeCommonAttributes(I, Obj, RepositoryUrl);
363334
Obj["Scoped"] = I.Scoped;
364335

@@ -371,26 +342,12 @@ static void serializeInfo(const EnumInfo &I, json::Object &Obj,
371342
Obj["BaseType"] = BaseTypeVal;
372343
}
373344

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-
}
345+
if (!I.Members.empty())
346+
serializeArray(I.Members, Obj, "Members", SerializeInfoLambda);
390347
}
391348

392349
static void serializeInfo(const TypedefInfo &I, json::Object &Obj,
393-
std::optional<StringRef> RepositoryUrl) {
350+
const std::optional<StringRef> &RepositoryUrl) {
394351
serializeCommonAttributes(I, Obj, RepositoryUrl);
395352
Obj["TypeDeclaration"] = I.TypeDeclaration;
396353
Obj["IsUsing"] = I.IsUsing;
@@ -400,8 +357,16 @@ static void serializeInfo(const TypedefInfo &I, json::Object &Obj,
400357
Obj["Underlying"] = TypeVal;
401358
}
402359

360+
static void serializeInfo(const BaseRecordInfo &I, Object &Obj,
361+
const std::optional<StringRef> &RepositoryUrl) {
362+
serializeInfo(static_cast<const RecordInfo &>(I), Obj, RepositoryUrl);
363+
Obj["IsVirtual"] = I.IsVirtual;
364+
Obj["Access"] = getAccessSpelling(I.Access);
365+
Obj["IsParent"] = I.IsParent;
366+
}
367+
403368
static void serializeInfo(const RecordInfo &I, json::Object &Obj,
404-
std::optional<StringRef> RepositoryUrl) {
369+
const std::optional<StringRef> &RepositoryUrl) {
405370
serializeCommonAttributes(I, Obj, RepositoryUrl);
406371
Obj["FullName"] = I.FullName;
407372
Obj["TagType"] = getTagType(I.TagType);
@@ -454,27 +419,19 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
454419
Obj["ProtectedMembers"] = ProtectedMembersArray;
455420
}
456421

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-
}
422+
if (!I.Bases.empty())
423+
serializeArray(
424+
I.Bases, Obj, "Bases",
425+
[&RepositoryUrl](const BaseRecordInfo &Base, Object &BaseObj) {
426+
serializeInfo(Base, BaseObj, RepositoryUrl);
427+
});
472428

473429
if (!I.Parents.empty())
474-
serializeReference(I.Parents, Obj, "Parents");
430+
serializeArray(I.Parents, Obj, "Parents", SerializeReferenceLambda);
475431

476432
if (!I.VirtualParents.empty())
477-
serializeReference(I.VirtualParents, Obj, "VirtualParents");
433+
serializeArray(I.VirtualParents, Obj, "VirtualParents",
434+
SerializeReferenceLambda);
478435

479436
if (I.Template)
480437
serializeInfo(I.Template.value(), Obj);
@@ -483,7 +440,7 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
483440
}
484441

485442
static void serializeInfo(const VarInfo &I, json::Object &Obj,
486-
std::optional<StringRef> RepositoryUrl) {
443+
const std::optional<StringRef> &RepositoryUrl) {
487444
serializeCommonAttributes(I, Obj, RepositoryUrl);
488445
Obj["IsStatic"] = I.IsStatic;
489446
auto TypeObj = Object();
@@ -492,45 +449,26 @@ static void serializeInfo(const VarInfo &I, json::Object &Obj,
492449
}
493450

494451
static void serializeInfo(const NamespaceInfo &I, json::Object &Obj,
495-
std::optional<StringRef> RepositoryUrl) {
452+
const std::optional<StringRef> &RepositoryUrl) {
496453
serializeCommonAttributes(I, Obj, RepositoryUrl);
497454

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-
}
455+
if (!I.Children.Namespaces.empty())
456+
serializeArray(I.Children.Namespaces, Obj, "Namespaces",
457+
SerializeReferenceLambda);
510458

511-
auto SerializeInfo = [RepositoryUrl](const auto &Info, Object &Object) {
459+
static auto SerializeInfo = [&RepositoryUrl](const auto &Info,
460+
Object &Object) {
512461
serializeInfo(Info, Object, RepositoryUrl);
513462
};
514463

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-
}
464+
if (!I.Children.Functions.empty())
465+
serializeArray(I.Children.Functions, Obj, "Functions", SerializeInfo);
527466

528467
if (!I.Children.Concepts.empty())
529468
serializeArray(I.Children.Concepts, Obj, "Concepts", SerializeInfo);
530469

531-
if (!I.Children.Variables.empty()) {
470+
if (!I.Children.Variables.empty())
532471
serializeArray(I.Children.Variables, Obj, "Variables", SerializeInfo);
533-
}
534472

535473
serializeCommonChildren(I.Children, Obj, RepositoryUrl);
536474
}

0 commit comments

Comments
 (0)