@@ -161,15 +161,271 @@ Error MustacheHTMLGenerator::generateDocs(
161161 return Error::success ();
162162}
163163
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+
164375static json::Value extractValue (const NamespaceInfo &I,
165376 const ClangDocContext &CDCtx) {
166377 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);
167387 return NamespaceValue;
168388}
169389
170390static json::Value extractValue (const RecordInfo &I,
171391 const ClangDocContext &CDCtx) {
172392 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+
173429 return RecordValue;
174430}
175431
0 commit comments