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