@@ -22,19 +22,27 @@ class JSONGenerator : public Generator {
2222
2323const  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);
2925static  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
3947static  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.
217211static  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+ 
281260static  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+ 
333305static  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+ 
360329static  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
392347static  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+ 
403366static  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