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