@@ -22,22 +22,31 @@ 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+                           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+ 
281262static  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
317286static  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+ 
333307static  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+ 
360331static  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
392349static  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+ 
403368static  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
485442static  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
494451static  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