@@ -163,15 +163,266 @@ Error MustacheHTMLGenerator::generateDocs(
163
163
return Error::success ();
164
164
}
165
165
166
+ static json::Value
167
+ extractValue (const Location &L,
168
+ std::optional<StringRef> RepositoryUrl = std::nullopt) {
169
+ Object Obj = Object ();
170
+ // Should there be Start/End line numbers?
171
+ Obj.insert ({" LineNumber" , L.StartLineNumber });
172
+ Obj.insert ({" Filename" , L.Filename });
173
+
174
+ if (!L.IsFileInRootDir || !RepositoryUrl) {
175
+ return Obj;
176
+ }
177
+ SmallString<128 > FileURL (*RepositoryUrl);
178
+ sys::path::append (FileURL, sys::path::Style ::posix, L.Filename );
179
+ FileURL += " #" + std::to_string (L.StartLineNumber );
180
+ Obj.insert ({" FileURL" , FileURL});
181
+
182
+ return Obj;
183
+ }
184
+
185
+ static json::Value extractValue (const Reference &I,
186
+ StringRef CurrentDirectory) {
187
+ SmallString<64 > Path = I.getRelativeFilePath (CurrentDirectory);
188
+ sys::path::append (Path, I.getFileBaseName () + " .html" );
189
+ sys::path::native (Path, sys::path::Style ::posix);
190
+ Object Obj = Object ();
191
+ Obj.insert ({" Link" , Path});
192
+ Obj.insert ({" Name" , I.Name });
193
+ Obj.insert ({" QualName" , I.QualName });
194
+ Obj.insert ({" ID" , toHex (toStringRef (I.USR ))});
195
+ return Obj;
196
+ }
197
+
198
+ static json::Value extractValue (const TypedefInfo &I) {
199
+ // Not Supported
200
+ return nullptr ;
201
+ }
202
+
203
+ static json::Value extractValue (const CommentInfo &I) {
204
+ assert ((I.Kind == " BlockCommandComment" || I.Kind == " FullComment" ||
205
+ I.Kind == " ParagraphComment" || I.Kind == " TextComment" ) &&
206
+ " Unknown Comment type in CommentInfo." );
207
+
208
+ Object Obj = Object ();
209
+ json::Value Child = Object ();
210
+
211
+ // TextComment has no children, so return it.
212
+ if (I.Kind == " TextComment" ) {
213
+ Obj.insert ({" TextComment" , I.Text });
214
+ return Obj;
215
+ }
216
+
217
+ // BlockCommandComment needs to generate a Command key.
218
+ if (I.Kind == " BlockCommandComment" ) {
219
+ Child.getAsObject ()->insert ({" Command" , I.Name });
220
+ }
221
+
222
+ // Use the same handling for everything else.
223
+ // Only valid for:
224
+ // - BlockCommandComment
225
+ // - FullComment
226
+ // - ParagraphComment
227
+ json::Value ChildArr = Array ();
228
+ auto &CARef = *ChildArr.getAsArray ();
229
+ CARef.reserve (I.Children .size ());
230
+ for (const auto &C : I.Children )
231
+ CARef.emplace_back (extractValue (*C));
232
+ Child.getAsObject ()->insert ({" Children" , ChildArr});
233
+ Obj.insert ({I.Kind , Child});
234
+
235
+ return Obj;
236
+ }
237
+
238
+ static void maybeInsertLocation (std::optional<Location> Loc,
239
+ const ClangDocContext &CDCtx, Object &Obj) {
240
+ if (!Loc)
241
+ return ;
242
+ Location L = *Loc;
243
+ Obj.insert ({" Location" , extractValue (L, CDCtx.RepositoryUrl )});
244
+ }
245
+
246
+ static void extractDescriptionFromInfo (ArrayRef<CommentInfo> Descriptions,
247
+ json::Object &EnumValObj) {
248
+ if (Descriptions.empty ())
249
+ return ;
250
+ json::Value ArrDesc = Array ();
251
+ json::Array &ADescRef = *ArrDesc.getAsArray ();
252
+ for (const CommentInfo &Child : Descriptions)
253
+ ADescRef.emplace_back (extractValue (Child));
254
+ EnumValObj.insert ({" EnumValueComments" , ArrDesc});
255
+ }
256
+
257
+ static json::Value extractValue (const FunctionInfo &I, StringRef ParentInfoDir,
258
+ const ClangDocContext &CDCtx) {
259
+ Object Obj = Object ();
260
+ Obj.insert ({" Name" , I.Name });
261
+ Obj.insert ({" ID" , toHex (toStringRef (I.USR ))});
262
+ Obj.insert ({" Access" , getAccessSpelling (I.Access ).str ()});
263
+ Obj.insert ({" ReturnType" , extractValue (I.ReturnType .Type , ParentInfoDir)});
264
+
265
+ json::Value ParamArr = Array ();
266
+ for (const auto Val : enumerate(I.Params )) {
267
+ json::Value V = Object ();
268
+ auto &VRef = *V.getAsObject ();
269
+ VRef.insert ({" Name" , Val.value ().Name });
270
+ VRef.insert ({" Type" , Val.value ().Type .Name });
271
+ VRef.insert ({" End" , Val.index () + 1 == I.Params .size ()});
272
+ ParamArr.getAsArray ()->emplace_back (V);
273
+ }
274
+ Obj.insert ({" Params" , ParamArr});
275
+
276
+ maybeInsertLocation (I.DefLoc , CDCtx, Obj);
277
+ return Obj;
278
+ }
279
+
280
+ static json::Value extractValue (const EnumInfo &I,
281
+ const ClangDocContext &CDCtx) {
282
+ Object Obj = Object ();
283
+ std::string EnumType = I.Scoped ? " enum class " : " enum " ;
284
+ EnumType += I.Name ;
285
+ bool HasComment = std::any_of (
286
+ I.Members .begin (), I.Members .end (),
287
+ [](const EnumValueInfo &M) { return !M.Description .empty (); });
288
+ Obj.insert ({" EnumName" , EnumType});
289
+ Obj.insert ({" HasComment" , HasComment});
290
+ Obj.insert ({" ID" , toHex (toStringRef (I.USR ))});
291
+ json::Value Arr = Array ();
292
+ json::Array &ARef = *Arr.getAsArray ();
293
+ for (const EnumValueInfo &M : I.Members ) {
294
+ json::Value EnumValue = Object ();
295
+ auto &EnumValObj = *EnumValue.getAsObject ();
296
+ EnumValObj.insert ({" Name" , M.Name });
297
+ if (!M.ValueExpr .empty ())
298
+ EnumValObj.insert ({" ValueExpr" , M.ValueExpr });
299
+ else
300
+ EnumValObj.insert ({" Value" , M.Value });
301
+
302
+ extractDescriptionFromInfo (M.Description , EnumValObj);
303
+ ARef.emplace_back (EnumValue);
304
+ }
305
+ Obj.insert ({" EnumValues" , Arr});
306
+
307
+ extractDescriptionFromInfo (I.Description , Obj);
308
+ maybeInsertLocation (I.DefLoc , CDCtx, Obj);
309
+
310
+ return Obj;
311
+ }
312
+
313
+ static void extractScopeChildren (const ScopeChildren &S, Object &Obj,
314
+ StringRef ParentInfoDir,
315
+ const ClangDocContext &CDCtx) {
316
+ json::Value ArrNamespace = Array ();
317
+ for (const Reference &Child : S.Namespaces )
318
+ ArrNamespace.getAsArray ()->emplace_back (extractValue (Child, ParentInfoDir));
319
+
320
+ if (!ArrNamespace.getAsArray ()->empty ())
321
+ Obj.insert ({" Namespace" , Object{{" Links" , ArrNamespace}}});
322
+
323
+ json::Value ArrRecord = Array ();
324
+ for (const Reference &Child : S.Records )
325
+ ArrRecord.getAsArray ()->emplace_back (extractValue (Child, ParentInfoDir));
326
+
327
+ if (!ArrRecord.getAsArray ()->empty ())
328
+ Obj.insert ({" Record" , Object{{" Links" , ArrRecord}}});
329
+
330
+ json::Value ArrFunction = Array ();
331
+ json::Value PublicFunction = Array ();
332
+ json::Value ProtectedFunction = Array ();
333
+ json::Value PrivateFunction = Array ();
334
+
335
+ for (const FunctionInfo &Child : S.Functions ) {
336
+ json::Value F = extractValue (Child, ParentInfoDir, CDCtx);
337
+ AccessSpecifier Access = Child.Access ;
338
+ if (Access == AccessSpecifier::AS_public)
339
+ PublicFunction.getAsArray ()->emplace_back (F);
340
+ else if (Access == AccessSpecifier::AS_protected)
341
+ ProtectedFunction.getAsArray ()->emplace_back (F);
342
+ else
343
+ ArrFunction.getAsArray ()->emplace_back (F);
344
+ }
345
+
346
+ if (!ArrFunction.getAsArray ()->empty ())
347
+ Obj.insert ({" Function" , Object{{" Obj" , ArrFunction}}});
348
+
349
+ if (!PublicFunction.getAsArray ()->empty ())
350
+ Obj.insert ({" PublicFunction" , Object{{" Obj" , PublicFunction}}});
351
+
352
+ if (!ProtectedFunction.getAsArray ()->empty ())
353
+ Obj.insert ({" ProtectedFunction" , Object{{" Obj" , ProtectedFunction}}});
354
+
355
+ json::Value ArrEnum = Array ();
356
+ auto &ArrEnumRef = *ArrEnum.getAsArray ();
357
+ for (const EnumInfo &Child : S.Enums )
358
+ ArrEnumRef.emplace_back (extractValue (Child, CDCtx));
359
+
360
+ if (!ArrEnumRef.empty ())
361
+ Obj.insert ({" Enums" , Object{{" Obj" , ArrEnum}}});
362
+
363
+ json::Value ArrTypedefs = Array ();
364
+ auto &ArrTypedefsRef = *ArrTypedefs.getAsArray ();
365
+ for (const TypedefInfo &Child : S.Typedefs )
366
+ ArrTypedefsRef.emplace_back (extractValue (Child));
367
+
368
+ if (!ArrTypedefsRef.empty ())
369
+ Obj.insert ({" Typedefs" , Object{{" Obj" , ArrTypedefs}}});
370
+ }
371
+
166
372
static json::Value extractValue (const NamespaceInfo &I,
167
373
const ClangDocContext &CDCtx) {
168
374
Object NamespaceValue = Object ();
375
+ std::string InfoTitle = I.Name .empty () ? " Global Namespace"
376
+ : (Twine (" namespace " ) + I.Name ).str ();
377
+
378
+ SmallString<64 > BasePath = I.getRelativeFilePath (" " );
379
+ NamespaceValue.insert ({" NamespaceTitle" , InfoTitle});
380
+ NamespaceValue.insert ({" NamespacePath" , BasePath});
381
+
382
+ extractDescriptionFromInfo (I.Description , NamespaceValue);
383
+ extractScopeChildren (I.Children , NamespaceValue, BasePath, CDCtx);
169
384
return NamespaceValue;
170
385
}
171
386
172
387
static json::Value extractValue (const RecordInfo &I,
173
388
const ClangDocContext &CDCtx) {
174
389
Object RecordValue = Object ();
390
+ extractDescriptionFromInfo (I.Description , RecordValue);
391
+ RecordValue.insert ({" Name" , I.Name });
392
+ RecordValue.insert ({" FullName" , I.FullName });
393
+ RecordValue.insert ({" RecordType" , getTagType (I.TagType )});
394
+
395
+ maybeInsertLocation (I.DefLoc , CDCtx, RecordValue);
396
+
397
+ StringRef BasePath = I.getRelativeFilePath (" " );
398
+ extractScopeChildren (I.Children , RecordValue, BasePath, CDCtx);
399
+ json::Value PublicMembers = Array ();
400
+ json::Array &PubMemberRef = *PublicMembers.getAsArray ();
401
+ json::Value ProtectedMembers = Array ();
402
+ json::Array &ProtMemberRef = *ProtectedMembers.getAsArray ();
403
+ json::Value PrivateMembers = Array ();
404
+ json::Array &PrivMemberRef = *PrivateMembers.getAsArray ();
405
+ for (const MemberTypeInfo &Member : I.Members ) {
406
+ json::Value MemberValue = Object ();
407
+ auto &MVRef = *MemberValue.getAsObject ();
408
+ MVRef.insert ({" Name" , Member.Name });
409
+ MVRef.insert ({" Type" , Member.Type .Name });
410
+ extractDescriptionFromInfo (Member.Description , MVRef);
411
+
412
+ if (Member.Access == AccessSpecifier::AS_public)
413
+ PubMemberRef.emplace_back (MemberValue);
414
+ else if (Member.Access == AccessSpecifier::AS_protected)
415
+ ProtMemberRef.emplace_back (MemberValue);
416
+ else if (Member.Access == AccessSpecifier::AS_private)
417
+ ProtMemberRef.emplace_back (MemberValue);
418
+ }
419
+ if (!PubMemberRef.empty ())
420
+ RecordValue.insert ({" PublicMembers" , Object{{" Obj" , PublicMembers}}});
421
+ if (!ProtMemberRef.empty ())
422
+ RecordValue.insert ({" ProtectedMembers" , Object{{" Obj" , ProtectedMembers}}});
423
+ if (!PrivMemberRef.empty ())
424
+ RecordValue.insert ({" PrivateMembers" , Object{{" Obj" , PrivateMembers}}});
425
+
175
426
return RecordValue;
176
427
}
177
428
0 commit comments