xref: /llvm-project/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp (revision 2b932bc111c0d96db7044b0a854d7ad763710df2)
168049b1aSJulie Hockett //===-- clang-doc/SerializeTest.cpp ---------------------------------------===//
268049b1aSJulie Hockett //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668049b1aSJulie Hockett //
768049b1aSJulie Hockett //===----------------------------------------------------------------------===//
868049b1aSJulie Hockett 
968049b1aSJulie Hockett #include "Serialize.h"
1068049b1aSJulie Hockett #include "ClangDocTest.h"
1168049b1aSJulie Hockett #include "Representation.h"
1268049b1aSJulie Hockett #include "clang/AST/Comment.h"
1368049b1aSJulie Hockett #include "clang/AST/RecursiveASTVisitor.h"
1468049b1aSJulie Hockett #include "gtest/gtest.h"
1568049b1aSJulie Hockett 
1668049b1aSJulie Hockett namespace clang {
1768049b1aSJulie Hockett namespace doc {
1868049b1aSJulie Hockett 
1968049b1aSJulie Hockett class ClangDocSerializeTestVisitor
2068049b1aSJulie Hockett     : public RecursiveASTVisitor<ClangDocSerializeTestVisitor> {
2168049b1aSJulie Hockett 
2268049b1aSJulie Hockett   EmittedInfoList &EmittedInfos;
2368049b1aSJulie Hockett   bool Public;
2468049b1aSJulie Hockett 
2568049b1aSJulie Hockett   comments::FullComment *getComment(const NamedDecl *D) const {
2668049b1aSJulie Hockett     if (RawComment *Comment =
2768049b1aSJulie Hockett             D->getASTContext().getRawCommentForDeclNoCache(D)) {
2868049b1aSJulie Hockett       Comment->setAttached();
2968049b1aSJulie Hockett       return Comment->parse(D->getASTContext(), nullptr, D);
3068049b1aSJulie Hockett     }
3168049b1aSJulie Hockett     return nullptr;
3268049b1aSJulie Hockett   }
3368049b1aSJulie Hockett 
3468049b1aSJulie Hockett public:
3568049b1aSJulie Hockett   ClangDocSerializeTestVisitor(EmittedInfoList &EmittedInfos, bool Public)
3668049b1aSJulie Hockett       : EmittedInfos(EmittedInfos), Public(Public) {}
3768049b1aSJulie Hockett 
38097aedc9SJulie Hockett   template <typename T> bool mapDecl(const T *D) {
3968049b1aSJulie Hockett     auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
40665e9676SDiego Astiazaran                                  /*File=*/"test.cpp", true, Public);
41097aedc9SJulie Hockett     if (I.first)
42097aedc9SJulie Hockett       EmittedInfos.emplace_back(std::move(I.first));
43097aedc9SJulie Hockett     if (I.second)
44097aedc9SJulie Hockett       EmittedInfos.emplace_back(std::move(I.second));
4568049b1aSJulie Hockett     return true;
4668049b1aSJulie Hockett   }
4768049b1aSJulie Hockett 
48097aedc9SJulie Hockett   bool VisitNamespaceDecl(const NamespaceDecl *D) { return mapDecl(D); }
49097aedc9SJulie Hockett 
5068049b1aSJulie Hockett   bool VisitFunctionDecl(const FunctionDecl *D) {
5168049b1aSJulie Hockett     // Don't visit CXXMethodDecls twice
5268049b1aSJulie Hockett     if (dyn_cast<CXXMethodDecl>(D))
5368049b1aSJulie Hockett       return true;
54097aedc9SJulie Hockett     return mapDecl(D);
5568049b1aSJulie Hockett   }
5668049b1aSJulie Hockett 
57097aedc9SJulie Hockett   bool VisitCXXMethodDecl(const CXXMethodDecl *D) { return mapDecl(D); }
5868049b1aSJulie Hockett 
59097aedc9SJulie Hockett   bool VisitRecordDecl(const RecordDecl *D) { return mapDecl(D); }
6068049b1aSJulie Hockett 
61097aedc9SJulie Hockett   bool VisitEnumDecl(const EnumDecl *D) { return mapDecl(D); }
6221fb70c6SBrett Wilson 
6321fb70c6SBrett Wilson   bool VisitTypedefDecl(const TypedefDecl *D) { return mapDecl(D); }
6421fb70c6SBrett Wilson 
6521fb70c6SBrett Wilson   bool VisitTypeAliasDecl(const TypeAliasDecl *D) { return mapDecl(D); }
6668049b1aSJulie Hockett };
6768049b1aSJulie Hockett 
6868049b1aSJulie Hockett void ExtractInfosFromCode(StringRef Code, size_t NumExpectedInfos, bool Public,
6968049b1aSJulie Hockett                           EmittedInfoList &EmittedInfos) {
7068049b1aSJulie Hockett   auto ASTUnit = clang::tooling::buildASTFromCode(Code);
7168049b1aSJulie Hockett   auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
7268049b1aSJulie Hockett   ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
7368049b1aSJulie Hockett   Visitor.TraverseTranslationUnitDecl(TU);
7468049b1aSJulie Hockett   ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
7568049b1aSJulie Hockett }
7668049b1aSJulie Hockett 
7768049b1aSJulie Hockett void ExtractInfosFromCodeWithArgs(StringRef Code, size_t NumExpectedInfos,
7868049b1aSJulie Hockett                                   bool Public, EmittedInfoList &EmittedInfos,
7968049b1aSJulie Hockett                                   std::vector<std::string> &Args) {
8068049b1aSJulie Hockett   auto ASTUnit = clang::tooling::buildASTFromCodeWithArgs(Code, Args);
8168049b1aSJulie Hockett   auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
8268049b1aSJulie Hockett   ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
8368049b1aSJulie Hockett   Visitor.TraverseTranslationUnitDecl(TU);
8468049b1aSJulie Hockett   ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
8568049b1aSJulie Hockett }
8668049b1aSJulie Hockett 
8799baa10fSBrett Wilson // Constructs a comment definition as the parser would for one comment line.
8899baa10fSBrett Wilson /* TODO uncomment this when the missing comment is fixed in emitRecordInfo and
8999baa10fSBrett Wilson    the code that calls this is re-enabled.
9099baa10fSBrett Wilson CommentInfo MakeOneLineCommentInfo(const std::string &Text) {
9199baa10fSBrett Wilson   CommentInfo TopComment;
9299baa10fSBrett Wilson   TopComment.Kind = "FullComment";
9399baa10fSBrett Wilson   TopComment.Children.emplace_back(std::make_unique<CommentInfo>());
9499baa10fSBrett Wilson 
9599baa10fSBrett Wilson   CommentInfo *Brief = TopComment.Children.back().get();
9699baa10fSBrett Wilson   Brief->Kind = "ParagraphComment";
9799baa10fSBrett Wilson 
9899baa10fSBrett Wilson   Brief->Children.emplace_back(std::make_unique<CommentInfo>());
9999baa10fSBrett Wilson   Brief->Children.back()->Kind = "TextComment";
10099baa10fSBrett Wilson   Brief->Children.back()->Name = "ParagraphComment";
10199baa10fSBrett Wilson   Brief->Children.back()->Text = Text;
10299baa10fSBrett Wilson 
10399baa10fSBrett Wilson   return TopComment;
10499baa10fSBrett Wilson }
10599baa10fSBrett Wilson */
10699baa10fSBrett Wilson 
10768049b1aSJulie Hockett // Test serialization of namespace declarations.
10868049b1aSJulie Hockett TEST(SerializeTest, emitNamespaceInfo) {
10968049b1aSJulie Hockett   EmittedInfoList Infos;
110097aedc9SJulie Hockett   ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 5,
11168049b1aSJulie Hockett                        /*Public=*/false, Infos);
11268049b1aSJulie Hockett 
11368049b1aSJulie Hockett   NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
11468049b1aSJulie Hockett   NamespaceInfo ExpectedA(EmptySID, "A");
11568049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedA, A);
11668049b1aSJulie Hockett 
117097aedc9SJulie Hockett   NamespaceInfo *B = InfoAsNamespace(Infos[2].get());
1186169a730SDiego Astiazaran   NamespaceInfo ExpectedB(EmptySID, /*Name=*/"B", /*Path=*/"A");
11968049b1aSJulie Hockett   ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
12068049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedB, B);
12168049b1aSJulie Hockett 
122097aedc9SJulie Hockett   NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4].get());
12368049b1aSJulie Hockett   NamespaceInfo ExpectedBWithFunction(EmptySID);
12468049b1aSJulie Hockett   FunctionInfo F;
12568049b1aSJulie Hockett   F.Name = "f";
1260afc6085SBrett Wilson   F.ReturnType = TypeInfo("void");
12768049b1aSJulie Hockett   F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
12868049b1aSJulie Hockett   F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
12968049b1aSJulie Hockett   F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
1306a29ae4bSDiego Astiazaran   F.Access = AccessSpecifier::AS_none;
13121fb70c6SBrett Wilson   ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
13268049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
13368049b1aSJulie Hockett }
13468049b1aSJulie Hockett 
13568049b1aSJulie Hockett TEST(SerializeTest, emitAnonymousNamespaceInfo) {
13668049b1aSJulie Hockett   EmittedInfoList Infos;
137097aedc9SJulie Hockett   ExtractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos);
13868049b1aSJulie Hockett 
13968049b1aSJulie Hockett   NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
14068049b1aSJulie Hockett   NamespaceInfo ExpectedA(EmptySID);
141d900ef0aSJulie Hockett   ExpectedA.Name = "@nonymous_namespace";
14268049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedA, A);
14368049b1aSJulie Hockett }
14468049b1aSJulie Hockett 
14568049b1aSJulie Hockett // Test serialization of record declarations.
14668049b1aSJulie Hockett TEST(SerializeTest, emitRecordInfo) {
14768049b1aSJulie Hockett   EmittedInfoList Infos;
14868049b1aSJulie Hockett   ExtractInfosFromCode(R"raw(class E {
14968049b1aSJulie Hockett public:
15068049b1aSJulie Hockett   E() {}
15199baa10fSBrett Wilson 
15299baa10fSBrett Wilson   // Some docs.
15399baa10fSBrett Wilson   int value;
15468049b1aSJulie Hockett protected:
15568049b1aSJulie Hockett   void ProtectedMethod();
156b1f01e27SJulie Hockett };
157b1f01e27SJulie Hockett template <typename T>
158b1f01e27SJulie Hockett struct F {
159b1f01e27SJulie Hockett   void TemplateMethod();
160b1f01e27SJulie Hockett };
161b1f01e27SJulie Hockett template <>
162b1f01e27SJulie Hockett void F<int>::TemplateMethod();
163b1f01e27SJulie Hockett typedef struct {} G;)raw",
164097aedc9SJulie Hockett                        10, /*Public=*/false, Infos);
16568049b1aSJulie Hockett 
16668049b1aSJulie Hockett   RecordInfo *E = InfoAsRecord(Infos[0].get());
167b46131e5SDiego Astiazaran   RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
168b46131e5SDiego Astiazaran   ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
169b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
170edd690b0SVlad Serebrennikov   ExpectedE.TagType = TagTypeKind::Class;
17168049b1aSJulie Hockett   ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
1720afc6085SBrett Wilson   ExpectedE.Members.emplace_back(TypeInfo("int"), "value",
1730afc6085SBrett Wilson                                  AccessSpecifier::AS_public);
17499baa10fSBrett Wilson   // TODO the data member should have the docstring on it:
17599baa10fSBrett Wilson   //ExpectedE.Members.back().Description.push_back(MakeOneLineCommentInfo(" Some docs"));
17668049b1aSJulie Hockett   CheckRecordInfo(&ExpectedE, E);
17768049b1aSJulie Hockett 
178097aedc9SJulie Hockett   RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2].get());
17968049b1aSJulie Hockett   RecordInfo ExpectedRecordWithEConstructor(EmptySID);
18068049b1aSJulie Hockett   FunctionInfo EConstructor;
18168049b1aSJulie Hockett   EConstructor.Name = "E";
18268049b1aSJulie Hockett   EConstructor.Parent = Reference(EmptySID, "E", InfoType::IT_record);
1830afc6085SBrett Wilson   EConstructor.ReturnType = TypeInfo("void");
18468049b1aSJulie Hockett   EConstructor.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
18568049b1aSJulie Hockett   EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
186b46131e5SDiego Astiazaran   EConstructor.Namespace.emplace_back(EmptySID, "GlobalNamespace",
187b46131e5SDiego Astiazaran                                       InfoType::IT_namespace);
18868049b1aSJulie Hockett   EConstructor.Access = AccessSpecifier::AS_public;
18968049b1aSJulie Hockett   EConstructor.IsMethod = true;
19021fb70c6SBrett Wilson   ExpectedRecordWithEConstructor.Children.Functions.emplace_back(
19168049b1aSJulie Hockett       std::move(EConstructor));
19268049b1aSJulie Hockett   CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor);
19368049b1aSJulie Hockett 
194097aedc9SJulie Hockett   RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3].get());
19568049b1aSJulie Hockett   RecordInfo ExpectedRecordWithMethod(EmptySID);
19668049b1aSJulie Hockett   FunctionInfo Method;
19768049b1aSJulie Hockett   Method.Name = "ProtectedMethod";
19868049b1aSJulie Hockett   Method.Parent = Reference(EmptySID, "E", InfoType::IT_record);
1990afc6085SBrett Wilson   Method.ReturnType = TypeInfo("void");
20068049b1aSJulie Hockett   Method.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
20168049b1aSJulie Hockett   Method.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
202b46131e5SDiego Astiazaran   Method.Namespace.emplace_back(EmptySID, "GlobalNamespace",
203b46131e5SDiego Astiazaran                                 InfoType::IT_namespace);
20468049b1aSJulie Hockett   Method.Access = AccessSpecifier::AS_protected;
20568049b1aSJulie Hockett   Method.IsMethod = true;
20621fb70c6SBrett Wilson   ExpectedRecordWithMethod.Children.Functions.emplace_back(std::move(Method));
20768049b1aSJulie Hockett   CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
208b1f01e27SJulie Hockett 
209097aedc9SJulie Hockett   RecordInfo *F = InfoAsRecord(Infos[4].get());
210b46131e5SDiego Astiazaran   RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
211b46131e5SDiego Astiazaran   ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
212b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
213edd690b0SVlad Serebrennikov   ExpectedF.TagType = TagTypeKind::Struct;
214b1f01e27SJulie Hockett   ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
215b1f01e27SJulie Hockett   CheckRecordInfo(&ExpectedF, F);
216b1f01e27SJulie Hockett 
217097aedc9SJulie Hockett   RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6].get());
218b1f01e27SJulie Hockett   RecordInfo ExpectedRecordWithTemplateMethod(EmptySID);
219b1f01e27SJulie Hockett   FunctionInfo TemplateMethod;
220b1f01e27SJulie Hockett   TemplateMethod.Name = "TemplateMethod";
221b1f01e27SJulie Hockett   TemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record);
2220afc6085SBrett Wilson   TemplateMethod.ReturnType = TypeInfo("void");
223b1f01e27SJulie Hockett   TemplateMethod.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
224b1f01e27SJulie Hockett   TemplateMethod.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
225b46131e5SDiego Astiazaran   TemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
226b46131e5SDiego Astiazaran                                         InfoType::IT_namespace);
227b1f01e27SJulie Hockett   TemplateMethod.Access = AccessSpecifier::AS_public;
228b1f01e27SJulie Hockett   TemplateMethod.IsMethod = true;
22921fb70c6SBrett Wilson   ExpectedRecordWithTemplateMethod.Children.Functions.emplace_back(
230b1f01e27SJulie Hockett       std::move(TemplateMethod));
231b1f01e27SJulie Hockett   CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod);
232b1f01e27SJulie Hockett 
233097aedc9SJulie Hockett   RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7].get());
234b1f01e27SJulie Hockett   RecordInfo ExpectedTemplatedRecord(EmptySID);
235b1f01e27SJulie Hockett   FunctionInfo SpecializedTemplateMethod;
236b1f01e27SJulie Hockett   SpecializedTemplateMethod.Name = "TemplateMethod";
237b1f01e27SJulie Hockett   SpecializedTemplateMethod.Parent =
238b1f01e27SJulie Hockett       Reference(EmptySID, "F", InfoType::IT_record);
2390afc6085SBrett Wilson   SpecializedTemplateMethod.ReturnType = TypeInfo("void");
240b1f01e27SJulie Hockett   SpecializedTemplateMethod.Loc.emplace_back(0,
241b1f01e27SJulie Hockett                                              llvm::SmallString<16>{"test.cpp"});
242b1f01e27SJulie Hockett   SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "F",
243b1f01e27SJulie Hockett                                                    InfoType::IT_record);
244b46131e5SDiego Astiazaran   SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
245b46131e5SDiego Astiazaran                                                    InfoType::IT_namespace);
246b1f01e27SJulie Hockett   SpecializedTemplateMethod.Access = AccessSpecifier::AS_public;
247b1f01e27SJulie Hockett   SpecializedTemplateMethod.IsMethod = true;
24821fb70c6SBrett Wilson   ExpectedTemplatedRecord.Children.Functions.emplace_back(
249b1f01e27SJulie Hockett       std::move(SpecializedTemplateMethod));
250b1f01e27SJulie Hockett   CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord);
251b1f01e27SJulie Hockett 
252097aedc9SJulie Hockett   RecordInfo *G = InfoAsRecord(Infos[8].get());
253b46131e5SDiego Astiazaran   RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
254b46131e5SDiego Astiazaran   ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
255b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
256edd690b0SVlad Serebrennikov   ExpectedG.TagType = TagTypeKind::Struct;
257b1f01e27SJulie Hockett   ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
258b1f01e27SJulie Hockett   ExpectedG.IsTypeDef = true;
259b1f01e27SJulie Hockett   CheckRecordInfo(&ExpectedG, G);
26068049b1aSJulie Hockett }
26168049b1aSJulie Hockett 
26268049b1aSJulie Hockett // Test serialization of enum declarations.
26368049b1aSJulie Hockett TEST(SerializeTest, emitEnumInfo) {
26468049b1aSJulie Hockett   EmittedInfoList Infos;
26568049b1aSJulie Hockett   ExtractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2,
26668049b1aSJulie Hockett                        /*Public=*/false, Infos);
26768049b1aSJulie Hockett 
26868049b1aSJulie Hockett   NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get());
26968049b1aSJulie Hockett   NamespaceInfo ExpectedNamespaceWithEnum(EmptySID);
27068049b1aSJulie Hockett   EnumInfo E;
27168049b1aSJulie Hockett   E.Name = "E";
27268049b1aSJulie Hockett   E.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
273eaa7b324SBrett Wilson   E.Members.emplace_back("X", "0");
274eaa7b324SBrett Wilson   E.Members.emplace_back("Y", "1");
27521fb70c6SBrett Wilson   ExpectedNamespaceWithEnum.Children.Enums.emplace_back(std::move(E));
27668049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum);
27768049b1aSJulie Hockett 
27868049b1aSJulie Hockett   NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get());
27968049b1aSJulie Hockett   NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID);
28068049b1aSJulie Hockett   EnumInfo G;
28168049b1aSJulie Hockett   G.Name = "G";
28268049b1aSJulie Hockett   G.Scoped = true;
28368049b1aSJulie Hockett   G.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
284eaa7b324SBrett Wilson   G.Members.emplace_back("A", "0");
285eaa7b324SBrett Wilson   G.Members.emplace_back("B", "1");
28621fb70c6SBrett Wilson   ExpectedNamespaceWithScopedEnum.Children.Enums.emplace_back(std::move(G));
28768049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum);
28868049b1aSJulie Hockett }
28968049b1aSJulie Hockett 
29068049b1aSJulie Hockett TEST(SerializeTest, emitUndefinedRecordInfo) {
29168049b1aSJulie Hockett   EmittedInfoList Infos;
292097aedc9SJulie Hockett   ExtractInfosFromCode("class E;", 2, /*Public=*/false, Infos);
29368049b1aSJulie Hockett 
29468049b1aSJulie Hockett   RecordInfo *E = InfoAsRecord(Infos[0].get());
295b46131e5SDiego Astiazaran   RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
296b46131e5SDiego Astiazaran   ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
297b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
298edd690b0SVlad Serebrennikov   ExpectedE.TagType = TagTypeKind::Class;
29968049b1aSJulie Hockett   ExpectedE.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
30068049b1aSJulie Hockett   CheckRecordInfo(&ExpectedE, E);
30168049b1aSJulie Hockett }
30268049b1aSJulie Hockett 
30368049b1aSJulie Hockett TEST(SerializeTest, emitRecordMemberInfo) {
30468049b1aSJulie Hockett   EmittedInfoList Infos;
305097aedc9SJulie Hockett   ExtractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos);
30668049b1aSJulie Hockett 
30768049b1aSJulie Hockett   RecordInfo *E = InfoAsRecord(Infos[0].get());
308b46131e5SDiego Astiazaran   RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
309b46131e5SDiego Astiazaran   ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
310b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
311edd690b0SVlad Serebrennikov   ExpectedE.TagType = TagTypeKind::Struct;
31268049b1aSJulie Hockett   ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
3130afc6085SBrett Wilson   ExpectedE.Members.emplace_back(TypeInfo("int"), "I",
3140afc6085SBrett Wilson                                  AccessSpecifier::AS_public);
31568049b1aSJulie Hockett   CheckRecordInfo(&ExpectedE, E);
31668049b1aSJulie Hockett }
31768049b1aSJulie Hockett 
31868049b1aSJulie Hockett TEST(SerializeTest, emitInternalRecordInfo) {
31968049b1aSJulie Hockett   EmittedInfoList Infos;
320097aedc9SJulie Hockett   ExtractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos);
32168049b1aSJulie Hockett 
32268049b1aSJulie Hockett   RecordInfo *E = InfoAsRecord(Infos[0].get());
323b46131e5SDiego Astiazaran   RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
324b46131e5SDiego Astiazaran   ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
325b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
32668049b1aSJulie Hockett   ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
327edd690b0SVlad Serebrennikov   ExpectedE.TagType = TagTypeKind::Class;
32868049b1aSJulie Hockett   CheckRecordInfo(&ExpectedE, E);
32968049b1aSJulie Hockett 
330097aedc9SJulie Hockett   RecordInfo *G = InfoAsRecord(Infos[2].get());
331b46131e5SDiego Astiazaran   llvm::SmallString<128> ExpectedGPath("GlobalNamespace/E");
332b46131e5SDiego Astiazaran   llvm::sys::path::native(ExpectedGPath);
333b46131e5SDiego Astiazaran   RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/ExpectedGPath);
33468049b1aSJulie Hockett   ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
335edd690b0SVlad Serebrennikov   ExpectedG.TagType = TagTypeKind::Class;
33668049b1aSJulie Hockett   ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
337b46131e5SDiego Astiazaran   ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
338b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
33968049b1aSJulie Hockett   CheckRecordInfo(&ExpectedG, G);
34068049b1aSJulie Hockett }
34168049b1aSJulie Hockett 
34268049b1aSJulie Hockett TEST(SerializeTest, emitPublicAnonymousNamespaceInfo) {
34368049b1aSJulie Hockett   EmittedInfoList Infos;
34468049b1aSJulie Hockett   ExtractInfosFromCode("namespace { class A; }", 0, /*Public=*/true, Infos);
34568049b1aSJulie Hockett }
34668049b1aSJulie Hockett 
34768049b1aSJulie Hockett TEST(SerializeTest, emitPublicFunctionInternalInfo) {
34868049b1aSJulie Hockett   EmittedInfoList Infos;
34968049b1aSJulie Hockett   ExtractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true,
35068049b1aSJulie Hockett                        Infos);
35168049b1aSJulie Hockett 
35268049b1aSJulie Hockett   NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
35368049b1aSJulie Hockett   NamespaceInfo ExpectedBWithFunction(EmptySID);
35468049b1aSJulie Hockett   FunctionInfo F;
35568049b1aSJulie Hockett   F.Name = "F";
3560afc6085SBrett Wilson   F.ReturnType = TypeInfo("int");
35768049b1aSJulie Hockett   F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
3586a29ae4bSDiego Astiazaran   F.Access = AccessSpecifier::AS_none;
35921fb70c6SBrett Wilson   ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
36068049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
36168049b1aSJulie Hockett }
36268049b1aSJulie Hockett 
36368049b1aSJulie Hockett TEST(SerializeTest, emitInlinedFunctionInfo) {
36468049b1aSJulie Hockett   EmittedInfoList Infos;
36568049b1aSJulie Hockett   ExtractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos);
36668049b1aSJulie Hockett 
36768049b1aSJulie Hockett   NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
36868049b1aSJulie Hockett   NamespaceInfo ExpectedBWithFunction(EmptySID);
36968049b1aSJulie Hockett   FunctionInfo F;
37068049b1aSJulie Hockett   F.Name = "F";
3710afc6085SBrett Wilson   F.ReturnType = TypeInfo("void");
37268049b1aSJulie Hockett   F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
3730afc6085SBrett Wilson   F.Params.emplace_back(TypeInfo("int"), "I");
3746a29ae4bSDiego Astiazaran   F.Access = AccessSpecifier::AS_none;
37521fb70c6SBrett Wilson   ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
37668049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
37768049b1aSJulie Hockett }
37868049b1aSJulie Hockett 
379ba3d595fSDiego Astiazaran TEST(SerializeTest, emitInheritedRecordInfo) {
38068049b1aSJulie Hockett   EmittedInfoList Infos;
381ba3d595fSDiego Astiazaran   ExtractInfosFromCode(R"raw(class F { protected: void set(int N); };
382ba3d595fSDiego Astiazaran class G { public: int get() { return 1; } protected: int I; };
383b1f01e27SJulie Hockett class E : public F, virtual private G {};
384ba3d595fSDiego Astiazaran class H : private E {};
385b1f01e27SJulie Hockett template <typename T>
386ba3d595fSDiego Astiazaran class I {} ;
387ba3d595fSDiego Astiazaran class J : public I<int> {} ;)raw",
388ba3d595fSDiego Astiazaran                        14, /*Public=*/false, Infos);
38968049b1aSJulie Hockett 
39068049b1aSJulie Hockett   RecordInfo *F = InfoAsRecord(Infos[0].get());
391b46131e5SDiego Astiazaran   RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
392b46131e5SDiego Astiazaran   ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
3934a68babdSBrett Wilson                                    InfoType::IT_namespace, "");
394edd690b0SVlad Serebrennikov   ExpectedF.TagType = TagTypeKind::Class;
39568049b1aSJulie Hockett   ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
39668049b1aSJulie Hockett   CheckRecordInfo(&ExpectedF, F);
39768049b1aSJulie Hockett 
398ba3d595fSDiego Astiazaran   RecordInfo *G = InfoAsRecord(Infos[3].get());
399b46131e5SDiego Astiazaran   RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
400b46131e5SDiego Astiazaran   ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
401b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
402edd690b0SVlad Serebrennikov   ExpectedG.TagType = TagTypeKind::Class;
40368049b1aSJulie Hockett   ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
4040afc6085SBrett Wilson   ExpectedG.Members.emplace_back(TypeInfo("int"), "I",
4050afc6085SBrett Wilson                                  AccessSpecifier::AS_protected);
40668049b1aSJulie Hockett   CheckRecordInfo(&ExpectedG, G);
40768049b1aSJulie Hockett 
408ba3d595fSDiego Astiazaran   RecordInfo *E = InfoAsRecord(Infos[6].get());
409b46131e5SDiego Astiazaran   RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
410b46131e5SDiego Astiazaran   ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
411b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
412b46131e5SDiego Astiazaran   ExpectedE.Parents.emplace_back(EmptySID, /*Name=*/"F", InfoType::IT_record,
4134a68babdSBrett Wilson                                  /*QualName=*/"", /*Path*=*/"GlobalNamespace");
4144a68babdSBrett Wilson   ExpectedE.VirtualParents.emplace_back(EmptySID, /*Name=*/"G",
4154a68babdSBrett Wilson                                         InfoType::IT_record, /*QualName=*/"G",
416b46131e5SDiego Astiazaran                                         /*Path*=*/"GlobalNamespace");
417b46131e5SDiego Astiazaran   ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"F",
418b46131e5SDiego Astiazaran                                /*Path=*/"GlobalNamespace", false,
419ba3d595fSDiego Astiazaran                                AccessSpecifier::AS_public, true);
420ba3d595fSDiego Astiazaran   FunctionInfo FunctionSet;
421ba3d595fSDiego Astiazaran   FunctionSet.Name = "set";
4220afc6085SBrett Wilson   FunctionSet.ReturnType = TypeInfo("void");
423ba3d595fSDiego Astiazaran   FunctionSet.Loc.emplace_back();
4240afc6085SBrett Wilson   FunctionSet.Params.emplace_back(TypeInfo("int"), "N");
425ba3d595fSDiego Astiazaran   FunctionSet.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
426b46131e5SDiego Astiazaran   FunctionSet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
427b46131e5SDiego Astiazaran                                      InfoType::IT_namespace);
428ba3d595fSDiego Astiazaran   FunctionSet.Access = AccessSpecifier::AS_protected;
429ba3d595fSDiego Astiazaran   FunctionSet.IsMethod = true;
43021fb70c6SBrett Wilson   ExpectedE.Bases.back().Children.Functions.emplace_back(
43121fb70c6SBrett Wilson       std::move(FunctionSet));
432b46131e5SDiego Astiazaran   ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"G",
433b46131e5SDiego Astiazaran                                /*Path=*/"GlobalNamespace", true,
434ba3d595fSDiego Astiazaran                                AccessSpecifier::AS_private, true);
435ba3d595fSDiego Astiazaran   FunctionInfo FunctionGet;
436ba3d595fSDiego Astiazaran   FunctionGet.Name = "get";
4370afc6085SBrett Wilson   FunctionGet.ReturnType = TypeInfo("int");
438ba3d595fSDiego Astiazaran   FunctionGet.DefLoc = Location();
439ba3d595fSDiego Astiazaran   FunctionGet.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
440b46131e5SDiego Astiazaran   FunctionGet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
441b46131e5SDiego Astiazaran                                      InfoType::IT_namespace);
442ba3d595fSDiego Astiazaran   FunctionGet.Access = AccessSpecifier::AS_private;
443ba3d595fSDiego Astiazaran   FunctionGet.IsMethod = true;
44421fb70c6SBrett Wilson   ExpectedE.Bases.back().Children.Functions.emplace_back(
44521fb70c6SBrett Wilson       std::move(FunctionGet));
4460afc6085SBrett Wilson   ExpectedE.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
447ba3d595fSDiego Astiazaran                                               AccessSpecifier::AS_private);
44868049b1aSJulie Hockett   ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
449edd690b0SVlad Serebrennikov   ExpectedE.TagType = TagTypeKind::Class;
45068049b1aSJulie Hockett   CheckRecordInfo(&ExpectedE, E);
451b1f01e27SJulie Hockett 
452ba3d595fSDiego Astiazaran   RecordInfo *H = InfoAsRecord(Infos[8].get());
453b46131e5SDiego Astiazaran   RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace");
454b46131e5SDiego Astiazaran   ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace",
455b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
456edd690b0SVlad Serebrennikov   ExpectedH.TagType = TagTypeKind::Class;
457b1f01e27SJulie Hockett   ExpectedH.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
458b46131e5SDiego Astiazaran   ExpectedH.Parents.emplace_back(EmptySID, /*Name=*/"E", InfoType::IT_record,
4594a68babdSBrett Wilson                                  /*QualName=*/"E", /*Path=*/"GlobalNamespace");
4604a68babdSBrett Wilson   ExpectedH.VirtualParents.emplace_back(EmptySID, /*Name=*/"G",
4614a68babdSBrett Wilson                                         InfoType::IT_record, /*QualName=*/"G",
462b46131e5SDiego Astiazaran                                         /*Path=*/"GlobalNamespace");
463b46131e5SDiego Astiazaran   ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"E",
464b46131e5SDiego Astiazaran                                /*Path=*/"GlobalNamespace", false,
465ba3d595fSDiego Astiazaran                                AccessSpecifier::AS_private, true);
466b46131e5SDiego Astiazaran   ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"F",
467b46131e5SDiego Astiazaran                                /*Path=*/"GlobalNamespace", false,
468ba3d595fSDiego Astiazaran                                AccessSpecifier::AS_private, false);
469ba3d595fSDiego Astiazaran   FunctionInfo FunctionSetNew;
470ba3d595fSDiego Astiazaran   FunctionSetNew.Name = "set";
4710afc6085SBrett Wilson   FunctionSetNew.ReturnType = TypeInfo("void");
472ba3d595fSDiego Astiazaran   FunctionSetNew.Loc.emplace_back();
4730afc6085SBrett Wilson   FunctionSetNew.Params.emplace_back(TypeInfo("int"), "N");
474ba3d595fSDiego Astiazaran   FunctionSetNew.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
475b46131e5SDiego Astiazaran   FunctionSetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
476b46131e5SDiego Astiazaran                                         InfoType::IT_namespace);
477ba3d595fSDiego Astiazaran   FunctionSetNew.Access = AccessSpecifier::AS_private;
478ba3d595fSDiego Astiazaran   FunctionSetNew.IsMethod = true;
47921fb70c6SBrett Wilson   ExpectedH.Bases.back().Children.Functions.emplace_back(
48021fb70c6SBrett Wilson       std::move(FunctionSetNew));
481b46131e5SDiego Astiazaran   ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"G",
482b46131e5SDiego Astiazaran                                /*Path=*/"GlobalNamespace", true,
483ba3d595fSDiego Astiazaran                                AccessSpecifier::AS_private, false);
484ba3d595fSDiego Astiazaran   FunctionInfo FunctionGetNew;
485ba3d595fSDiego Astiazaran   FunctionGetNew.Name = "get";
4860afc6085SBrett Wilson   FunctionGetNew.ReturnType = TypeInfo("int");
487ba3d595fSDiego Astiazaran   FunctionGetNew.DefLoc = Location();
488ba3d595fSDiego Astiazaran   FunctionGetNew.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
489b46131e5SDiego Astiazaran   FunctionGetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
490b46131e5SDiego Astiazaran                                         InfoType::IT_namespace);
491ba3d595fSDiego Astiazaran   FunctionGetNew.Access = AccessSpecifier::AS_private;
492ba3d595fSDiego Astiazaran   FunctionGetNew.IsMethod = true;
49321fb70c6SBrett Wilson   ExpectedH.Bases.back().Children.Functions.emplace_back(
49421fb70c6SBrett Wilson       std::move(FunctionGetNew));
4950afc6085SBrett Wilson   ExpectedH.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
496ba3d595fSDiego Astiazaran                                               AccessSpecifier::AS_private);
497b1f01e27SJulie Hockett   CheckRecordInfo(&ExpectedH, H);
498b1f01e27SJulie Hockett 
499ba3d595fSDiego Astiazaran   RecordInfo *I = InfoAsRecord(Infos[10].get());
500b46131e5SDiego Astiazaran   RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace");
501b46131e5SDiego Astiazaran   ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace",
502b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
503edd690b0SVlad Serebrennikov   ExpectedI.TagType = TagTypeKind::Class;
504ba3d595fSDiego Astiazaran   ExpectedI.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
505b1f01e27SJulie Hockett   CheckRecordInfo(&ExpectedI, I);
506ba3d595fSDiego Astiazaran 
507ba3d595fSDiego Astiazaran   RecordInfo *J = InfoAsRecord(Infos[12].get());
508b46131e5SDiego Astiazaran   RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace");
509b46131e5SDiego Astiazaran   ExpectedJ.Namespace.emplace_back(EmptySID, "GlobalNamespace",
510b46131e5SDiego Astiazaran                                    InfoType::IT_namespace);
511b46131e5SDiego Astiazaran   ExpectedJ.Parents.emplace_back(EmptySID, /*Name=*/"I<int>",
512b46131e5SDiego Astiazaran                                  InfoType::IT_record);
513b46131e5SDiego Astiazaran   ExpectedJ.Bases.emplace_back(EmptySID, /*Name=*/"I<int>",
514b46131e5SDiego Astiazaran                                /*Path=*/"GlobalNamespace", false,
515ba3d595fSDiego Astiazaran                                AccessSpecifier::AS_public, true);
516ba3d595fSDiego Astiazaran   ExpectedJ.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
517edd690b0SVlad Serebrennikov   ExpectedJ.TagType = TagTypeKind::Class;
518ba3d595fSDiego Astiazaran   CheckRecordInfo(&ExpectedJ, J);
51968049b1aSJulie Hockett }
52068049b1aSJulie Hockett 
52168049b1aSJulie Hockett TEST(SerializeTest, emitModulePublicLFunctions) {
52268049b1aSJulie Hockett   EmittedInfoList Infos;
52368049b1aSJulie Hockett   std::vector<std::string> Args;
52468049b1aSJulie Hockett   Args.push_back("-fmodules-ts");
52568049b1aSJulie Hockett   ExtractInfosFromCodeWithArgs(R"raw(export module M;
526e191086bSBrett Wilson int moduleFunction(int x, double d = 3.2 - 1.0);
52768049b1aSJulie Hockett static int staticModuleFunction(int x);
52868049b1aSJulie Hockett export double exportedModuleFunction(double y);)raw",
52968049b1aSJulie Hockett                                2, /*Public=*/true, Infos, Args);
53068049b1aSJulie Hockett 
53168049b1aSJulie Hockett   NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
53268049b1aSJulie Hockett   NamespaceInfo ExpectedBWithFunction(EmptySID);
53368049b1aSJulie Hockett   FunctionInfo F;
53468049b1aSJulie Hockett   F.Name = "moduleFunction";
5350afc6085SBrett Wilson   F.ReturnType = TypeInfo("int");
53668049b1aSJulie Hockett   F.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
5370afc6085SBrett Wilson   F.Params.emplace_back(TypeInfo("int"), "x");
5380afc6085SBrett Wilson   F.Params.emplace_back(TypeInfo("double"), "d");
539e191086bSBrett Wilson   F.Params.back().DefaultValue = "3.2 - 1.0";
5406a29ae4bSDiego Astiazaran   F.Access = AccessSpecifier::AS_none;
54121fb70c6SBrett Wilson   ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
54268049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
54368049b1aSJulie Hockett 
54468049b1aSJulie Hockett   NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get());
54568049b1aSJulie Hockett   NamespaceInfo ExpectedBWithExportedFunction(EmptySID);
54668049b1aSJulie Hockett   FunctionInfo ExportedF;
54768049b1aSJulie Hockett   ExportedF.Name = "exportedModuleFunction";
5480afc6085SBrett Wilson   ExportedF.ReturnType =
5490afc6085SBrett Wilson       TypeInfo(Reference(EmptySID, "double", InfoType::IT_default));
55068049b1aSJulie Hockett   ExportedF.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
5510afc6085SBrett Wilson   ExportedF.Params.emplace_back(TypeInfo("double"), "y");
5526a29ae4bSDiego Astiazaran   ExportedF.Access = AccessSpecifier::AS_none;
55321fb70c6SBrett Wilson   ExpectedBWithExportedFunction.Children.Functions.emplace_back(
55468049b1aSJulie Hockett       std::move(ExportedF));
55568049b1aSJulie Hockett   CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction);
55668049b1aSJulie Hockett }
55768049b1aSJulie Hockett 
558097aedc9SJulie Hockett // Test serialization of child records in namespaces and other records
559097aedc9SJulie Hockett TEST(SerializeTest, emitChildRecords) {
560097aedc9SJulie Hockett   EmittedInfoList Infos;
561097aedc9SJulie Hockett   ExtractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8,
562097aedc9SJulie Hockett                        /*Public=*/false, Infos);
563097aedc9SJulie Hockett 
564097aedc9SJulie Hockett   NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
565097aedc9SJulie Hockett   NamespaceInfo ExpectedParentA(EmptySID);
56621fb70c6SBrett Wilson   ExpectedParentA.Children.Records.emplace_back(
5674a68babdSBrett Wilson       EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace");
568097aedc9SJulie Hockett   CheckNamespaceInfo(&ExpectedParentA, ParentA);
569097aedc9SJulie Hockett 
570097aedc9SJulie Hockett   RecordInfo *ParentB = InfoAsRecord(Infos[3].get());
571097aedc9SJulie Hockett   RecordInfo ExpectedParentB(EmptySID);
572b46131e5SDiego Astiazaran   llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A");
573b46131e5SDiego Astiazaran   llvm::sys::path::native(ExpectedParentBPath);
57421fb70c6SBrett Wilson   ExpectedParentB.Children.Records.emplace_back(
5754a68babdSBrett Wilson       EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath);
576097aedc9SJulie Hockett   CheckRecordInfo(&ExpectedParentB, ParentB);
577097aedc9SJulie Hockett 
578097aedc9SJulie Hockett   NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get());
579097aedc9SJulie Hockett   NamespaceInfo ExpectedParentC(EmptySID);
58021fb70c6SBrett Wilson   ExpectedParentC.Children.Records.emplace_back(
5814a68babdSBrett Wilson       EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace");
582097aedc9SJulie Hockett   CheckNamespaceInfo(&ExpectedParentC, ParentC);
583097aedc9SJulie Hockett }
584097aedc9SJulie Hockett 
585097aedc9SJulie Hockett // Test serialization of child namespaces
586097aedc9SJulie Hockett TEST(SerializeTest, emitChildNamespaces) {
587097aedc9SJulie Hockett   EmittedInfoList Infos;
588097aedc9SJulie Hockett   ExtractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false,
589097aedc9SJulie Hockett                        Infos);
590097aedc9SJulie Hockett 
591097aedc9SJulie Hockett   NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
592097aedc9SJulie Hockett   NamespaceInfo ExpectedParentA(EmptySID);
59321fb70c6SBrett Wilson   ExpectedParentA.Children.Namespaces.emplace_back(EmptySID, "A",
594097aedc9SJulie Hockett                                                    InfoType::IT_namespace);
595097aedc9SJulie Hockett   CheckNamespaceInfo(&ExpectedParentA, ParentA);
596097aedc9SJulie Hockett 
597097aedc9SJulie Hockett   NamespaceInfo *ParentB = InfoAsNamespace(Infos[3].get());
598097aedc9SJulie Hockett   NamespaceInfo ExpectedParentB(EmptySID);
5994a68babdSBrett Wilson   ExpectedParentB.Children.Namespaces.emplace_back(
6004a68babdSBrett Wilson       EmptySID, "B", InfoType::IT_namespace, "A::B", "A");
601097aedc9SJulie Hockett   CheckNamespaceInfo(&ExpectedParentB, ParentB);
602097aedc9SJulie Hockett }
603097aedc9SJulie Hockett 
60421fb70c6SBrett Wilson TEST(SerializeTests, emitTypedefs) {
60521fb70c6SBrett Wilson   EmittedInfoList Infos;
60621fb70c6SBrett Wilson   ExtractInfosFromCode("typedef int MyInt; using MyDouble = double;", 2,
60721fb70c6SBrett Wilson                        /*Public=*/false, Infos);
60821fb70c6SBrett Wilson 
60921fb70c6SBrett Wilson   // First info will be the global namespace with the typedef in it.
61021fb70c6SBrett Wilson   NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get());
61121fb70c6SBrett Wilson   ASSERT_EQ(1u, GlobalNS1->Children.Typedefs.size());
61221fb70c6SBrett Wilson 
61321fb70c6SBrett Wilson   const TypedefInfo &FirstTD = GlobalNS1->Children.Typedefs[0];
61421fb70c6SBrett Wilson   EXPECT_EQ("MyInt", FirstTD.Name);
61521fb70c6SBrett Wilson   EXPECT_FALSE(FirstTD.IsUsing);
61621fb70c6SBrett Wilson   EXPECT_EQ("int", FirstTD.Underlying.Type.Name);
61721fb70c6SBrett Wilson 
61821fb70c6SBrett Wilson   // The second will be another global namespace with the using in it (the
61921fb70c6SBrett Wilson   // global namespace is duplicated because the items haven't been merged at the
62021fb70c6SBrett Wilson   // serialization phase of processing).
62121fb70c6SBrett Wilson   NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get());
62221fb70c6SBrett Wilson   ASSERT_EQ(1u, GlobalNS2->Children.Typedefs.size());
62321fb70c6SBrett Wilson 
62421fb70c6SBrett Wilson   // Second is the "using" typedef.
62521fb70c6SBrett Wilson   const TypedefInfo &SecondTD = GlobalNS2->Children.Typedefs[0];
62621fb70c6SBrett Wilson   EXPECT_EQ("MyDouble", SecondTD.Name);
62721fb70c6SBrett Wilson   EXPECT_TRUE(SecondTD.IsUsing);
62821fb70c6SBrett Wilson   EXPECT_EQ("double", SecondTD.Underlying.Type.Name);
62921fb70c6SBrett Wilson }
63021fb70c6SBrett Wilson 
6314a68babdSBrett Wilson TEST(SerializeTests, emitFunctionTemplate) {
6324a68babdSBrett Wilson   EmittedInfoList Infos;
6334a68babdSBrett Wilson   // A template and a specialization.
634*2b932bc1SPaul Kirth   ExtractInfosFromCode("template<typename T = int> bool GetFoo(T);\n"
635*2b932bc1SPaul Kirth                        "template<> bool GetFoo<bool>(bool);",
6364a68babdSBrett Wilson                        2,
6374a68babdSBrett Wilson                        /*Public=*/false, Infos);
6384a68babdSBrett Wilson 
6394a68babdSBrett Wilson   // First info will be the global namespace.
6404a68babdSBrett Wilson   NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get());
6414a68babdSBrett Wilson   ASSERT_EQ(1u, GlobalNS1->Children.Functions.size());
6424a68babdSBrett Wilson 
6434a68babdSBrett Wilson   const FunctionInfo &Func1 = GlobalNS1->Children.Functions[0];
6444a68babdSBrett Wilson   EXPECT_EQ("GetFoo", Func1.Name);
6454a68babdSBrett Wilson   ASSERT_TRUE(Func1.Template);
6464a68babdSBrett Wilson   EXPECT_FALSE(Func1.Template->Specialization); // Not a specialization.
6474a68babdSBrett Wilson 
6484a68babdSBrett Wilson   // Template parameter.
6494a68babdSBrett Wilson   ASSERT_EQ(1u, Func1.Template->Params.size());
6504a68babdSBrett Wilson   EXPECT_EQ("typename T = int", Func1.Template->Params[0].Contents);
6514a68babdSBrett Wilson 
6524a68babdSBrett Wilson   // The second will be another global namespace with the function in it (the
6534a68babdSBrett Wilson   // global namespace is duplicated because the items haven't been merged at the
6544a68babdSBrett Wilson   // serialization phase of processing).
6554a68babdSBrett Wilson   NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get());
6564a68babdSBrett Wilson   ASSERT_EQ(1u, GlobalNS2->Children.Functions.size());
6574a68babdSBrett Wilson 
6584a68babdSBrett Wilson   // This one is a template specialization.
6594a68babdSBrett Wilson   const FunctionInfo &Func2 = GlobalNS2->Children.Functions[0];
6604a68babdSBrett Wilson   EXPECT_EQ("GetFoo", Func2.Name);
6614a68babdSBrett Wilson   ASSERT_TRUE(Func2.Template);
6624a68babdSBrett Wilson   EXPECT_TRUE(Func2.Template->Params.empty()); // No template params.
6634a68babdSBrett Wilson   ASSERT_TRUE(Func2.Template->Specialization);
6644a68babdSBrett Wilson 
6654a68babdSBrett Wilson   // Specialization values.
6664a68babdSBrett Wilson   ASSERT_EQ(1u, Func2.Template->Specialization->Params.size());
6674a68babdSBrett Wilson   EXPECT_EQ("bool", Func2.Template->Specialization->Params[0].Contents);
6684a68babdSBrett Wilson   EXPECT_EQ(Func1.USR, Func2.Template->Specialization->SpecializationOf);
669*2b932bc1SPaul Kirth 
670*2b932bc1SPaul Kirth   EXPECT_EQ("bool", Func2.ReturnType.Type.Name);
6714a68babdSBrett Wilson }
6724a68babdSBrett Wilson 
6734a68babdSBrett Wilson TEST(SerializeTests, emitClassTemplate) {
6744a68babdSBrett Wilson   EmittedInfoList Infos;
6754a68babdSBrett Wilson   // This will generate 2x the number of infos: each Record will be followed by
6764a68babdSBrett Wilson   // a copy of the global namespace containing it (this test checks the data
6774a68babdSBrett Wilson   // pre-merge).
6784a68babdSBrett Wilson   ExtractInfosFromCode(
6794a68babdSBrett Wilson       "template<int I> class MyTemplate { int i[I]; };\n"
6804a68babdSBrett Wilson       "template<> class MyTemplate<0> {};\n"
6814a68babdSBrett Wilson       "template<typename T, int U = 1> class OtherTemplate {};\n"
6824a68babdSBrett Wilson       "template<int U> class OtherTemplate<MyTemplate<0>, U> {};",
6834a68babdSBrett Wilson       8,
6844a68babdSBrett Wilson       /*Public=*/false, Infos);
6854a68babdSBrett Wilson 
6864a68babdSBrett Wilson   // First record.
6874a68babdSBrett Wilson   const RecordInfo *Rec1 = InfoAsRecord(Infos[0].get());
6884a68babdSBrett Wilson   EXPECT_EQ("MyTemplate", Rec1->Name);
6894a68babdSBrett Wilson   ASSERT_TRUE(Rec1->Template);
6904a68babdSBrett Wilson   EXPECT_FALSE(Rec1->Template->Specialization); // Not a specialization.
6914a68babdSBrett Wilson 
6924a68babdSBrett Wilson   // First record template parameter.
6934a68babdSBrett Wilson   ASSERT_EQ(1u, Rec1->Template->Params.size());
6944a68babdSBrett Wilson   EXPECT_EQ("int I", Rec1->Template->Params[0].Contents);
6954a68babdSBrett Wilson 
6964a68babdSBrett Wilson   // Second record.
6974a68babdSBrett Wilson   const RecordInfo *Rec2 = InfoAsRecord(Infos[2].get());
6984a68babdSBrett Wilson   EXPECT_EQ("MyTemplate", Rec2->Name);
6994a68babdSBrett Wilson   ASSERT_TRUE(Rec2->Template);
7004a68babdSBrett Wilson   EXPECT_TRUE(Rec2->Template->Params.empty()); // No template params.
7014a68babdSBrett Wilson   ASSERT_TRUE(Rec2->Template->Specialization);
7024a68babdSBrett Wilson 
7034a68babdSBrett Wilson   // Second record specialization values.
7044a68babdSBrett Wilson   ASSERT_EQ(1u, Rec2->Template->Specialization->Params.size());
7054a68babdSBrett Wilson   EXPECT_EQ("0", Rec2->Template->Specialization->Params[0].Contents);
7064a68babdSBrett Wilson   EXPECT_EQ(Rec1->USR, Rec2->Template->Specialization->SpecializationOf);
7074a68babdSBrett Wilson 
7084a68babdSBrett Wilson   // Third record.
7094a68babdSBrett Wilson   const RecordInfo *Rec3 = InfoAsRecord(Infos[4].get());
7104a68babdSBrett Wilson   EXPECT_EQ("OtherTemplate", Rec3->Name);
7114a68babdSBrett Wilson   ASSERT_TRUE(Rec3->Template);
7124a68babdSBrett Wilson 
7134a68babdSBrett Wilson   // Third record template parameters.
7144a68babdSBrett Wilson   ASSERT_EQ(2u, Rec3->Template->Params.size());
7154a68babdSBrett Wilson   EXPECT_EQ("typename T", Rec3->Template->Params[0].Contents);
7164a68babdSBrett Wilson   EXPECT_EQ("int U = 1", Rec3->Template->Params[1].Contents);
7174a68babdSBrett Wilson 
7184a68babdSBrett Wilson   // Fourth record.
7194a68babdSBrett Wilson   const RecordInfo *Rec4 = InfoAsRecord(Infos[6].get());
7204a68babdSBrett Wilson   EXPECT_EQ("OtherTemplate", Rec3->Name);
7214a68babdSBrett Wilson   ASSERT_TRUE(Rec4->Template);
7224a68babdSBrett Wilson   ASSERT_TRUE(Rec4->Template->Specialization);
7234a68babdSBrett Wilson 
7244a68babdSBrett Wilson   // Fourth record template + specialization parameters.
7254a68babdSBrett Wilson   ASSERT_EQ(1u, Rec4->Template->Params.size());
7264a68babdSBrett Wilson   EXPECT_EQ("int U", Rec4->Template->Params[0].Contents);
7274a68babdSBrett Wilson   ASSERT_EQ(2u, Rec4->Template->Specialization->Params.size());
7284a68babdSBrett Wilson   EXPECT_EQ("MyTemplate<0>",
7294a68babdSBrett Wilson             Rec4->Template->Specialization->Params[0].Contents);
7304a68babdSBrett Wilson   EXPECT_EQ("U", Rec4->Template->Specialization->Params[1].Contents);
7314a68babdSBrett Wilson }
7324a68babdSBrett Wilson 
73368049b1aSJulie Hockett } // namespace doc
73468049b1aSJulie Hockett } // end namespace clang
735