[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang-tools-extra / unittests / clang-doc / SerializeTest.cpp
blob187ea39b7fe60c45a51a95014a2055c7ada223e9
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); }
64 void ExtractInfosFromCode(StringRef Code, size_t NumExpectedInfos, bool Public,
65 EmittedInfoList &EmittedInfos) {
66 auto ASTUnit = clang::tooling::buildASTFromCode(Code);
67 auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
68 ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
69 Visitor.TraverseTranslationUnitDecl(TU);
70 ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
73 void ExtractInfosFromCodeWithArgs(StringRef Code, size_t NumExpectedInfos,
74 bool Public, EmittedInfoList &EmittedInfos,
75 std::vector<std::string> &Args) {
76 auto ASTUnit = clang::tooling::buildASTFromCodeWithArgs(Code, Args);
77 auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
78 ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
79 Visitor.TraverseTranslationUnitDecl(TU);
80 ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
83 // Constructs a comment definition as the parser would for one comment line.
84 /* TODO uncomment this when the missing comment is fixed in emitRecordInfo and
85 the code that calls this is re-enabled.
86 CommentInfo MakeOneLineCommentInfo(const std::string &Text) {
87 CommentInfo TopComment;
88 TopComment.Kind = "FullComment";
89 TopComment.Children.emplace_back(std::make_unique<CommentInfo>());
91 CommentInfo *Brief = TopComment.Children.back().get();
92 Brief->Kind = "ParagraphComment";
94 Brief->Children.emplace_back(std::make_unique<CommentInfo>());
95 Brief->Children.back()->Kind = "TextComment";
96 Brief->Children.back()->Name = "ParagraphComment";
97 Brief->Children.back()->Text = Text;
99 return TopComment;
103 // Test serialization of namespace declarations.
104 TEST(SerializeTest, emitNamespaceInfo) {
105 EmittedInfoList Infos;
106 ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 5,
107 /*Public=*/false, Infos);
109 NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
110 NamespaceInfo ExpectedA(EmptySID, "A");
111 CheckNamespaceInfo(&ExpectedA, A);
113 NamespaceInfo *B = InfoAsNamespace(Infos[2].get());
114 NamespaceInfo ExpectedB(EmptySID, /*Name=*/"B", /*Path=*/"A");
115 ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
116 CheckNamespaceInfo(&ExpectedB, B);
118 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4].get());
119 NamespaceInfo ExpectedBWithFunction(EmptySID);
120 FunctionInfo F;
121 F.Name = "f";
122 F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
123 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
124 F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
125 F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
126 F.Access = AccessSpecifier::AS_none;
127 ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
128 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
131 TEST(SerializeTest, emitAnonymousNamespaceInfo) {
132 EmittedInfoList Infos;
133 ExtractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos);
135 NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
136 NamespaceInfo ExpectedA(EmptySID);
137 ExpectedA.Name = "@nonymous_namespace";
138 CheckNamespaceInfo(&ExpectedA, A);
141 // Test serialization of record declarations.
142 TEST(SerializeTest, emitRecordInfo) {
143 EmittedInfoList Infos;
144 ExtractInfosFromCode(R"raw(class E {
145 public:
146 E() {}
148 // Some docs.
149 int value;
150 protected:
151 void ProtectedMethod();
153 template <typename T>
154 struct F {
155 void TemplateMethod();
157 template <>
158 void F<int>::TemplateMethod();
159 typedef struct {} G;)raw",
160 10, /*Public=*/false, Infos);
162 RecordInfo *E = InfoAsRecord(Infos[0].get());
163 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
164 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
165 InfoType::IT_namespace);
166 ExpectedE.TagType = TagTypeKind::TTK_Class;
167 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
168 ExpectedE.Members.emplace_back("int", "value", AccessSpecifier::AS_public);
169 // TODO the data member should have the docstring on it:
170 //ExpectedE.Members.back().Description.push_back(MakeOneLineCommentInfo(" Some docs"));
171 CheckRecordInfo(&ExpectedE, E);
173 RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2].get());
174 RecordInfo ExpectedRecordWithEConstructor(EmptySID);
175 FunctionInfo EConstructor;
176 EConstructor.Name = "E";
177 EConstructor.Parent = Reference(EmptySID, "E", InfoType::IT_record);
178 EConstructor.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
179 EConstructor.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
180 EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
181 EConstructor.Namespace.emplace_back(EmptySID, "GlobalNamespace",
182 InfoType::IT_namespace);
183 EConstructor.Access = AccessSpecifier::AS_public;
184 EConstructor.IsMethod = true;
185 ExpectedRecordWithEConstructor.ChildFunctions.emplace_back(
186 std::move(EConstructor));
187 CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor);
189 RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3].get());
190 RecordInfo ExpectedRecordWithMethod(EmptySID);
191 FunctionInfo Method;
192 Method.Name = "ProtectedMethod";
193 Method.Parent = Reference(EmptySID, "E", InfoType::IT_record);
194 Method.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
195 Method.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
196 Method.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
197 Method.Namespace.emplace_back(EmptySID, "GlobalNamespace",
198 InfoType::IT_namespace);
199 Method.Access = AccessSpecifier::AS_protected;
200 Method.IsMethod = true;
201 ExpectedRecordWithMethod.ChildFunctions.emplace_back(std::move(Method));
202 CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
204 RecordInfo *F = InfoAsRecord(Infos[4].get());
205 RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
206 ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
207 InfoType::IT_namespace);
208 ExpectedF.TagType = TagTypeKind::TTK_Struct;
209 ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
210 CheckRecordInfo(&ExpectedF, F);
212 RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6].get());
213 RecordInfo ExpectedRecordWithTemplateMethod(EmptySID);
214 FunctionInfo TemplateMethod;
215 TemplateMethod.Name = "TemplateMethod";
216 TemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record);
217 TemplateMethod.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
218 TemplateMethod.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
219 TemplateMethod.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
220 TemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
221 InfoType::IT_namespace);
222 TemplateMethod.Access = AccessSpecifier::AS_public;
223 TemplateMethod.IsMethod = true;
224 ExpectedRecordWithTemplateMethod.ChildFunctions.emplace_back(
225 std::move(TemplateMethod));
226 CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod);
228 RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7].get());
229 RecordInfo ExpectedTemplatedRecord(EmptySID);
230 FunctionInfo SpecializedTemplateMethod;
231 SpecializedTemplateMethod.Name = "TemplateMethod";
232 SpecializedTemplateMethod.Parent =
233 Reference(EmptySID, "F", InfoType::IT_record);
234 SpecializedTemplateMethod.ReturnType =
235 TypeInfo(EmptySID, "void", InfoType::IT_default);
236 SpecializedTemplateMethod.Loc.emplace_back(0,
237 llvm::SmallString<16>{"test.cpp"});
238 SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "F",
239 InfoType::IT_record);
240 SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
241 InfoType::IT_namespace);
242 SpecializedTemplateMethod.Access = AccessSpecifier::AS_public;
243 SpecializedTemplateMethod.IsMethod = true;
244 ExpectedTemplatedRecord.ChildFunctions.emplace_back(
245 std::move(SpecializedTemplateMethod));
246 CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord);
248 RecordInfo *G = InfoAsRecord(Infos[8].get());
249 RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
250 ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
251 InfoType::IT_namespace);
252 ExpectedG.TagType = TagTypeKind::TTK_Struct;
253 ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
254 ExpectedG.IsTypeDef = true;
255 CheckRecordInfo(&ExpectedG, G);
258 // Test serialization of enum declarations.
259 TEST(SerializeTest, emitEnumInfo) {
260 EmittedInfoList Infos;
261 ExtractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2,
262 /*Public=*/false, Infos);
264 NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get());
265 NamespaceInfo ExpectedNamespaceWithEnum(EmptySID);
266 EnumInfo E;
267 E.Name = "E";
268 E.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
269 E.Members.emplace_back("X");
270 E.Members.emplace_back("Y");
271 ExpectedNamespaceWithEnum.ChildEnums.emplace_back(std::move(E));
272 CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum);
274 NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get());
275 NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID);
276 EnumInfo G;
277 G.Name = "G";
278 G.Scoped = true;
279 G.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
280 G.Members.emplace_back("A");
281 G.Members.emplace_back("B");
282 ExpectedNamespaceWithScopedEnum.ChildEnums.emplace_back(std::move(G));
283 CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum);
286 TEST(SerializeTest, emitUndefinedRecordInfo) {
287 EmittedInfoList Infos;
288 ExtractInfosFromCode("class E;", 2, /*Public=*/false, Infos);
290 RecordInfo *E = InfoAsRecord(Infos[0].get());
291 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
292 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
293 InfoType::IT_namespace);
294 ExpectedE.TagType = TagTypeKind::TTK_Class;
295 ExpectedE.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
296 CheckRecordInfo(&ExpectedE, E);
299 TEST(SerializeTest, emitRecordMemberInfo) {
300 EmittedInfoList Infos;
301 ExtractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos);
303 RecordInfo *E = InfoAsRecord(Infos[0].get());
304 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
305 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
306 InfoType::IT_namespace);
307 ExpectedE.TagType = TagTypeKind::TTK_Struct;
308 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
309 ExpectedE.Members.emplace_back("int", "I", AccessSpecifier::AS_public);
310 CheckRecordInfo(&ExpectedE, E);
313 TEST(SerializeTest, emitInternalRecordInfo) {
314 EmittedInfoList Infos;
315 ExtractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos);
317 RecordInfo *E = InfoAsRecord(Infos[0].get());
318 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
319 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
320 InfoType::IT_namespace);
321 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
322 ExpectedE.TagType = TagTypeKind::TTK_Class;
323 CheckRecordInfo(&ExpectedE, E);
325 RecordInfo *G = InfoAsRecord(Infos[2].get());
326 llvm::SmallString<128> ExpectedGPath("GlobalNamespace/E");
327 llvm::sys::path::native(ExpectedGPath);
328 RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/ExpectedGPath);
329 ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
330 ExpectedG.TagType = TagTypeKind::TTK_Class;
331 ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
332 ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
333 InfoType::IT_namespace);
334 CheckRecordInfo(&ExpectedG, G);
337 TEST(SerializeTest, emitPublicAnonymousNamespaceInfo) {
338 EmittedInfoList Infos;
339 ExtractInfosFromCode("namespace { class A; }", 0, /*Public=*/true, Infos);
342 TEST(SerializeTest, emitPublicFunctionInternalInfo) {
343 EmittedInfoList Infos;
344 ExtractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true,
345 Infos);
347 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
348 NamespaceInfo ExpectedBWithFunction(EmptySID);
349 FunctionInfo F;
350 F.Name = "F";
351 F.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
352 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
353 F.Access = AccessSpecifier::AS_none;
354 ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
355 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
358 TEST(SerializeTest, emitInlinedFunctionInfo) {
359 EmittedInfoList Infos;
360 ExtractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos);
362 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
363 NamespaceInfo ExpectedBWithFunction(EmptySID);
364 FunctionInfo F;
365 F.Name = "F";
366 F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
367 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
368 F.Params.emplace_back("int", "I");
369 F.Access = AccessSpecifier::AS_none;
370 ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
371 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
374 TEST(SerializeTest, emitInheritedRecordInfo) {
375 EmittedInfoList Infos;
376 ExtractInfosFromCode(R"raw(class F { protected: void set(int N); };
377 class G { public: int get() { return 1; } protected: int I; };
378 class E : public F, virtual private G {};
379 class H : private E {};
380 template <typename T>
381 class I {} ;
382 class J : public I<int> {} ;)raw",
383 14, /*Public=*/false, Infos);
385 RecordInfo *F = InfoAsRecord(Infos[0].get());
386 RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
387 ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
388 InfoType::IT_namespace);
389 ExpectedF.TagType = TagTypeKind::TTK_Class;
390 ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
391 CheckRecordInfo(&ExpectedF, F);
393 RecordInfo *G = InfoAsRecord(Infos[3].get());
394 RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
395 ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
396 InfoType::IT_namespace);
397 ExpectedG.TagType = TagTypeKind::TTK_Class;
398 ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
399 ExpectedG.Members.emplace_back("int", "I", AccessSpecifier::AS_protected);
400 CheckRecordInfo(&ExpectedG, G);
402 RecordInfo *E = InfoAsRecord(Infos[6].get());
403 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
404 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
405 InfoType::IT_namespace);
406 ExpectedE.Parents.emplace_back(EmptySID, /*Name=*/"F", InfoType::IT_record,
407 /*Path*=*/"GlobalNamespace");
408 ExpectedE.VirtualParents.emplace_back(
409 EmptySID, /*Name=*/"G", InfoType::IT_record, /*Path*=*/"GlobalNamespace");
410 ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"F",
411 /*Path=*/"GlobalNamespace", false,
412 AccessSpecifier::AS_public, true);
413 FunctionInfo FunctionSet;
414 FunctionSet.Name = "set";
415 FunctionSet.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
416 FunctionSet.Loc.emplace_back();
417 FunctionSet.Params.emplace_back("int", "N");
418 FunctionSet.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
419 FunctionSet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
420 InfoType::IT_namespace);
421 FunctionSet.Access = AccessSpecifier::AS_protected;
422 FunctionSet.IsMethod = true;
423 ExpectedE.Bases.back().ChildFunctions.emplace_back(std::move(FunctionSet));
424 ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"G",
425 /*Path=*/"GlobalNamespace", true,
426 AccessSpecifier::AS_private, true);
427 FunctionInfo FunctionGet;
428 FunctionGet.Name = "get";
429 FunctionGet.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
430 FunctionGet.DefLoc = Location();
431 FunctionGet.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
432 FunctionGet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
433 InfoType::IT_namespace);
434 FunctionGet.Access = AccessSpecifier::AS_private;
435 FunctionGet.IsMethod = true;
436 ExpectedE.Bases.back().ChildFunctions.emplace_back(std::move(FunctionGet));
437 ExpectedE.Bases.back().Members.emplace_back("int", "I",
438 AccessSpecifier::AS_private);
439 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
440 ExpectedE.TagType = TagTypeKind::TTK_Class;
441 CheckRecordInfo(&ExpectedE, E);
443 RecordInfo *H = InfoAsRecord(Infos[8].get());
444 RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace");
445 ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace",
446 InfoType::IT_namespace);
447 ExpectedH.TagType = TagTypeKind::TTK_Class;
448 ExpectedH.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
449 ExpectedH.Parents.emplace_back(EmptySID, /*Name=*/"E", InfoType::IT_record,
450 /*Path=*/"GlobalNamespace");
451 ExpectedH.VirtualParents.emplace_back(
452 EmptySID, /*Name=*/"G", InfoType::IT_record, /*Path=*/"GlobalNamespace");
453 ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"E",
454 /*Path=*/"GlobalNamespace", false,
455 AccessSpecifier::AS_private, true);
456 ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"F",
457 /*Path=*/"GlobalNamespace", false,
458 AccessSpecifier::AS_private, false);
459 FunctionInfo FunctionSetNew;
460 FunctionSetNew.Name = "set";
461 FunctionSetNew.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
462 FunctionSetNew.Loc.emplace_back();
463 FunctionSetNew.Params.emplace_back("int", "N");
464 FunctionSetNew.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
465 FunctionSetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
466 InfoType::IT_namespace);
467 FunctionSetNew.Access = AccessSpecifier::AS_private;
468 FunctionSetNew.IsMethod = true;
469 ExpectedH.Bases.back().ChildFunctions.emplace_back(std::move(FunctionSetNew));
470 ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"G",
471 /*Path=*/"GlobalNamespace", true,
472 AccessSpecifier::AS_private, false);
473 FunctionInfo FunctionGetNew;
474 FunctionGetNew.Name = "get";
475 FunctionGetNew.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
476 FunctionGetNew.DefLoc = Location();
477 FunctionGetNew.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
478 FunctionGetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
479 InfoType::IT_namespace);
480 FunctionGetNew.Access = AccessSpecifier::AS_private;
481 FunctionGetNew.IsMethod = true;
482 ExpectedH.Bases.back().ChildFunctions.emplace_back(std::move(FunctionGetNew));
483 ExpectedH.Bases.back().Members.emplace_back("int", "I",
484 AccessSpecifier::AS_private);
485 CheckRecordInfo(&ExpectedH, H);
487 RecordInfo *I = InfoAsRecord(Infos[10].get());
488 RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace");
489 ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace",
490 InfoType::IT_namespace);
491 ExpectedI.TagType = TagTypeKind::TTK_Class;
492 ExpectedI.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
493 CheckRecordInfo(&ExpectedI, I);
495 RecordInfo *J = InfoAsRecord(Infos[12].get());
496 RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace");
497 ExpectedJ.Namespace.emplace_back(EmptySID, "GlobalNamespace",
498 InfoType::IT_namespace);
499 ExpectedJ.Parents.emplace_back(EmptySID, /*Name=*/"I<int>",
500 InfoType::IT_record);
501 ExpectedJ.Bases.emplace_back(EmptySID, /*Name=*/"I<int>",
502 /*Path=*/"GlobalNamespace", false,
503 AccessSpecifier::AS_public, true);
504 ExpectedJ.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
505 ExpectedJ.TagType = TagTypeKind::TTK_Class;
506 CheckRecordInfo(&ExpectedJ, J);
509 TEST(SerializeTest, emitModulePublicLFunctions) {
510 EmittedInfoList Infos;
511 std::vector<std::string> Args;
512 Args.push_back("-fmodules-ts");
513 ExtractInfosFromCodeWithArgs(R"raw(export module M;
514 int moduleFunction(int x);
515 static int staticModuleFunction(int x);
516 export double exportedModuleFunction(double y);)raw",
517 2, /*Public=*/true, Infos, Args);
519 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
520 NamespaceInfo ExpectedBWithFunction(EmptySID);
521 FunctionInfo F;
522 F.Name = "moduleFunction";
523 F.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
524 F.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
525 F.Params.emplace_back("int", "x");
526 F.Access = AccessSpecifier::AS_none;
527 ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
528 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
530 NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get());
531 NamespaceInfo ExpectedBWithExportedFunction(EmptySID);
532 FunctionInfo ExportedF;
533 ExportedF.Name = "exportedModuleFunction";
534 ExportedF.ReturnType = TypeInfo(EmptySID, "double", InfoType::IT_default);
535 ExportedF.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
536 ExportedF.Params.emplace_back("double", "y");
537 ExportedF.Access = AccessSpecifier::AS_none;
538 ExpectedBWithExportedFunction.ChildFunctions.emplace_back(
539 std::move(ExportedF));
540 CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction);
543 // Test serialization of child records in namespaces and other records
544 TEST(SerializeTest, emitChildRecords) {
545 EmittedInfoList Infos;
546 ExtractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8,
547 /*Public=*/false, Infos);
549 NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
550 NamespaceInfo ExpectedParentA(EmptySID);
551 ExpectedParentA.ChildRecords.emplace_back(EmptySID, "A", InfoType::IT_record,
552 "GlobalNamespace");
553 CheckNamespaceInfo(&ExpectedParentA, ParentA);
555 RecordInfo *ParentB = InfoAsRecord(Infos[3].get());
556 RecordInfo ExpectedParentB(EmptySID);
557 llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A");
558 llvm::sys::path::native(ExpectedParentBPath);
559 ExpectedParentB.ChildRecords.emplace_back(EmptySID, "B", InfoType::IT_record,
560 ExpectedParentBPath);
561 CheckRecordInfo(&ExpectedParentB, ParentB);
563 NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get());
564 NamespaceInfo ExpectedParentC(EmptySID);
565 ExpectedParentC.ChildRecords.emplace_back(EmptySID, "C", InfoType::IT_record,
566 "@nonymous_namespace");
567 CheckNamespaceInfo(&ExpectedParentC, ParentC);
570 // Test serialization of child namespaces
571 TEST(SerializeTest, emitChildNamespaces) {
572 EmittedInfoList Infos;
573 ExtractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false,
574 Infos);
576 NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
577 NamespaceInfo ExpectedParentA(EmptySID);
578 ExpectedParentA.ChildNamespaces.emplace_back(EmptySID, "A",
579 InfoType::IT_namespace);
580 CheckNamespaceInfo(&ExpectedParentA, ParentA);
582 NamespaceInfo *ParentB = InfoAsNamespace(Infos[3].get());
583 NamespaceInfo ExpectedParentB(EmptySID);
584 ExpectedParentB.ChildNamespaces.emplace_back(EmptySID, "B",
585 InfoType::IT_namespace, "A");
586 CheckNamespaceInfo(&ExpectedParentB, ParentB);
589 } // namespace doc
590 } // end namespace clang