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