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