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 //===----------------------------------------------------------------------===// 8 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" 15 16 namespace clang { 17 namespace doc { 18 19 class ClangDocSerializeTestVisitor 20 : public RecursiveASTVisitor<ClangDocSerializeTestVisitor> { 21 22 EmittedInfoList &EmittedInfos; 23 bool Public; 24 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); 30 } 31 return nullptr; 32 } 33 34 public: 35 ClangDocSerializeTestVisitor(EmittedInfoList &EmittedInfos, bool Public) 36 : EmittedInfos(EmittedInfos), Public(Public) {} 37 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; 46 } 47 48 bool VisitNamespaceDecl(const NamespaceDecl *D) { return mapDecl(D); } 49 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); 55 } 56 57 bool VisitCXXMethodDecl(const CXXMethodDecl *D) { return mapDecl(D); } 58 59 bool VisitRecordDecl(const RecordDecl *D) { return mapDecl(D); } 60 61 bool VisitEnumDecl(const EnumDecl *D) { return mapDecl(D); } 62 }; 63 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()); 71 } 72 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()); 81 } 82 83 // Test serialization of namespace declarations. 84 TEST(SerializeTest, emitNamespaceInfo) { 85 EmittedInfoList Infos; 86 ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 5, 87 /*Public=*/false, Infos); 88 89 NamespaceInfo *A = InfoAsNamespace(Infos[0].get()); 90 NamespaceInfo ExpectedA(EmptySID, "A"); 91 CheckNamespaceInfo(&ExpectedA, A); 92 93 NamespaceInfo *B = InfoAsNamespace(Infos[2].get()); 94 NamespaceInfo ExpectedB(EmptySID, /*Name=*/"B", /*Path=*/"A"); 95 ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); 96 CheckNamespaceInfo(&ExpectedB, B); 97 98 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4].get()); 99 NamespaceInfo ExpectedBWithFunction(EmptySID); 100 FunctionInfo F; 101 F.Name = "f"; 102 F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 103 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 104 F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace); 105 F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); 106 F.Access = AccessSpecifier::AS_none; 107 ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F)); 108 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); 109 } 110 111 TEST(SerializeTest, emitAnonymousNamespaceInfo) { 112 EmittedInfoList Infos; 113 ExtractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos); 114 115 NamespaceInfo *A = InfoAsNamespace(Infos[0].get()); 116 NamespaceInfo ExpectedA(EmptySID); 117 ExpectedA.Name = "@nonymous_namespace"; 118 CheckNamespaceInfo(&ExpectedA, A); 119 } 120 121 // Test serialization of record declarations. 122 TEST(SerializeTest, emitRecordInfo) { 123 EmittedInfoList Infos; 124 ExtractInfosFromCode(R"raw(class E { 125 public: 126 E() {} 127 protected: 128 void ProtectedMethod(); 129 }; 130 template <typename T> 131 struct F { 132 void TemplateMethod(); 133 }; 134 template <> 135 void F<int>::TemplateMethod(); 136 typedef struct {} G;)raw", 137 10, /*Public=*/false, Infos); 138 139 RecordInfo *E = InfoAsRecord(Infos[0].get()); 140 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); 141 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", 142 InfoType::IT_namespace); 143 ExpectedE.TagType = TagTypeKind::TTK_Class; 144 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 145 CheckRecordInfo(&ExpectedE, E); 146 147 RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2].get()); 148 RecordInfo ExpectedRecordWithEConstructor(EmptySID); 149 FunctionInfo EConstructor; 150 EConstructor.Name = "E"; 151 EConstructor.Parent = Reference(EmptySID, "E", InfoType::IT_record); 152 EConstructor.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 153 EConstructor.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 154 EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record); 155 EConstructor.Namespace.emplace_back(EmptySID, "GlobalNamespace", 156 InfoType::IT_namespace); 157 EConstructor.Access = AccessSpecifier::AS_public; 158 EConstructor.IsMethod = true; 159 ExpectedRecordWithEConstructor.ChildFunctions.emplace_back( 160 std::move(EConstructor)); 161 CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor); 162 163 RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3].get()); 164 RecordInfo ExpectedRecordWithMethod(EmptySID); 165 FunctionInfo Method; 166 Method.Name = "ProtectedMethod"; 167 Method.Parent = Reference(EmptySID, "E", InfoType::IT_record); 168 Method.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 169 Method.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"}); 170 Method.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record); 171 Method.Namespace.emplace_back(EmptySID, "GlobalNamespace", 172 InfoType::IT_namespace); 173 Method.Access = AccessSpecifier::AS_protected; 174 Method.IsMethod = true; 175 ExpectedRecordWithMethod.ChildFunctions.emplace_back(std::move(Method)); 176 CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod); 177 178 RecordInfo *F = InfoAsRecord(Infos[4].get()); 179 RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace"); 180 ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace", 181 InfoType::IT_namespace); 182 ExpectedF.TagType = TagTypeKind::TTK_Struct; 183 ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 184 CheckRecordInfo(&ExpectedF, F); 185 186 RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6].get()); 187 RecordInfo ExpectedRecordWithTemplateMethod(EmptySID); 188 FunctionInfo TemplateMethod; 189 TemplateMethod.Name = "TemplateMethod"; 190 TemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record); 191 TemplateMethod.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 192 TemplateMethod.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"}); 193 TemplateMethod.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record); 194 TemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace", 195 InfoType::IT_namespace); 196 TemplateMethod.Access = AccessSpecifier::AS_public; 197 TemplateMethod.IsMethod = true; 198 ExpectedRecordWithTemplateMethod.ChildFunctions.emplace_back( 199 std::move(TemplateMethod)); 200 CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod); 201 202 RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7].get()); 203 RecordInfo ExpectedTemplatedRecord(EmptySID); 204 FunctionInfo SpecializedTemplateMethod; 205 SpecializedTemplateMethod.Name = "TemplateMethod"; 206 SpecializedTemplateMethod.Parent = 207 Reference(EmptySID, "F", InfoType::IT_record); 208 SpecializedTemplateMethod.ReturnType = 209 TypeInfo(EmptySID, "void", InfoType::IT_default); 210 SpecializedTemplateMethod.Loc.emplace_back(0, 211 llvm::SmallString<16>{"test.cpp"}); 212 SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "F", 213 InfoType::IT_record); 214 SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace", 215 InfoType::IT_namespace); 216 SpecializedTemplateMethod.Access = AccessSpecifier::AS_public; 217 SpecializedTemplateMethod.IsMethod = true; 218 ExpectedTemplatedRecord.ChildFunctions.emplace_back( 219 std::move(SpecializedTemplateMethod)); 220 CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord); 221 222 RecordInfo *G = InfoAsRecord(Infos[8].get()); 223 RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace"); 224 ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace", 225 InfoType::IT_namespace); 226 ExpectedG.TagType = TagTypeKind::TTK_Struct; 227 ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 228 ExpectedG.IsTypeDef = true; 229 CheckRecordInfo(&ExpectedG, G); 230 } 231 232 // Test serialization of enum declarations. 233 TEST(SerializeTest, emitEnumInfo) { 234 EmittedInfoList Infos; 235 ExtractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2, 236 /*Public=*/false, Infos); 237 238 NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get()); 239 NamespaceInfo ExpectedNamespaceWithEnum(EmptySID); 240 EnumInfo E; 241 E.Name = "E"; 242 E.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 243 E.Members.emplace_back("X"); 244 E.Members.emplace_back("Y"); 245 ExpectedNamespaceWithEnum.ChildEnums.emplace_back(std::move(E)); 246 CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum); 247 248 NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get()); 249 NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID); 250 EnumInfo G; 251 G.Name = "G"; 252 G.Scoped = true; 253 G.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 254 G.Members.emplace_back("A"); 255 G.Members.emplace_back("B"); 256 ExpectedNamespaceWithScopedEnum.ChildEnums.emplace_back(std::move(G)); 257 CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum); 258 } 259 260 TEST(SerializeTest, emitUndefinedRecordInfo) { 261 EmittedInfoList Infos; 262 ExtractInfosFromCode("class E;", 2, /*Public=*/false, Infos); 263 264 RecordInfo *E = InfoAsRecord(Infos[0].get()); 265 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); 266 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", 267 InfoType::IT_namespace); 268 ExpectedE.TagType = TagTypeKind::TTK_Class; 269 ExpectedE.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"}); 270 CheckRecordInfo(&ExpectedE, E); 271 } 272 273 TEST(SerializeTest, emitRecordMemberInfo) { 274 EmittedInfoList Infos; 275 ExtractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos); 276 277 RecordInfo *E = InfoAsRecord(Infos[0].get()); 278 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); 279 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", 280 InfoType::IT_namespace); 281 ExpectedE.TagType = TagTypeKind::TTK_Struct; 282 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 283 ExpectedE.Members.emplace_back("int", "I", AccessSpecifier::AS_public); 284 CheckRecordInfo(&ExpectedE, E); 285 } 286 287 TEST(SerializeTest, emitInternalRecordInfo) { 288 EmittedInfoList Infos; 289 ExtractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos); 290 291 RecordInfo *E = InfoAsRecord(Infos[0].get()); 292 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); 293 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", 294 InfoType::IT_namespace); 295 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 296 ExpectedE.TagType = TagTypeKind::TTK_Class; 297 CheckRecordInfo(&ExpectedE, E); 298 299 RecordInfo *G = InfoAsRecord(Infos[2].get()); 300 llvm::SmallString<128> ExpectedGPath("GlobalNamespace/E"); 301 llvm::sys::path::native(ExpectedGPath); 302 RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/ExpectedGPath); 303 ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 304 ExpectedG.TagType = TagTypeKind::TTK_Class; 305 ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record); 306 ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace", 307 InfoType::IT_namespace); 308 CheckRecordInfo(&ExpectedG, G); 309 } 310 311 TEST(SerializeTest, emitPublicAnonymousNamespaceInfo) { 312 EmittedInfoList Infos; 313 ExtractInfosFromCode("namespace { class A; }", 0, /*Public=*/true, Infos); 314 } 315 316 TEST(SerializeTest, emitPublicFunctionInternalInfo) { 317 EmittedInfoList Infos; 318 ExtractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true, 319 Infos); 320 321 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get()); 322 NamespaceInfo ExpectedBWithFunction(EmptySID); 323 FunctionInfo F; 324 F.Name = "F"; 325 F.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default); 326 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 327 F.Access = AccessSpecifier::AS_none; 328 ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F)); 329 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); 330 } 331 332 TEST(SerializeTest, emitInlinedFunctionInfo) { 333 EmittedInfoList Infos; 334 ExtractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos); 335 336 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get()); 337 NamespaceInfo ExpectedBWithFunction(EmptySID); 338 FunctionInfo F; 339 F.Name = "F"; 340 F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 341 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 342 F.Params.emplace_back("int", "I"); 343 F.Access = AccessSpecifier::AS_none; 344 ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F)); 345 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); 346 } 347 348 TEST(SerializeTest, emitInheritedRecordInfo) { 349 EmittedInfoList Infos; 350 ExtractInfosFromCode(R"raw(class F { protected: void set(int N); }; 351 class G { public: int get() { return 1; } protected: int I; }; 352 class E : public F, virtual private G {}; 353 class H : private E {}; 354 template <typename T> 355 class I {} ; 356 class J : public I<int> {} ;)raw", 357 14, /*Public=*/false, Infos); 358 359 RecordInfo *F = InfoAsRecord(Infos[0].get()); 360 RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace"); 361 ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace", 362 InfoType::IT_namespace); 363 ExpectedF.TagType = TagTypeKind::TTK_Class; 364 ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 365 CheckRecordInfo(&ExpectedF, F); 366 367 RecordInfo *G = InfoAsRecord(Infos[3].get()); 368 RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace"); 369 ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace", 370 InfoType::IT_namespace); 371 ExpectedG.TagType = TagTypeKind::TTK_Class; 372 ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 373 ExpectedG.Members.emplace_back("int", "I", AccessSpecifier::AS_protected); 374 CheckRecordInfo(&ExpectedG, G); 375 376 RecordInfo *E = InfoAsRecord(Infos[6].get()); 377 RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); 378 ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", 379 InfoType::IT_namespace); 380 ExpectedE.Parents.emplace_back(EmptySID, /*Name=*/"F", InfoType::IT_record, 381 /*Path*=*/"GlobalNamespace"); 382 ExpectedE.VirtualParents.emplace_back( 383 EmptySID, /*Name=*/"G", InfoType::IT_record, /*Path*=*/"GlobalNamespace"); 384 ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"F", 385 /*Path=*/"GlobalNamespace", false, 386 AccessSpecifier::AS_public, true); 387 FunctionInfo FunctionSet; 388 FunctionSet.Name = "set"; 389 FunctionSet.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 390 FunctionSet.Loc.emplace_back(); 391 FunctionSet.Params.emplace_back("int", "N"); 392 FunctionSet.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record); 393 FunctionSet.Namespace.emplace_back(EmptySID, "GlobalNamespace", 394 InfoType::IT_namespace); 395 FunctionSet.Access = AccessSpecifier::AS_protected; 396 FunctionSet.IsMethod = true; 397 ExpectedE.Bases.back().ChildFunctions.emplace_back(std::move(FunctionSet)); 398 ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"G", 399 /*Path=*/"GlobalNamespace", true, 400 AccessSpecifier::AS_private, true); 401 FunctionInfo FunctionGet; 402 FunctionGet.Name = "get"; 403 FunctionGet.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default); 404 FunctionGet.DefLoc = Location(); 405 FunctionGet.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record); 406 FunctionGet.Namespace.emplace_back(EmptySID, "GlobalNamespace", 407 InfoType::IT_namespace); 408 FunctionGet.Access = AccessSpecifier::AS_private; 409 FunctionGet.IsMethod = true; 410 ExpectedE.Bases.back().ChildFunctions.emplace_back(std::move(FunctionGet)); 411 ExpectedE.Bases.back().Members.emplace_back("int", "I", 412 AccessSpecifier::AS_private); 413 ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 414 ExpectedE.TagType = TagTypeKind::TTK_Class; 415 CheckRecordInfo(&ExpectedE, E); 416 417 RecordInfo *H = InfoAsRecord(Infos[8].get()); 418 RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace"); 419 ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace", 420 InfoType::IT_namespace); 421 ExpectedH.TagType = TagTypeKind::TTK_Class; 422 ExpectedH.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 423 ExpectedH.Parents.emplace_back(EmptySID, /*Name=*/"E", InfoType::IT_record, 424 /*Path=*/"GlobalNamespace"); 425 ExpectedH.VirtualParents.emplace_back( 426 EmptySID, /*Name=*/"G", InfoType::IT_record, /*Path=*/"GlobalNamespace"); 427 ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"E", 428 /*Path=*/"GlobalNamespace", false, 429 AccessSpecifier::AS_private, true); 430 ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"F", 431 /*Path=*/"GlobalNamespace", false, 432 AccessSpecifier::AS_private, false); 433 FunctionInfo FunctionSetNew; 434 FunctionSetNew.Name = "set"; 435 FunctionSetNew.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 436 FunctionSetNew.Loc.emplace_back(); 437 FunctionSetNew.Params.emplace_back("int", "N"); 438 FunctionSetNew.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record); 439 FunctionSetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace", 440 InfoType::IT_namespace); 441 FunctionSetNew.Access = AccessSpecifier::AS_private; 442 FunctionSetNew.IsMethod = true; 443 ExpectedH.Bases.back().ChildFunctions.emplace_back(std::move(FunctionSetNew)); 444 ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"G", 445 /*Path=*/"GlobalNamespace", true, 446 AccessSpecifier::AS_private, false); 447 FunctionInfo FunctionGetNew; 448 FunctionGetNew.Name = "get"; 449 FunctionGetNew.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default); 450 FunctionGetNew.DefLoc = Location(); 451 FunctionGetNew.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record); 452 FunctionGetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace", 453 InfoType::IT_namespace); 454 FunctionGetNew.Access = AccessSpecifier::AS_private; 455 FunctionGetNew.IsMethod = true; 456 ExpectedH.Bases.back().ChildFunctions.emplace_back(std::move(FunctionGetNew)); 457 ExpectedH.Bases.back().Members.emplace_back("int", "I", 458 AccessSpecifier::AS_private); 459 CheckRecordInfo(&ExpectedH, H); 460 461 RecordInfo *I = InfoAsRecord(Infos[10].get()); 462 RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace"); 463 ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace", 464 InfoType::IT_namespace); 465 ExpectedI.TagType = TagTypeKind::TTK_Class; 466 ExpectedI.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 467 CheckRecordInfo(&ExpectedI, I); 468 469 RecordInfo *J = InfoAsRecord(Infos[12].get()); 470 RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace"); 471 ExpectedJ.Namespace.emplace_back(EmptySID, "GlobalNamespace", 472 InfoType::IT_namespace); 473 ExpectedJ.Parents.emplace_back(EmptySID, /*Name=*/"I<int>", 474 InfoType::IT_record); 475 ExpectedJ.Bases.emplace_back(EmptySID, /*Name=*/"I<int>", 476 /*Path=*/"GlobalNamespace", false, 477 AccessSpecifier::AS_public, true); 478 ExpectedJ.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 479 ExpectedJ.TagType = TagTypeKind::TTK_Class; 480 CheckRecordInfo(&ExpectedJ, J); 481 } 482 483 TEST(SerializeTest, emitModulePublicLFunctions) { 484 EmittedInfoList Infos; 485 std::vector<std::string> Args; 486 Args.push_back("-fmodules-ts"); 487 ExtractInfosFromCodeWithArgs(R"raw(export module M; 488 int moduleFunction(int x); 489 static int staticModuleFunction(int x); 490 export double exportedModuleFunction(double y);)raw", 491 2, /*Public=*/true, Infos, Args); 492 493 NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get()); 494 NamespaceInfo ExpectedBWithFunction(EmptySID); 495 FunctionInfo F; 496 F.Name = "moduleFunction"; 497 F.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default); 498 F.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"}); 499 F.Params.emplace_back("int", "x"); 500 F.Access = AccessSpecifier::AS_none; 501 ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F)); 502 CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); 503 504 NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get()); 505 NamespaceInfo ExpectedBWithExportedFunction(EmptySID); 506 FunctionInfo ExportedF; 507 ExportedF.Name = "exportedModuleFunction"; 508 ExportedF.ReturnType = TypeInfo(EmptySID, "double", InfoType::IT_default); 509 ExportedF.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"}); 510 ExportedF.Params.emplace_back("double", "y"); 511 ExportedF.Access = AccessSpecifier::AS_none; 512 ExpectedBWithExportedFunction.ChildFunctions.emplace_back( 513 std::move(ExportedF)); 514 CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction); 515 } 516 517 // Test serialization of child records in namespaces and other records 518 TEST(SerializeTest, emitChildRecords) { 519 EmittedInfoList Infos; 520 ExtractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8, 521 /*Public=*/false, Infos); 522 523 NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get()); 524 NamespaceInfo ExpectedParentA(EmptySID); 525 ExpectedParentA.ChildRecords.emplace_back(EmptySID, "A", InfoType::IT_record, 526 "GlobalNamespace"); 527 CheckNamespaceInfo(&ExpectedParentA, ParentA); 528 529 RecordInfo *ParentB = InfoAsRecord(Infos[3].get()); 530 RecordInfo ExpectedParentB(EmptySID); 531 llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A"); 532 llvm::sys::path::native(ExpectedParentBPath); 533 ExpectedParentB.ChildRecords.emplace_back(EmptySID, "B", InfoType::IT_record, 534 ExpectedParentBPath); 535 CheckRecordInfo(&ExpectedParentB, ParentB); 536 537 NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get()); 538 NamespaceInfo ExpectedParentC(EmptySID); 539 ExpectedParentC.ChildRecords.emplace_back(EmptySID, "C", InfoType::IT_record, 540 "@nonymous_namespace"); 541 CheckNamespaceInfo(&ExpectedParentC, ParentC); 542 } 543 544 // Test serialization of child namespaces 545 TEST(SerializeTest, emitChildNamespaces) { 546 EmittedInfoList Infos; 547 ExtractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false, 548 Infos); 549 550 NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get()); 551 NamespaceInfo ExpectedParentA(EmptySID); 552 ExpectedParentA.ChildNamespaces.emplace_back(EmptySID, "A", 553 InfoType::IT_namespace); 554 CheckNamespaceInfo(&ExpectedParentA, ParentA); 555 556 NamespaceInfo *ParentB = InfoAsNamespace(Infos[3].get()); 557 NamespaceInfo ExpectedParentB(EmptySID); 558 ExpectedParentB.ChildNamespaces.emplace_back(EmptySID, "B", 559 InfoType::IT_namespace, "A"); 560 CheckNamespaceInfo(&ExpectedParentB, ParentB); 561 } 562 563 } // namespace doc 564 } // end namespace clang 565