Skip to content

Commit 0f109e9

Browse files
committed
add templates, use JSON values
1 parent cf3c931 commit 0f109e9

File tree

5 files changed

+211
-84
lines changed

5 files changed

+211
-84
lines changed

clang-tools-extra/clang-doc/JSONGenerator.cpp

Lines changed: 108 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -78,24 +78,24 @@ static json::Value serializeComment(const CommentInfo &Comment) {
7878

7979
static void serializeCommonAttributes(const Info &I, json::Object &Obj,
8080
std::optional<StringRef> RepositoryUrl) {
81-
Obj["Name"] = I.Name.str();
81+
Obj["Name"] = I.Name;
8282
Obj["USR"] = toHex(toStringRef(I.USR));
8383

8484
if (!I.Path.empty())
85-
Obj["Path"] = I.Path.str();
85+
Obj["Path"] = I.Path;
8686

8787
if (!I.Namespace.empty()) {
8888
Obj["Namespace"] = json::Array();
8989
for (const auto &NS : I.Namespace)
90-
Obj["Namespace"].getAsArray()->push_back(NS.Name.str());
90+
Obj["Namespace"].getAsArray()->push_back(NS.Name);
9191
}
9292

9393
if (!I.Description.empty()) {
9494
json::Value DescArray = json::Array();
9595
auto &DescArrayRef = *DescArray.getAsArray();
9696
for (const auto &Comment : I.Description)
9797
DescArrayRef.push_back(serializeComment(Comment));
98-
Obj["Description"] = std::move(DescArray);
98+
Obj["Description"] = DescArray;
9999
}
100100

101101
// Namespaces aren't SymbolInfos, so they dont have a DefLoc
@@ -115,19 +115,21 @@ static void serializeReference(const Reference &Ref, Object &ReferenceObj,
115115
ReferenceObj["Link"] = Path;
116116
ReferenceObj["Name"] = Ref.Name;
117117
ReferenceObj["QualName"] = Ref.QualName;
118-
ReferenceObj["ID"] = toHex(toStringRef(Ref.USR));
118+
ReferenceObj["USR"] = toHex(toStringRef(Ref.USR));
119119
}
120120

121-
static void serializeReference(Object &Obj, SmallVector<Reference, 4> References, std::string Key) {
121+
static void serializeReference(const SmallVector<Reference, 4> &References,
122+
Object &Obj, std::string Key) {
122123
json::Value ReferencesArray = Array();
123124
json::Array &ReferencesArrayRef = *ReferencesArray.getAsArray();
124125
for (const auto& Reference : References) {
125-
Object ReferenceObject = Object();
126+
json::Value ReferenceVal = Object();
127+
auto &ReferenceObj = *ReferenceVal.getAsObject();
126128
auto BasePath = Reference.getRelativeFilePath("");
127-
serializeReference(Reference, ReferenceObject, BasePath);
128-
ReferencesArrayRef.push_back(std::move(ReferenceObject));
129-
}
130-
Obj[Key] = std::move(ReferencesArray);
129+
serializeReference(Reference, ReferenceObj, BasePath);
130+
ReferencesArrayRef.push_back(ReferenceVal);
131+
}
132+
Obj[Key] = ReferencesArray;
131133
}
132134

133135
// Although namespaces and records both have ScopeChildren, they serialize them
@@ -139,41 +141,74 @@ static void serializeCommonChildren(const ScopeChildren &Children,
139141
json::Value EnumsArray = Array();
140142
auto &EnumsArrayRef = *EnumsArray.getAsArray();
141143
for (const auto &Enum : Children.Enums) {
142-
json::Object EnumObj;
144+
json::Value EnumVal = Object();
145+
auto &EnumObj = *EnumVal.getAsObject();
143146
serializeInfo(Enum, EnumObj, RepositoryUrl);
144-
EnumsArrayRef.push_back(std::move(EnumObj));
147+
EnumsArrayRef.push_back(EnumVal);
145148
}
146-
Obj["Enums"] = std::move(EnumsArray);
149+
Obj["Enums"] = EnumsArray;
147150
}
148151

149152
if (!Children.Typedefs.empty()) {
150153
json::Value TypedefsArray = Array();
151154
auto &TypedefsArrayRef = *TypedefsArray.getAsArray();
152155
for (const auto &Typedef : Children.Typedefs) {
153-
json::Object TypedefObj;
156+
json::Value TypedefVal = Object();
157+
auto &TypedefObj = *TypedefVal.getAsObject();
154158
serializeInfo(Typedef, TypedefObj, RepositoryUrl);
155-
TypedefsArrayRef.push_back(std::move(TypedefObj));
159+
TypedefsArrayRef.push_back(TypedefVal);
156160
}
157-
Obj["Typedefs"] = std::move(TypedefsArray);
161+
Obj["Typedefs"] = TypedefsArray;
158162
}
159163

160164
if (!Children.Records.empty()) {
161165
json::Value RecordsArray = Array();
162166
auto &RecordsArrayRef = *RecordsArray.getAsArray();
163167
for (const auto &Record : Children.Records) {
164-
json::Object RecordObj;
168+
json::Value RecordVal = Object();
169+
auto &RecordObj = *RecordVal.getAsObject();
165170
SmallString<64> BasePath = Record.getRelativeFilePath("");
166171
serializeReference(Record, RecordObj, BasePath);
167-
RecordsArrayRef.push_back(std::move(RecordObj));
172+
RecordsArrayRef.push_back(RecordVal);
168173
}
169-
Obj["Records"] = std::move(RecordsArray);
174+
Obj["Records"] = RecordsArray;
170175
}
171176
}
172177

178+
static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
179+
json::Value TemplateVal = Object();
180+
auto &TemplateObj = *TemplateVal.getAsObject();
181+
182+
if (Template.Specialization) {
183+
json::Value TemplateSpecializationVal = Object();
184+
auto &TemplateSpecializationObj = *TemplateSpecializationVal.getAsObject();
185+
TemplateSpecializationObj["SpecializationOf"] =
186+
toHex(toStringRef(Template.Specialization->SpecializationOf));
187+
if (!Template.Specialization->Params.empty()) {
188+
json::Value ParamsArray = Array();
189+
auto &ParamsArrayRef = *ParamsArray.getAsArray();
190+
for (const auto &Param : Template.Specialization->Params)
191+
ParamsArrayRef.push_back(Param.Contents);
192+
TemplateSpecializationObj["Parameters"] = ParamsArray;
193+
}
194+
TemplateObj["Specialization"] = TemplateSpecializationVal;
195+
}
196+
197+
if (!Template.Params.empty()) {
198+
json::Value ParamsArray = Array();
199+
auto &ParamsArrayRef = *ParamsArray.getAsArray();
200+
for (const auto &Param : Template.Params)
201+
ParamsArrayRef.push_back(Param.Contents);
202+
TemplateObj["Parameters"] = ParamsArray;
203+
}
204+
205+
Obj["Template"] = TemplateVal;
206+
}
207+
173208
static void serializeInfo(const TypeInfo &I, Object &Obj) {
174209
Obj["Name"] = I.Type.Name;
175210
Obj["QualName"] = I.Type.QualName;
176-
Obj["ID"] = toHex(toStringRef(I.Type.USR));
211+
Obj["USR"] = toHex(toStringRef(I.Type.USR));
177212
Obj["IsTemplate"] = I.IsTemplate;
178213
Obj["IsBuiltIn"] = I.IsBuiltIn;
179214
}
@@ -191,13 +226,17 @@ static void serializeInfo(const FunctionInfo &F, json::Object &Obj,
191226
json::Value ParamsArray = json::Array();
192227
auto &ParamsArrayRef = *ParamsArray.getAsArray();
193228
for (const auto &Param : F.Params) {
194-
json::Object ParamObj;
229+
json::Value ParamVal = Object();
230+
auto &ParamObj = *ParamVal.getAsObject();
195231
ParamObj["Name"] = Param.Name;
196232
ParamObj["Type"] = Param.Type.Name;
197-
ParamsArrayRef.push_back(std::move(ParamObj));
233+
ParamsArrayRef.push_back(ParamVal);
198234
}
199-
Obj["Params"] = std::move(ParamsArray);
235+
Obj["Params"] = ParamsArray;
200236
}
237+
238+
if (F.Template)
239+
serializeInfo(F.Template.value(), Obj);
201240
}
202241

203242
static void serializeInfo(const EnumInfo &I, json::Object &Obj,
@@ -206,26 +245,28 @@ static void serializeInfo(const EnumInfo &I, json::Object &Obj,
206245
Obj["Scoped"] = I.Scoped;
207246

208247
if (I.BaseType) {
209-
json::Object BaseTypeObj;
248+
json::Value BaseTypeVal = Object();
249+
auto &BaseTypeObj = *BaseTypeVal.getAsObject();
210250
BaseTypeObj["Name"] = I.BaseType->Type.Name;
211251
BaseTypeObj["QualName"] = I.BaseType->Type.QualName;
212-
BaseTypeObj["ID"] = toHex(toStringRef(I.BaseType->Type.USR));
213-
Obj["BaseType"] = std::move(BaseTypeObj);
252+
BaseTypeObj["USR"] = toHex(toStringRef(I.BaseType->Type.USR));
253+
Obj["BaseType"] = BaseTypeVal;
214254
}
215255

216256
if (!I.Members.empty()) {
217257
json::Value MembersArray = Array();
218258
auto &MembersArrayRef = *MembersArray.getAsArray();
219259
for (const auto &Member : I.Members) {
220-
json::Object MemberObj;
260+
json::Value MemberVal = Object();
261+
auto &MemberObj = *MemberVal.getAsObject();
221262
MemberObj["Name"] = Member.Name;
222263
if (!Member.ValueExpr.empty())
223264
MemberObj["ValueExpr"] = Member.ValueExpr;
224265
else
225266
MemberObj["Value"] = Member.Value;
226-
MembersArrayRef.push_back(std::move(MemberObj));
267+
MembersArrayRef.push_back(MemberVal);
227268
}
228-
Obj["Members"] = std::move(MembersArray);
269+
Obj["Members"] = MembersArray;
229270
}
230271
}
231272

@@ -234,82 +275,89 @@ static void serializeInfo(const TypedefInfo &I, json::Object &Obj,
234275
serializeCommonAttributes(I, Obj, RepositoryUrl);
235276
Obj["TypeDeclaration"] = I.TypeDeclaration;
236277
Obj["IsUsing"] = I.IsUsing;
237-
Object TypeObj = Object();
278+
json::Value TypeVal = Object();
279+
auto &TypeObj = *TypeVal.getAsObject();
238280
serializeInfo(I.Underlying, TypeObj);
239-
Obj["Underlying"] = std::move(TypeObj);
281+
Obj["Underlying"] = TypeVal;
240282
}
241283

242284
static void serializeInfo(const RecordInfo &I, json::Object &Obj,
243285
std::optional<StringRef> RepositoryUrl) {
244286
serializeCommonAttributes(I, Obj, RepositoryUrl);
245-
Obj["FullName"] = I.Name.str();
287+
Obj["FullName"] = I.FullName;
246288
Obj["TagType"] = getTagType(I.TagType);
247289
Obj["IsTypedef"] = I.IsTypeDef;
248290

249291
if (!I.Children.Functions.empty()) {
250-
json::Value PublicFunctionArr = Array();
251-
json::Array &PublicFunctionARef = *PublicFunctionArr.getAsArray();
252-
json::Value ProtectedFunctionArr = Array();
253-
json::Array &ProtectedFunctionARef = *ProtectedFunctionArr.getAsArray();
292+
json::Value PubFunctionsArray = Array();
293+
json::Array &PubFunctionsArrayRef = *PubFunctionsArray.getAsArray();
294+
json::Value ProtFunctionsArray = Array();
295+
json::Array &ProtFunctionsArrayRef = *ProtFunctionsArray.getAsArray();
254296

255297
for (const auto &Function : I.Children.Functions) {
256-
json::Object FunctionObj;
298+
json::Value FunctionVal = Object();
299+
auto &FunctionObj = *FunctionVal.getAsObject();
257300
serializeInfo(Function, FunctionObj, RepositoryUrl);
258301
AccessSpecifier Access = Function.Access;
259302
if (Access == AccessSpecifier::AS_public)
260-
PublicFunctionARef.push_back(std::move(FunctionObj));
303+
PubFunctionsArrayRef.push_back(FunctionVal);
261304
else if (Access == AccessSpecifier::AS_protected)
262-
ProtectedFunctionARef.push_back(std::move(FunctionObj));
305+
ProtFunctionsArrayRef.push_back(FunctionVal);
263306
}
264307

265-
if (!PublicFunctionARef.empty())
266-
Obj["PublicFunctions"] = std::move(PublicFunctionArr);
267-
if (!ProtectedFunctionARef.empty())
268-
Obj["ProtectedFunctions"] = std::move(ProtectedFunctionArr);
308+
if (!PubFunctionsArrayRef.empty())
309+
Obj["PublicFunctions"] = PubFunctionsArray;
310+
if (!ProtFunctionsArrayRef.empty())
311+
Obj["ProtectedFunctions"] = ProtFunctionsArray;
269312
}
270313

271314
if (!I.Members.empty()) {
272-
json::Value PublicMembers = Array();
273-
json::Array &PubMemberRef = *PublicMembers.getAsArray();
274-
json::Value ProtectedMembers = Array();
275-
json::Array &ProtMemberRef = *ProtectedMembers.getAsArray();
315+
json::Value PublicMembersArray = Array();
316+
json::Array &PubMembersArrayRef = *PublicMembersArray.getAsArray();
317+
json::Value ProtectedMembersArray = Array();
318+
json::Array &ProtMembersArrayRef = *ProtectedMembersArray.getAsArray();
276319

277320
for (const MemberTypeInfo &Member : I.Members) {
278-
json::Object MemberObj = Object();
321+
json::Value MemberVal = Object();
322+
auto &MemberObj = *MemberVal.getAsObject();
279323
MemberObj["Name"] = Member.Name;
280324
MemberObj["Type"] = Member.Type.Name;
281325

282326
if (Member.Access == AccessSpecifier::AS_public)
283-
PubMemberRef.push_back(std::move(MemberObj));
327+
PubMembersArrayRef.push_back(MemberVal);
284328
else if (Member.Access == AccessSpecifier::AS_protected)
285-
ProtMemberRef.push_back(std::move(MemberObj));
329+
ProtMembersArrayRef.push_back(MemberVal);
286330
}
287331

288-
if (!PubMemberRef.empty())
289-
Obj["PublicMembers"] = std::move(PublicMembers);
290-
if (!ProtMemberRef.empty())
291-
Obj["ProtectedMembers"] = std::move(ProtectedMembers);
332+
if (!PubMembersArrayRef.empty())
333+
Obj["PublicMembers"] = PublicMembersArray;
334+
if (!ProtMembersArrayRef.empty())
335+
Obj["ProtectedMembers"] = ProtectedMembersArray;
292336
}
293337

294338
if (!I.Bases.empty()) {
295339
json::Value BasesArray = Array();
296340
json::Array &BasesArrayRef = *BasesArray.getAsArray();
297341
for (const auto &BaseInfo : I.Bases) {
298-
Object BaseInfoObj = Object();
342+
json::Value BaseInfoVal = Object();
343+
auto &BaseInfoObj = *BaseInfoVal.getAsObject();
299344
serializeInfo(BaseInfo, BaseInfoObj, RepositoryUrl);
300345
BaseInfoObj["IsVirtual"] = BaseInfo.IsVirtual;
301346
BaseInfoObj["Access"] = getAccessSpelling(BaseInfo.Access);
302347
BaseInfoObj["IsParent"] = BaseInfo.IsParent;
303-
BasesArrayRef.push_back(std::move(BaseInfoObj));
348+
BasesArrayRef.push_back(BaseInfoVal);
304349
}
305-
Obj["Bases"] = std::move(BasesArray);
350+
Obj["Bases"] = BasesArray;
306351
}
307352

308353
if (!I.Parents.empty())
309-
serializeReference(Obj, I.Parents, "Parents");
354+
serializeReference(I.Parents, Obj, "Parents");
310355

311356
if (!I.VirtualParents.empty())
312-
serializeReference(Obj, I.VirtualParents, "VirtualParents");
357+
serializeReference(I.VirtualParents, Obj, "VirtualParents");
358+
359+
if (I.Template)
360+
serializeInfo(I.Template.value(), Obj);
313361

314362
serializeCommonChildren(I.Children, Obj, RepositoryUrl);
315363
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: rm -rf %t && mkdir -p %t
2+
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
3+
// RUN: FileCheck %s < %t/GlobalNamespace/MyClass.json
4+
5+
template<typename T> struct MyClass {
6+
T MemberTemplate;
7+
T method(T Param);
8+
};
9+
10+
// CHECK: "Name": "MyClass",
11+
// CHECK: "Name": "method",
12+
// CHECK: "Params": [
13+
// CHECK-NEXT: {
14+
// CHECK-NEXT: "Name": "Param",
15+
// CHECK-NEXT: "Type": "T"
16+
// CHECK-NEXT: }
17+
// CHECK-NEXT: ],
18+
// CHECK-NEXT: "ReturnType": {
19+
// CHECK-NEXT: "IsBuiltIn": false,
20+
// CHECK-NEXT: "IsTemplate": false,
21+
// CHECK-NEXT: "Name": "T",
22+
// CHECK-NEXT: "QualName": "T"
23+
// CHECK-NEXT: "USR": "0000000000000000000000000000000000000000"
24+
// CHECK: "Name": "MemberTemplate",
25+
// CHECK: "Type": "T"
26+
// CHECK: "Template": {
27+
// CHECK-NEXT: "Parameters": [
28+
// CHECK-NEXT: "typename T"
29+
// CHECK-NEXT: ]

0 commit comments

Comments
 (0)