581 lines · cpp
1//===-- clang-doc/YAMLGeneratorTest.cpp2//------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#include "ClangDocTest.h"11#include "Generators.h"12#include "Representation.h"13#include "gtest/gtest.h"14 15namespace clang {16namespace doc {17 18static std::unique_ptr<Generator> getYAMLGenerator() {19 auto G = doc::findGeneratorByName("yaml");20 if (!G)21 return nullptr;22 return std::move(G.get());23}24 25TEST(YAMLGeneratorTest, emitNamespaceYAML) {26 NamespaceInfo I;27 I.Name = "Namespace";28 I.Path = "path/to/A";29 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);30 31 I.Children.Namespaces.emplace_back(32 EmptySID, "ChildNamespace", InfoType::IT_namespace,33 "path::to::A::Namespace::ChildNamespace", "path/to/A/Namespace");34 I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,35 "path::to::A::Namespace::ChildStruct",36 "path/to/A/Namespace");37 I.Children.Functions.emplace_back();38 I.Children.Functions.back().Name = "OneFunction";39 I.Children.Functions.back().Access = AccessSpecifier::AS_none;40 I.Children.Enums.emplace_back();41 I.Children.Enums.back().Name = "OneEnum";42 43 auto G = getYAMLGenerator();44 assert(G);45 std::string Buffer;46 llvm::raw_string_ostream Actual(Buffer);47 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());48 assert(!Err);49 std::string Expected =50 R"raw(---51USR: '0000000000000000000000000000000000000000'52Name: 'Namespace'53Path: 'path/to/A'54Namespace:55 - Type: Namespace56 Name: 'A'57 QualName: 'A'58ChildNamespaces:59 - Type: Namespace60 Name: 'ChildNamespace'61 QualName: 'path::to::A::Namespace::ChildNamespace'62 Path: 'path/to/A/Namespace'63ChildRecords:64 - Type: Record65 Name: 'ChildStruct'66 QualName: 'path::to::A::Namespace::ChildStruct'67 Path: 'path/to/A/Namespace'68ChildFunctions:69 - USR: '0000000000000000000000000000000000000000'70 Name: 'OneFunction'71 ReturnType: {}72ChildEnums:73 - USR: '0000000000000000000000000000000000000000'74 Name: 'OneEnum'75...76)raw";77 EXPECT_EQ(Expected, Actual.str());78}79 80TEST(YAMLGeneratorTest, emitRecordYAML) {81 RecordInfo I;82 I.Name = "r";83 I.Path = "path/to/A";84 I.IsTypeDef = true;85 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);86 87 I.DefLoc = Location(10, 10, "test.cpp");88 I.Loc.emplace_back(12, 12, "test.cpp");89 90 I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);91 92 // Member documentation.93 CommentInfo TopComment;94 TopComment.Kind = CommentKind::CK_FullComment;95 TopComment.Children.emplace_back(std::make_unique<CommentInfo>());96 CommentInfo *Brief = TopComment.Children.back().get();97 Brief->Kind = CommentKind::CK_ParagraphComment;98 Brief->Children.emplace_back(std::make_unique<CommentInfo>());99 Brief->Children.back()->Kind = CommentKind::CK_TextComment;100 Brief->Children.back()->Name = "ParagraphComment";101 Brief->Children.back()->Text = "Value of the thing.";102 I.Members.back().Description.push_back(std::move(TopComment));103 104 I.TagType = TagTypeKind::Class;105 I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,106 AccessSpecifier::AS_public, true);107 I.Bases.back().Children.Functions.emplace_back();108 I.Bases.back().Children.Functions.back().Name = "InheritedFunctionOne";109 I.Bases.back().Members.emplace_back(TypeInfo("int"), "N",110 AccessSpecifier::AS_private);111 // F is in the global namespace112 I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "");113 I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,114 "path::to::G::G", "path/to/G");115 116 I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,117 "path::to::A::r::ChildStruct", "path/to/A/r");118 I.Children.Functions.emplace_back();119 I.Children.Functions.back().Name = "OneFunction";120 I.Children.Enums.emplace_back();121 I.Children.Enums.back().Name = "OneEnum";122 123 auto G = getYAMLGenerator();124 assert(G);125 std::string Buffer;126 llvm::raw_string_ostream Actual(Buffer);127 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());128 assert(!Err);129 std::string Expected =130 R"raw(---131USR: '0000000000000000000000000000000000000000'132Name: 'r'133Path: 'path/to/A'134Namespace:135 - Type: Namespace136 Name: 'A'137 QualName: 'A'138DefLocation:139 LineNumber: 10140 Filename: 'test.cpp'141Location:142 - LineNumber: 12143 Filename: 'test.cpp'144TagType: Class145IsTypeDef: true146Members:147 - Type:148 Name: 'int'149 QualName: 'int'150 Name: 'X'151 Access: Private152 Description:153 - Kind: FullComment154 Children:155 - Kind: ParagraphComment156 Children:157 - Kind: TextComment158 Text: 'Value of the thing.'159 Name: 'ParagraphComment'160Bases:161 - USR: '0000000000000000000000000000000000000000'162 Name: 'F'163 Path: 'path/to/F'164 TagType: Struct165 Members:166 - Type:167 Name: 'int'168 QualName: 'int'169 Name: 'N'170 Access: Private171 ChildFunctions:172 - USR: '0000000000000000000000000000000000000000'173 Name: 'InheritedFunctionOne'174 ReturnType: {}175 Access: Public176 IsVirtual: true177 Access: Public178 IsParent: true179Parents:180 - Type: Record181 Name: 'F'182VirtualParents:183 - Type: Record184 Name: 'G'185 QualName: 'path::to::G::G'186 Path: 'path/to/G'187ChildRecords:188 - Type: Record189 Name: 'ChildStruct'190 QualName: 'path::to::A::r::ChildStruct'191 Path: 'path/to/A/r'192ChildFunctions:193 - USR: '0000000000000000000000000000000000000000'194 Name: 'OneFunction'195 ReturnType: {}196 Access: Public197ChildEnums:198 - USR: '0000000000000000000000000000000000000000'199 Name: 'OneEnum'200...201)raw";202 EXPECT_EQ(Expected, Actual.str());203}204 205TEST(YAMLGeneratorTest, emitFunctionYAML) {206 FunctionInfo I;207 I.Name = "f";208 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);209 210 I.DefLoc = Location(10, 10, "test.cpp");211 I.Loc.emplace_back(12, 12, "test.cpp");212 213 I.Access = AccessSpecifier::AS_none;214 215 I.ReturnType = TypeInfo(Reference(EmptySID, "void", InfoType::IT_default));216 I.Params.emplace_back(TypeInfo("int"), "P");217 I.Params.emplace_back(TypeInfo("double"), "D");218 I.Params.back().DefaultValue = "2.0 * M_PI";219 I.IsMethod = true;220 I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);221 222 auto G = getYAMLGenerator();223 assert(G);224 std::string Buffer;225 llvm::raw_string_ostream Actual(Buffer);226 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());227 assert(!Err);228 std::string Expected =229 R"raw(---230USR: '0000000000000000000000000000000000000000'231Name: 'f'232Namespace:233 - Type: Namespace234 Name: 'A'235 QualName: 'A'236DefLocation:237 LineNumber: 10238 Filename: 'test.cpp'239Location:240 - LineNumber: 12241 Filename: 'test.cpp'242IsMethod: true243Parent:244 Type: Record245 Name: 'Parent'246 QualName: 'Parent'247Params:248 - Type:249 Name: 'int'250 QualName: 'int'251 Name: 'P'252 - Type:253 Name: 'double'254 QualName: 'double'255 Name: 'D'256 DefaultValue: '2.0 * M_PI'257ReturnType:258 Type:259 Name: 'void'260 QualName: 'void'261...262)raw";263 EXPECT_EQ(Expected, Actual.str());264}265 266// Tests the equivalent of:267// namespace A {268// enum e { X };269// }270TEST(YAMLGeneratorTest, emitSimpleEnumYAML) {271 EnumInfo I;272 I.Name = "e";273 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);274 275 I.DefLoc = Location(10, 10, "test.cpp");276 I.Loc.emplace_back(12, 12, "test.cpp");277 278 I.Members.emplace_back("X");279 I.Scoped = false;280 281 auto G = getYAMLGenerator();282 assert(G);283 std::string Buffer;284 llvm::raw_string_ostream Actual(Buffer);285 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());286 assert(!Err);287 std::string Expected =288 R"raw(---289USR: '0000000000000000000000000000000000000000'290Name: 'e'291Namespace:292 - Type: Namespace293 Name: 'A'294 QualName: 'A'295DefLocation:296 LineNumber: 10297 Filename: 'test.cpp'298Location:299 - LineNumber: 12300 Filename: 'test.cpp'301Members:302 - Name: 'X'303 Value: '0'304...305)raw";306 EXPECT_EQ(Expected, Actual.str());307}308 309// Tests the equivalent of:310// enum class e : short { X = FOO_BAR + 2 };311TEST(YAMLGeneratorTest, enumTypedScopedEnumYAML) {312 EnumInfo I;313 I.Name = "e";314 315 I.Members.emplace_back("X", "-9876", "FOO_BAR + 2");316 I.Scoped = true;317 I.BaseType = TypeInfo("short");318 319 auto G = getYAMLGenerator();320 assert(G);321 std::string Buffer;322 llvm::raw_string_ostream Actual(Buffer);323 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());324 assert(!Err);325 std::string Expected =326 R"raw(---327USR: '0000000000000000000000000000000000000000'328Name: 'e'329Scoped: true330BaseType:331 Type:332 Name: 'short'333 QualName: 'short'334Members:335 - Name: 'X'336 Value: '-9876'337 Expr: 'FOO_BAR + 2'338...339)raw";340 EXPECT_EQ(Expected, Actual.str());341}342 343TEST(YAMLGeneratorTest, enumTypedefYAML) {344 TypedefInfo I;345 I.Name = "MyUsing";346 I.Underlying = TypeInfo("int");347 I.IsUsing = true;348 349 auto G = getYAMLGenerator();350 assert(G);351 std::string Buffer;352 llvm::raw_string_ostream Actual(Buffer);353 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());354 assert(!Err);355 std::string Expected =356 R"raw(---357USR: '0000000000000000000000000000000000000000'358Name: 'MyUsing'359Underlying:360 Name: 'int'361 QualName: 'int'362IsUsing: true363...364)raw";365 EXPECT_EQ(Expected, Actual.str());366}367 368TEST(YAMLGeneratorTest, emitCommentYAML) {369 FunctionInfo I;370 I.Name = "f";371 I.DefLoc = Location(10, 10, "test.cpp");372 I.ReturnType = TypeInfo("void");373 I.Params.emplace_back(TypeInfo("int"), "I");374 I.Params.emplace_back(TypeInfo("int"), "J");375 I.Access = AccessSpecifier::AS_none;376 377 CommentInfo Top;378 Top.Kind = CommentKind::CK_FullComment;379 380 Top.Children.emplace_back(std::make_unique<CommentInfo>());381 CommentInfo *BlankLine = Top.Children.back().get();382 BlankLine->Kind = CommentKind::CK_ParagraphComment;383 BlankLine->Children.emplace_back(std::make_unique<CommentInfo>());384 BlankLine->Children.back()->Kind = CommentKind::CK_TextComment;385 386 Top.Children.emplace_back(std::make_unique<CommentInfo>());387 CommentInfo *Brief = Top.Children.back().get();388 Brief->Kind = CommentKind::CK_ParagraphComment;389 Brief->Children.emplace_back(std::make_unique<CommentInfo>());390 Brief->Children.back()->Kind = CommentKind::CK_TextComment;391 Brief->Children.back()->Name = "ParagraphComment";392 Brief->Children.back()->Text = " Brief description.";393 394 Top.Children.emplace_back(std::make_unique<CommentInfo>());395 CommentInfo *Extended = Top.Children.back().get();396 Extended->Kind = CommentKind::CK_ParagraphComment;397 Extended->Children.emplace_back(std::make_unique<CommentInfo>());398 Extended->Children.back()->Kind = CommentKind::CK_TextComment;399 Extended->Children.back()->Text = " Extended description that";400 Extended->Children.emplace_back(std::make_unique<CommentInfo>());401 Extended->Children.back()->Kind = CommentKind::CK_TextComment;402 Extended->Children.back()->Text = " continues onto the next line.";403 404 Top.Children.emplace_back(std::make_unique<CommentInfo>());405 CommentInfo *HTML = Top.Children.back().get();406 HTML->Kind = CommentKind::CK_ParagraphComment;407 HTML->Children.emplace_back(std::make_unique<CommentInfo>());408 HTML->Children.back()->Kind = CommentKind::CK_TextComment;409 HTML->Children.emplace_back(std::make_unique<CommentInfo>());410 HTML->Children.back()->Kind = CommentKind::CK_HTMLStartTagComment;411 HTML->Children.back()->Name = "ul";412 HTML->Children.back()->AttrKeys.emplace_back("class");413 HTML->Children.back()->AttrValues.emplace_back("test");414 HTML->Children.emplace_back(std::make_unique<CommentInfo>());415 HTML->Children.back()->Kind = CommentKind::CK_HTMLStartTagComment;416 HTML->Children.back()->Name = "li";417 HTML->Children.emplace_back(std::make_unique<CommentInfo>());418 HTML->Children.back()->Kind = CommentKind::CK_TextComment;419 HTML->Children.back()->Text = " Testing.";420 HTML->Children.emplace_back(std::make_unique<CommentInfo>());421 HTML->Children.back()->Kind = CommentKind::CK_HTMLEndTagComment;422 HTML->Children.back()->Name = "ul";423 HTML->Children.back()->SelfClosing = true;424 425 Top.Children.emplace_back(std::make_unique<CommentInfo>());426 CommentInfo *Verbatim = Top.Children.back().get();427 Verbatim->Kind = CommentKind::CK_VerbatimBlockComment;428 Verbatim->Name = "verbatim";429 Verbatim->CloseName = "endverbatim";430 Verbatim->Children.emplace_back(std::make_unique<CommentInfo>());431 Verbatim->Children.back()->Kind = CommentKind::CK_VerbatimBlockLineComment;432 Verbatim->Children.back()->Text = " The description continues.";433 434 Top.Children.emplace_back(std::make_unique<CommentInfo>());435 CommentInfo *ParamOut = Top.Children.back().get();436 ParamOut->Kind = CommentKind::CK_ParamCommandComment;437 ParamOut->Direction = "[out]";438 ParamOut->ParamName = "I";439 ParamOut->Explicit = true;440 ParamOut->Children.emplace_back(std::make_unique<CommentInfo>());441 ParamOut->Children.back()->Kind = CommentKind::CK_ParagraphComment;442 ParamOut->Children.back()->Children.emplace_back(443 std::make_unique<CommentInfo>());444 ParamOut->Children.back()->Children.back()->Kind =445 CommentKind::CK_TextComment;446 ParamOut->Children.back()->Children.emplace_back(447 std::make_unique<CommentInfo>());448 ParamOut->Children.back()->Children.back()->Kind =449 CommentKind::CK_TextComment;450 ParamOut->Children.back()->Children.back()->Text = " is a parameter.";451 452 Top.Children.emplace_back(std::make_unique<CommentInfo>());453 CommentInfo *ParamIn = Top.Children.back().get();454 ParamIn->Kind = CommentKind::CK_ParamCommandComment;455 ParamIn->Direction = "[in]";456 ParamIn->ParamName = "J";457 ParamIn->Children.emplace_back(std::make_unique<CommentInfo>());458 ParamIn->Children.back()->Kind = CommentKind::CK_ParagraphComment;459 ParamIn->Children.back()->Children.emplace_back(460 std::make_unique<CommentInfo>());461 ParamIn->Children.back()->Children.back()->Kind = CommentKind::CK_TextComment;462 ParamIn->Children.back()->Children.back()->Text = " is a parameter.";463 ParamIn->Children.back()->Children.emplace_back(464 std::make_unique<CommentInfo>());465 ParamIn->Children.back()->Children.back()->Kind = CommentKind::CK_TextComment;466 467 Top.Children.emplace_back(std::make_unique<CommentInfo>());468 CommentInfo *Return = Top.Children.back().get();469 Return->Kind = CommentKind::CK_BlockCommandComment;470 Return->Name = "return";471 Return->Explicit = true;472 Return->Children.emplace_back(std::make_unique<CommentInfo>());473 Return->Children.back()->Kind = CommentKind::CK_ParagraphComment;474 Return->Children.back()->Children.emplace_back(475 std::make_unique<CommentInfo>());476 Return->Children.back()->Children.back()->Kind = CommentKind::CK_TextComment;477 Return->Children.back()->Children.back()->Text = "void";478 479 I.Description.emplace_back(std::move(Top));480 481 auto G = getYAMLGenerator();482 assert(G);483 std::string Buffer;484 llvm::raw_string_ostream Actual(Buffer);485 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());486 assert(!Err);487 std::string Expected =488 R"raw(---489USR: '0000000000000000000000000000000000000000'490Name: 'f'491Description:492 - Kind: FullComment493 Children:494 - Kind: ParagraphComment495 Children:496 - Kind: TextComment497 - Kind: ParagraphComment498 Children:499 - Kind: TextComment500 Text: ' Brief description.'501 Name: 'ParagraphComment'502 - Kind: ParagraphComment503 Children:504 - Kind: TextComment505 Text: ' Extended description that'506 - Kind: TextComment507 Text: ' continues onto the next line.'508 - Kind: ParagraphComment509 Children:510 - Kind: TextComment511 - Kind: HTMLStartTagComment512 Name: 'ul'513 AttrKeys:514 - 'class'515 AttrValues:516 - 'test'517 - Kind: HTMLStartTagComment518 Name: 'li'519 - Kind: TextComment520 Text: ' Testing.'521 - Kind: HTMLEndTagComment522 Name: 'ul'523 SelfClosing: true524 - Kind: VerbatimBlockComment525 Name: 'verbatim'526 CloseName: 'endverbatim'527 Children:528 - Kind: VerbatimBlockLineComment529 Text: ' The description continues.'530 - Kind: ParamCommandComment531 Direction: '[out]'532 ParamName: 'I'533 Explicit: true534 Children:535 - Kind: ParagraphComment536 Children:537 - Kind: TextComment538 - Kind: TextComment539 Text: ' is a parameter.'540 - Kind: ParamCommandComment541 Direction: '[in]'542 ParamName: 'J'543 Children:544 - Kind: ParagraphComment545 Children:546 - Kind: TextComment547 Text: ' is a parameter.'548 - Kind: TextComment549 - Kind: BlockCommandComment550 Name: 'return'551 Explicit: true552 Children:553 - Kind: ParagraphComment554 Children:555 - Kind: TextComment556 Text: 'void'557DefLocation:558 LineNumber: 10559 Filename: 'test.cpp'560Params:561 - Type:562 Name: 'int'563 QualName: 'int'564 Name: 'I'565 - Type:566 Name: 'int'567 QualName: 'int'568 Name: 'J'569ReturnType:570 Type:571 Name: 'void'572 QualName: 'void'573...574)raw";575 576 EXPECT_EQ(Expected, Actual.str());577}578 579} // namespace doc580} // namespace clang581