Bump version to 19.1.0git
[llvm-project.git] / clang-tools-extra / unittests / clang-doc / SerializeTest.cpp
blob5df42b9f5bca0b044f1c61cfe0d8757db779a01f
1 //===-- clang-doc/SerializeTest.cpp ---------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "Serialize.h"
10 #include "ClangDocTest.h"
11 #include "Representation.h"
12 #include "clang/AST/Comment.h"
13 #include "clang/AST/RecursiveASTVisitor.h"
14 #include "gtest/gtest.h"
16 namespace clang {
17 namespace doc {
19 class ClangDocSerializeTestVisitor
20 : public RecursiveASTVisitor<ClangDocSerializeTestVisitor> {
22 EmittedInfoList &EmittedInfos;
23 bool Public;
25 comments::FullComment *getComment(const NamedDecl *D) const {
26 if (RawComment *Comment =
27 D->getASTContext().getRawCommentForDeclNoCache(D)) {
28 Comment->setAttached();
29 return Comment->parse(D->getASTContext(), nullptr, D);
31 return nullptr;
34 public:
35 ClangDocSerializeTestVisitor(EmittedInfoList &EmittedInfos, bool Public)
36 : EmittedInfos(EmittedInfos), Public(Public) {}
38 template <typename T> bool mapDecl(const T *D) {
39 auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
40 /*File=*/"test.cpp", true, Public);
41 if (I.first)
42 EmittedInfos.emplace_back(std::move(I.first));
43 if (I.second)
44 EmittedInfos.emplace_back(std::move(I.second));
45 return true;
48 bool VisitNamespaceDecl(const NamespaceDecl *D) { return mapDecl(D); }
50 bool VisitFunctionDecl(const FunctionDecl *D) {
51 // Don't visit CXXMethodDecls twice
52 if (dyn_cast<CXXMethodDecl>(D))
53 return true;
54 return mapDecl(D);
57 bool VisitCXXMethodDecl(const CXXMethodDecl *D) { return mapDecl(D); }
59 bool VisitRecordDecl(const RecordDecl *D) { return mapDecl(D); }
61 bool VisitEnumDecl(const EnumDecl *D) { return mapDecl(D); }
63 bool VisitTypedefDecl(const TypedefDecl *D) { return mapDecl(D); }
65 bool VisitTypeAliasDecl(const TypeAliasDecl *D) { return mapDecl(D); }
68 void ExtractInfosFromCode(StringRef Code, size_t NumExpectedInfos, bool Public,
69 EmittedInfoList &EmittedInfos) {
70 auto ASTUnit = clang::tooling::buildASTFromCode(Code);
71 auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
72 ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
73 Visitor.TraverseTranslationUnitDecl(TU);
74 ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
77 void ExtractInfosFromCodeWithArgs(StringRef Code, size_t NumExpectedInfos,
78 bool Public, EmittedInfoList &EmittedInfos,
79 std::vector<std::string> &Args) {
80 auto ASTUnit = clang::tooling::buildASTFromCodeWithArgs(Code, Args);
81 auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
82 ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
83 Visitor.TraverseTranslationUnitDecl(TU);
84 ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
87 // Constructs a comment definition as the parser would for one comment line.
88 /* TODO uncomment this when the missing comment is fixed in emitRecordInfo and
89 the code that calls this is re-enabled.
90 CommentInfo MakeOneLineCommentInfo(const std::string &Text) {
91 CommentInfo TopComment;
92 TopComment.Kind = "FullComment";
93 TopComment.Children.emplace_back(std::make_unique<CommentInfo>());
95 CommentInfo *Brief = TopComment.Children.back().get();
96 Brief->Kind = "ParagraphComment";
98 Brief->Children.emplace_back(std::make_unique<CommentInfo>());
99 Brief->Children.back()->Kind = "TextComment";
100 Brief->Children.back()->Name = "ParagraphComment";
101 Brief->Children.back()->Text = Text;
103 return TopComment;
107 // Test serialization of namespace declarations.
108 TEST(SerializeTest, emitNamespaceInfo) {
109 EmittedInfoList Infos;
110 ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 5,
111 /*Public=*/false, Infos);
113 NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
114 NamespaceInfo ExpectedA(EmptySID, "A");
115 CheckNamespaceInfo(&ExpectedA, A);
117 NamespaceInfo *B = InfoAsNamespace(Infos[2].get());
118 NamespaceInfo ExpectedB(EmptySID, /*Name=*/"B", /*Path=*/"A");
119 ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
120 CheckNamespaceInfo(&ExpectedB, B);
122 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4].get());
123 NamespaceInfo ExpectedBWithFunction(EmptySID);
124 FunctionInfo F;
125 F.Name = "f";
126 F.ReturnType = TypeInfo("void");
127 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
128 F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
129 F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
130 F.Access = AccessSpecifier::AS_none;
131 ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
132 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
135 TEST(SerializeTest, emitAnonymousNamespaceInfo) {
136 EmittedInfoList Infos;
137 ExtractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos);
139 NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
140 NamespaceInfo ExpectedA(EmptySID);
141 ExpectedA.Name = "@nonymous_namespace";
142 CheckNamespaceInfo(&ExpectedA, A);
145 // Test serialization of record declarations.
146 TEST(SerializeTest, emitRecordInfo) {
147 EmittedInfoList Infos;
148 ExtractInfosFromCode(R"raw(class E {
149 public:
150 E() {}
152 // Some docs.
153 int value;
154 protected:
155 void ProtectedMethod();
157 template <typename T>
158 struct F {
159 void TemplateMethod();
161 template <>
162 void F<int>::TemplateMethod();
163 typedef struct {} G;)raw",
164 10, /*Public=*/false, Infos);
166 RecordInfo *E = InfoAsRecord(Infos[0].get());
167 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
168 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
169 InfoType::IT_namespace);
170 ExpectedE.TagType = TagTypeKind::Class;
171 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
172 ExpectedE.Members.emplace_back(TypeInfo("int"), "value",
173 AccessSpecifier::AS_public);
174 // TODO the data member should have the docstring on it:
175 //ExpectedE.Members.back().Description.push_back(MakeOneLineCommentInfo(" Some docs"));
176 CheckRecordInfo(&ExpectedE, E);
178 RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2].get());
179 RecordInfo ExpectedRecordWithEConstructor(EmptySID);
180 FunctionInfo EConstructor;
181 EConstructor.Name = "E";
182 EConstructor.Parent = Reference(EmptySID, "E", InfoType::IT_record);
183 EConstructor.ReturnType = TypeInfo("void");
184 EConstructor.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
185 EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
186 EConstructor.Namespace.emplace_back(EmptySID, "GlobalNamespace",
187 InfoType::IT_namespace);
188 EConstructor.Access = AccessSpecifier::AS_public;
189 EConstructor.IsMethod = true;
190 ExpectedRecordWithEConstructor.Children.Functions.emplace_back(
191 std::move(EConstructor));
192 CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor);
194 RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3].get());
195 RecordInfo ExpectedRecordWithMethod(EmptySID);
196 FunctionInfo Method;
197 Method.Name = "ProtectedMethod";
198 Method.Parent = Reference(EmptySID, "E", InfoType::IT_record);
199 Method.ReturnType = TypeInfo("void");
200 Method.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
201 Method.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
202 Method.Namespace.emplace_back(EmptySID, "GlobalNamespace",
203 InfoType::IT_namespace);
204 Method.Access = AccessSpecifier::AS_protected;
205 Method.IsMethod = true;
206 ExpectedRecordWithMethod.Children.Functions.emplace_back(std::move(Method));
207 CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
209 RecordInfo *F = InfoAsRecord(Infos[4].get());
210 RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
211 ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
212 InfoType::IT_namespace);
213 ExpectedF.TagType = TagTypeKind::Struct;
214 ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
215 CheckRecordInfo(&ExpectedF, F);
217 RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6].get());
218 RecordInfo ExpectedRecordWithTemplateMethod(EmptySID);
219 FunctionInfo TemplateMethod;
220 TemplateMethod.Name = "TemplateMethod";
221 TemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record);
222 TemplateMethod.ReturnType = TypeInfo("void");
223 TemplateMethod.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
224 TemplateMethod.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
225 TemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
226 InfoType::IT_namespace);
227 TemplateMethod.Access = AccessSpecifier::AS_public;
228 TemplateMethod.IsMethod = true;
229 ExpectedRecordWithTemplateMethod.Children.Functions.emplace_back(
230 std::move(TemplateMethod));
231 CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod);
233 RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7].get());
234 RecordInfo ExpectedTemplatedRecord(EmptySID);
235 FunctionInfo SpecializedTemplateMethod;
236 SpecializedTemplateMethod.Name = "TemplateMethod";
237 SpecializedTemplateMethod.Parent =
238 Reference(EmptySID, "F", InfoType::IT_record);
239 SpecializedTemplateMethod.ReturnType = TypeInfo("void");
240 SpecializedTemplateMethod.Loc.emplace_back(0,
241 llvm::SmallString<16>{"test.cpp"});
242 SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "F",
243 InfoType::IT_record);
244 SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
245 InfoType::IT_namespace);
246 SpecializedTemplateMethod.Access = AccessSpecifier::AS_public;
247 SpecializedTemplateMethod.IsMethod = true;
248 ExpectedTemplatedRecord.Children.Functions.emplace_back(
249 std::move(SpecializedTemplateMethod));
250 CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord);
252 RecordInfo *G = InfoAsRecord(Infos[8].get());
253 RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
254 ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
255 InfoType::IT_namespace);
256 ExpectedG.TagType = TagTypeKind::Struct;
257 ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
258 ExpectedG.IsTypeDef = true;
259 CheckRecordInfo(&ExpectedG, G);
262 // Test serialization of enum declarations.
263 TEST(SerializeTest, emitEnumInfo) {
264 EmittedInfoList Infos;
265 ExtractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2,
266 /*Public=*/false, Infos);
268 NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get());
269 NamespaceInfo ExpectedNamespaceWithEnum(EmptySID);
270 EnumInfo E;
271 E.Name = "E";
272 E.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
273 E.Members.emplace_back("X", "0");
274 E.Members.emplace_back("Y", "1");
275 ExpectedNamespaceWithEnum.Children.Enums.emplace_back(std::move(E));
276 CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum);
278 NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get());
279 NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID);
280 EnumInfo G;
281 G.Name = "G";
282 G.Scoped = true;
283 G.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
284 G.Members.emplace_back("A", "0");
285 G.Members.emplace_back("B", "1");
286 ExpectedNamespaceWithScopedEnum.Children.Enums.emplace_back(std::move(G));
287 CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum);
290 TEST(SerializeTest, emitUndefinedRecordInfo) {
291 EmittedInfoList Infos;
292 ExtractInfosFromCode("class E;", 2, /*Public=*/false, Infos);
294 RecordInfo *E = InfoAsRecord(Infos[0].get());
295 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
296 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
297 InfoType::IT_namespace);
298 ExpectedE.TagType = TagTypeKind::Class;
299 ExpectedE.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
300 CheckRecordInfo(&ExpectedE, E);
303 TEST(SerializeTest, emitRecordMemberInfo) {
304 EmittedInfoList Infos;
305 ExtractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos);
307 RecordInfo *E = InfoAsRecord(Infos[0].get());
308 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
309 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
310 InfoType::IT_namespace);
311 ExpectedE.TagType = TagTypeKind::Struct;
312 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
313 ExpectedE.Members.emplace_back(TypeInfo("int"), "I",
314 AccessSpecifier::AS_public);
315 CheckRecordInfo(&ExpectedE, E);
318 TEST(SerializeTest, emitInternalRecordInfo) {
319 EmittedInfoList Infos;
320 ExtractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos);
322 RecordInfo *E = InfoAsRecord(Infos[0].get());
323 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
324 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
325 InfoType::IT_namespace);
326 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
327 ExpectedE.TagType = TagTypeKind::Class;
328 CheckRecordInfo(&ExpectedE, E);
330 RecordInfo *G = InfoAsRecord(Infos[2].get());
331 llvm::SmallString<128> ExpectedGPath("GlobalNamespace/E");
332 llvm::sys::path::native(ExpectedGPath);
333 RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/ExpectedGPath);
334 ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
335 ExpectedG.TagType = TagTypeKind::Class;
336 ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
337 ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
338 InfoType::IT_namespace);
339 CheckRecordInfo(&ExpectedG, G);
342 TEST(SerializeTest, emitPublicAnonymousNamespaceInfo) {
343 EmittedInfoList Infos;
344 ExtractInfosFromCode("namespace { class A; }", 0, /*Public=*/true, Infos);
347 TEST(SerializeTest, emitPublicFunctionInternalInfo) {
348 EmittedInfoList Infos;
349 ExtractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true,
350 Infos);
352 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
353 NamespaceInfo ExpectedBWithFunction(EmptySID);
354 FunctionInfo F;
355 F.Name = "F";
356 F.ReturnType = TypeInfo("int");
357 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
358 F.Access = AccessSpecifier::AS_none;
359 ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
360 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
363 TEST(SerializeTest, emitInlinedFunctionInfo) {
364 EmittedInfoList Infos;
365 ExtractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos);
367 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
368 NamespaceInfo ExpectedBWithFunction(EmptySID);
369 FunctionInfo F;
370 F.Name = "F";
371 F.ReturnType = TypeInfo("void");
372 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
373 F.Params.emplace_back(TypeInfo("int"), "I");
374 F.Access = AccessSpecifier::AS_none;
375 ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
376 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
379 TEST(SerializeTest, emitInheritedRecordInfo) {
380 EmittedInfoList Infos;
381 ExtractInfosFromCode(R"raw(class F { protected: void set(int N); };
382 class G { public: int get() { return 1; } protected: int I; };
383 class E : public F, virtual private G {};
384 class H : private E {};
385 template <typename T>
386 class I {} ;
387 class J : public I<int> {} ;)raw",
388 14, /*Public=*/false, Infos);
390 RecordInfo *F = InfoAsRecord(Infos[0].get());
391 RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
392 ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
393 InfoType::IT_namespace, "");
394 ExpectedF.TagType = TagTypeKind::Class;
395 ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
396 CheckRecordInfo(&ExpectedF, F);
398 RecordInfo *G = InfoAsRecord(Infos[3].get());
399 RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
400 ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
401 InfoType::IT_namespace);
402 ExpectedG.TagType = TagTypeKind::Class;
403 ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
404 ExpectedG.Members.emplace_back(TypeInfo("int"), "I",
405 AccessSpecifier::AS_protected);
406 CheckRecordInfo(&ExpectedG, G);
408 RecordInfo *E = InfoAsRecord(Infos[6].get());
409 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
410 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
411 InfoType::IT_namespace);
412 ExpectedE.Parents.emplace_back(EmptySID, /*Name=*/"F", InfoType::IT_record,
413 /*QualName=*/"", /*Path*=*/"GlobalNamespace");
414 ExpectedE.VirtualParents.emplace_back(EmptySID, /*Name=*/"G",
415 InfoType::IT_record, /*QualName=*/"G",
416 /*Path*=*/"GlobalNamespace");
417 ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"F",
418 /*Path=*/"GlobalNamespace", false,
419 AccessSpecifier::AS_public, true);
420 FunctionInfo FunctionSet;
421 FunctionSet.Name = "set";
422 FunctionSet.ReturnType = TypeInfo("void");
423 FunctionSet.Loc.emplace_back();
424 FunctionSet.Params.emplace_back(TypeInfo("int"), "N");
425 FunctionSet.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
426 FunctionSet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
427 InfoType::IT_namespace);
428 FunctionSet.Access = AccessSpecifier::AS_protected;
429 FunctionSet.IsMethod = true;
430 ExpectedE.Bases.back().Children.Functions.emplace_back(
431 std::move(FunctionSet));
432 ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"G",
433 /*Path=*/"GlobalNamespace", true,
434 AccessSpecifier::AS_private, true);
435 FunctionInfo FunctionGet;
436 FunctionGet.Name = "get";
437 FunctionGet.ReturnType = TypeInfo("int");
438 FunctionGet.DefLoc = Location();
439 FunctionGet.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
440 FunctionGet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
441 InfoType::IT_namespace);
442 FunctionGet.Access = AccessSpecifier::AS_private;
443 FunctionGet.IsMethod = true;
444 ExpectedE.Bases.back().Children.Functions.emplace_back(
445 std::move(FunctionGet));
446 ExpectedE.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
447 AccessSpecifier::AS_private);
448 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
449 ExpectedE.TagType = TagTypeKind::Class;
450 CheckRecordInfo(&ExpectedE, E);
452 RecordInfo *H = InfoAsRecord(Infos[8].get());
453 RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace");
454 ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace",
455 InfoType::IT_namespace);
456 ExpectedH.TagType = TagTypeKind::Class;
457 ExpectedH.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
458 ExpectedH.Parents.emplace_back(EmptySID, /*Name=*/"E", InfoType::IT_record,
459 /*QualName=*/"E", /*Path=*/"GlobalNamespace");
460 ExpectedH.VirtualParents.emplace_back(EmptySID, /*Name=*/"G",
461 InfoType::IT_record, /*QualName=*/"G",
462 /*Path=*/"GlobalNamespace");
463 ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"E",
464 /*Path=*/"GlobalNamespace", false,
465 AccessSpecifier::AS_private, true);
466 ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"F",
467 /*Path=*/"GlobalNamespace", false,
468 AccessSpecifier::AS_private, false);
469 FunctionInfo FunctionSetNew;
470 FunctionSetNew.Name = "set";
471 FunctionSetNew.ReturnType = TypeInfo("void");
472 FunctionSetNew.Loc.emplace_back();
473 FunctionSetNew.Params.emplace_back(TypeInfo("int"), "N");
474 FunctionSetNew.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
475 FunctionSetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
476 InfoType::IT_namespace);
477 FunctionSetNew.Access = AccessSpecifier::AS_private;
478 FunctionSetNew.IsMethod = true;
479 ExpectedH.Bases.back().Children.Functions.emplace_back(
480 std::move(FunctionSetNew));
481 ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"G",
482 /*Path=*/"GlobalNamespace", true,
483 AccessSpecifier::AS_private, false);
484 FunctionInfo FunctionGetNew;
485 FunctionGetNew.Name = "get";
486 FunctionGetNew.ReturnType = TypeInfo("int");
487 FunctionGetNew.DefLoc = Location();
488 FunctionGetNew.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
489 FunctionGetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
490 InfoType::IT_namespace);
491 FunctionGetNew.Access = AccessSpecifier::AS_private;
492 FunctionGetNew.IsMethod = true;
493 ExpectedH.Bases.back().Children.Functions.emplace_back(
494 std::move(FunctionGetNew));
495 ExpectedH.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
496 AccessSpecifier::AS_private);
497 CheckRecordInfo(&ExpectedH, H);
499 RecordInfo *I = InfoAsRecord(Infos[10].get());
500 RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace");
501 ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace",
502 InfoType::IT_namespace);
503 ExpectedI.TagType = TagTypeKind::Class;
504 ExpectedI.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
505 CheckRecordInfo(&ExpectedI, I);
507 RecordInfo *J = InfoAsRecord(Infos[12].get());
508 RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace");
509 ExpectedJ.Namespace.emplace_back(EmptySID, "GlobalNamespace",
510 InfoType::IT_namespace);
511 ExpectedJ.Parents.emplace_back(EmptySID, /*Name=*/"I<int>",
512 InfoType::IT_record);
513 ExpectedJ.Bases.emplace_back(EmptySID, /*Name=*/"I<int>",
514 /*Path=*/"GlobalNamespace", false,
515 AccessSpecifier::AS_public, true);
516 ExpectedJ.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
517 ExpectedJ.TagType = TagTypeKind::Class;
518 CheckRecordInfo(&ExpectedJ, J);
521 TEST(SerializeTest, emitModulePublicLFunctions) {
522 EmittedInfoList Infos;
523 std::vector<std::string> Args;
524 Args.push_back("-fmodules-ts");
525 ExtractInfosFromCodeWithArgs(R"raw(export module M;
526 int moduleFunction(int x, double d = 3.2 - 1.0);
527 static int staticModuleFunction(int x);
528 export double exportedModuleFunction(double y);)raw",
529 2, /*Public=*/true, Infos, Args);
531 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
532 NamespaceInfo ExpectedBWithFunction(EmptySID);
533 FunctionInfo F;
534 F.Name = "moduleFunction";
535 F.ReturnType = TypeInfo("int");
536 F.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
537 F.Params.emplace_back(TypeInfo("int"), "x");
538 F.Params.emplace_back(TypeInfo("double"), "d");
539 F.Params.back().DefaultValue = "3.2 - 1.0";
540 F.Access = AccessSpecifier::AS_none;
541 ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
542 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
544 NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get());
545 NamespaceInfo ExpectedBWithExportedFunction(EmptySID);
546 FunctionInfo ExportedF;
547 ExportedF.Name = "exportedModuleFunction";
548 ExportedF.ReturnType =
549 TypeInfo(Reference(EmptySID, "double", InfoType::IT_default));
550 ExportedF.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
551 ExportedF.Params.emplace_back(TypeInfo("double"), "y");
552 ExportedF.Access = AccessSpecifier::AS_none;
553 ExpectedBWithExportedFunction.Children.Functions.emplace_back(
554 std::move(ExportedF));
555 CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction);
558 // Test serialization of child records in namespaces and other records
559 TEST(SerializeTest, emitChildRecords) {
560 EmittedInfoList Infos;
561 ExtractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8,
562 /*Public=*/false, Infos);
564 NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
565 NamespaceInfo ExpectedParentA(EmptySID);
566 ExpectedParentA.Children.Records.emplace_back(
567 EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace");
568 CheckNamespaceInfo(&ExpectedParentA, ParentA);
570 RecordInfo *ParentB = InfoAsRecord(Infos[3].get());
571 RecordInfo ExpectedParentB(EmptySID);
572 llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A");
573 llvm::sys::path::native(ExpectedParentBPath);
574 ExpectedParentB.Children.Records.emplace_back(
575 EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath);
576 CheckRecordInfo(&ExpectedParentB, ParentB);
578 NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get());
579 NamespaceInfo ExpectedParentC(EmptySID);
580 ExpectedParentC.Children.Records.emplace_back(
581 EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace");
582 CheckNamespaceInfo(&ExpectedParentC, ParentC);
585 // Test serialization of child namespaces
586 TEST(SerializeTest, emitChildNamespaces) {
587 EmittedInfoList Infos;
588 ExtractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false,
589 Infos);
591 NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
592 NamespaceInfo ExpectedParentA(EmptySID);
593 ExpectedParentA.Children.Namespaces.emplace_back(EmptySID, "A",
594 InfoType::IT_namespace);
595 CheckNamespaceInfo(&ExpectedParentA, ParentA);
597 NamespaceInfo *ParentB = InfoAsNamespace(Infos[3].get());
598 NamespaceInfo ExpectedParentB(EmptySID);
599 ExpectedParentB.Children.Namespaces.emplace_back(
600 EmptySID, "B", InfoType::IT_namespace, "A::B", "A");
601 CheckNamespaceInfo(&ExpectedParentB, ParentB);
604 TEST(SerializeTests, emitTypedefs) {
605 EmittedInfoList Infos;
606 ExtractInfosFromCode("typedef int MyInt; using MyDouble = double;", 2,
607 /*Public=*/false, Infos);
609 // First info will be the global namespace with the typedef in it.
610 NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get());
611 ASSERT_EQ(1u, GlobalNS1->Children.Typedefs.size());
613 const TypedefInfo &FirstTD = GlobalNS1->Children.Typedefs[0];
614 EXPECT_EQ("MyInt", FirstTD.Name);
615 EXPECT_FALSE(FirstTD.IsUsing);
616 EXPECT_EQ("int", FirstTD.Underlying.Type.Name);
618 // The second will be another global namespace with the using in it (the
619 // global namespace is duplicated because the items haven't been merged at the
620 // serialization phase of processing).
621 NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get());
622 ASSERT_EQ(1u, GlobalNS2->Children.Typedefs.size());
624 // Second is the "using" typedef.
625 const TypedefInfo &SecondTD = GlobalNS2->Children.Typedefs[0];
626 EXPECT_EQ("MyDouble", SecondTD.Name);
627 EXPECT_TRUE(SecondTD.IsUsing);
628 EXPECT_EQ("double", SecondTD.Underlying.Type.Name);
631 TEST(SerializeTests, emitFunctionTemplate) {
632 EmittedInfoList Infos;
633 // A template and a specialization.
634 ExtractInfosFromCode("template<typename T = int> void GetFoo(T);\n"
635 "template<> void GetFoo<bool>(bool);",
637 /*Public=*/false, Infos);
639 // First info will be the global namespace.
640 NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get());
641 ASSERT_EQ(1u, GlobalNS1->Children.Functions.size());
643 const FunctionInfo &Func1 = GlobalNS1->Children.Functions[0];
644 EXPECT_EQ("GetFoo", Func1.Name);
645 ASSERT_TRUE(Func1.Template);
646 EXPECT_FALSE(Func1.Template->Specialization); // Not a specialization.
648 // Template parameter.
649 ASSERT_EQ(1u, Func1.Template->Params.size());
650 EXPECT_EQ("typename T = int", Func1.Template->Params[0].Contents);
652 // The second will be another global namespace with the function in it (the
653 // global namespace is duplicated because the items haven't been merged at the
654 // serialization phase of processing).
655 NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get());
656 ASSERT_EQ(1u, GlobalNS2->Children.Functions.size());
658 // This one is a template specialization.
659 const FunctionInfo &Func2 = GlobalNS2->Children.Functions[0];
660 EXPECT_EQ("GetFoo", Func2.Name);
661 ASSERT_TRUE(Func2.Template);
662 EXPECT_TRUE(Func2.Template->Params.empty()); // No template params.
663 ASSERT_TRUE(Func2.Template->Specialization);
665 // Specialization values.
666 ASSERT_EQ(1u, Func2.Template->Specialization->Params.size());
667 EXPECT_EQ("bool", Func2.Template->Specialization->Params[0].Contents);
668 EXPECT_EQ(Func1.USR, Func2.Template->Specialization->SpecializationOf);
671 TEST(SerializeTests, emitClassTemplate) {
672 EmittedInfoList Infos;
673 // This will generate 2x the number of infos: each Record will be followed by
674 // a copy of the global namespace containing it (this test checks the data
675 // pre-merge).
676 ExtractInfosFromCode(
677 "template<int I> class MyTemplate { int i[I]; };\n"
678 "template<> class MyTemplate<0> {};\n"
679 "template<typename T, int U = 1> class OtherTemplate {};\n"
680 "template<int U> class OtherTemplate<MyTemplate<0>, U> {};",
682 /*Public=*/false, Infos);
684 // First record.
685 const RecordInfo *Rec1 = InfoAsRecord(Infos[0].get());
686 EXPECT_EQ("MyTemplate", Rec1->Name);
687 ASSERT_TRUE(Rec1->Template);
688 EXPECT_FALSE(Rec1->Template->Specialization); // Not a specialization.
690 // First record template parameter.
691 ASSERT_EQ(1u, Rec1->Template->Params.size());
692 EXPECT_EQ("int I", Rec1->Template->Params[0].Contents);
694 // Second record.
695 const RecordInfo *Rec2 = InfoAsRecord(Infos[2].get());
696 EXPECT_EQ("MyTemplate", Rec2->Name);
697 ASSERT_TRUE(Rec2->Template);
698 EXPECT_TRUE(Rec2->Template->Params.empty()); // No template params.
699 ASSERT_TRUE(Rec2->Template->Specialization);
701 // Second record specialization values.
702 ASSERT_EQ(1u, Rec2->Template->Specialization->Params.size());
703 EXPECT_EQ("0", Rec2->Template->Specialization->Params[0].Contents);
704 EXPECT_EQ(Rec1->USR, Rec2->Template->Specialization->SpecializationOf);
706 // Third record.
707 const RecordInfo *Rec3 = InfoAsRecord(Infos[4].get());
708 EXPECT_EQ("OtherTemplate", Rec3->Name);
709 ASSERT_TRUE(Rec3->Template);
711 // Third record template parameters.
712 ASSERT_EQ(2u, Rec3->Template->Params.size());
713 EXPECT_EQ("typename T", Rec3->Template->Params[0].Contents);
714 EXPECT_EQ("int U = 1", Rec3->Template->Params[1].Contents);
716 // Fourth record.
717 const RecordInfo *Rec4 = InfoAsRecord(Infos[6].get());
718 EXPECT_EQ("OtherTemplate", Rec3->Name);
719 ASSERT_TRUE(Rec4->Template);
720 ASSERT_TRUE(Rec4->Template->Specialization);
722 // Fourth record template + specialization parameters.
723 ASSERT_EQ(1u, Rec4->Template->Params.size());
724 EXPECT_EQ("int U", Rec4->Template->Params[0].Contents);
725 ASSERT_EQ(2u, Rec4->Template->Specialization->Params.size());
726 EXPECT_EQ("MyTemplate<0>",
727 Rec4->Template->Specialization->Params[0].Contents);
728 EXPECT_EQ("U", Rec4->Template->Specialization->Params[1].Contents);
731 } // namespace doc
732 } // end namespace clang