1 //===-- clang-doc/SerializeTest.cpp ---------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
19 class ClangDocSerializeTestVisitor
20 : public RecursiveASTVisitor
<ClangDocSerializeTestVisitor
> {
22 EmittedInfoList
&EmittedInfos
;
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
);
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
);
42 EmittedInfos
.emplace_back(std::move(I
.first
));
44 EmittedInfos
.emplace_back(std::move(I
.second
));
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
))
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;
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
);
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 {
151 void ProtectedMethod();
153 template <typename T>
155 void TemplateMethod();
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
);
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
);
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
);
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,
347 NamespaceInfo
*BWithFunction
= InfoAsNamespace(Infos
[0].get());
348 NamespaceInfo
ExpectedBWithFunction(EmptySID
);
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
);
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>
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
);
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
,
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,
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
);
590 } // end namespace clang