1 //===- unittests/AST/CommentParser.cpp ------ Comment parser tests --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "clang/AST/CommentParser.h" 11 #include "clang/AST/Comment.h" 12 #include "clang/AST/CommentCommandTraits.h" 13 #include "clang/AST/CommentLexer.h" 14 #include "clang/AST/CommentSema.h" 15 #include "clang/Basic/CommentOptions.h" 16 #include "clang/Basic/Diagnostic.h" 17 #include "clang/Basic/DiagnosticOptions.h" 18 #include "clang/Basic/FileManager.h" 19 #include "clang/Basic/SourceManager.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/Support/Allocator.h" 22 #include "gtest/gtest.h" 23 24 using namespace llvm; 25 using namespace clang; 26 27 namespace clang { 28 namespace comments { 29 30 namespace { 31 32 const bool DEBUG = true; 33 34 class CommentParserTest : public ::testing::Test { 35 protected: 36 CommentParserTest() 37 : FileMgr(FileMgrOpts), 38 DiagID(new DiagnosticIDs()), 39 Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), 40 SourceMgr(Diags, FileMgr), 41 Traits(Allocator, CommentOptions()) { 42 } 43 44 FileSystemOptions FileMgrOpts; 45 FileManager FileMgr; 46 IntrusiveRefCntPtr<DiagnosticIDs> DiagID; 47 DiagnosticsEngine Diags; 48 SourceManager SourceMgr; 49 llvm::BumpPtrAllocator Allocator; 50 CommandTraits Traits; 51 52 FullComment *parseString(const char *Source); 53 }; 54 55 FullComment *CommentParserTest::parseString(const char *Source) { 56 std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Source); 57 FileID File = SourceMgr.createFileID(std::move(Buf)); 58 SourceLocation Begin = SourceMgr.getLocForStartOfFile(File); 59 60 Lexer L(Allocator, Diags, Traits, Begin, Source, Source + strlen(Source)); 61 62 Sema S(Allocator, SourceMgr, Diags, Traits, /*PP=*/ nullptr); 63 Parser P(L, S, Allocator, SourceMgr, Diags, Traits); 64 FullComment *FC = P.parseFullComment(); 65 66 if (DEBUG) { 67 llvm::errs() << "=== Source:\n" << Source << "\n=== AST:\n"; 68 FC->dump(llvm::errs(), &Traits, &SourceMgr); 69 } 70 71 Token Tok; 72 L.lex(Tok); 73 if (Tok.is(tok::eof)) 74 return FC; 75 else 76 return nullptr; 77 } 78 79 ::testing::AssertionResult HasChildCount(const Comment *C, size_t Count) { 80 if (!C) 81 return ::testing::AssertionFailure() << "Comment is NULL"; 82 83 if (Count != C->child_count()) 84 return ::testing::AssertionFailure() 85 << "Count = " << Count 86 << ", child_count = " << C->child_count(); 87 88 return ::testing::AssertionSuccess(); 89 } 90 91 template <typename T> 92 ::testing::AssertionResult GetChildAt(const Comment *C, 93 size_t Idx, 94 T *&Child) { 95 if (!C) 96 return ::testing::AssertionFailure() << "Comment is NULL"; 97 98 if (Idx >= C->child_count()) 99 return ::testing::AssertionFailure() 100 << "Idx out of range. Idx = " << Idx 101 << ", child_count = " << C->child_count(); 102 103 Comment::child_iterator I = C->child_begin() + Idx; 104 Comment *CommentChild = *I; 105 if (!CommentChild) 106 return ::testing::AssertionFailure() << "Child is NULL"; 107 108 Child = dyn_cast<T>(CommentChild); 109 if (!Child) 110 return ::testing::AssertionFailure() 111 << "Child is not of requested type, but a " 112 << CommentChild->getCommentKindName(); 113 114 return ::testing::AssertionSuccess(); 115 } 116 117 ::testing::AssertionResult HasTextAt(const Comment *C, 118 size_t Idx, 119 StringRef Text) { 120 TextComment *TC; 121 ::testing::AssertionResult AR = GetChildAt(C, Idx, TC); 122 if (!AR) 123 return AR; 124 125 StringRef ActualText = TC->getText(); 126 if (ActualText != Text) 127 return ::testing::AssertionFailure() 128 << "TextComment has text \"" << ActualText.str() << "\", " 129 "expected \"" << Text.str() << "\""; 130 131 if (TC->hasTrailingNewline()) 132 return ::testing::AssertionFailure() 133 << "TextComment has a trailing newline"; 134 135 return ::testing::AssertionSuccess(); 136 } 137 138 ::testing::AssertionResult HasTextWithNewlineAt(const Comment *C, 139 size_t Idx, 140 StringRef Text) { 141 TextComment *TC; 142 ::testing::AssertionResult AR = GetChildAt(C, Idx, TC); 143 if (!AR) 144 return AR; 145 146 StringRef ActualText = TC->getText(); 147 if (ActualText != Text) 148 return ::testing::AssertionFailure() 149 << "TextComment has text \"" << ActualText.str() << "\", " 150 "expected \"" << Text.str() << "\""; 151 152 if (!TC->hasTrailingNewline()) 153 return ::testing::AssertionFailure() 154 << "TextComment has no trailing newline"; 155 156 return ::testing::AssertionSuccess(); 157 } 158 159 ::testing::AssertionResult HasBlockCommandAt(const Comment *C, 160 const CommandTraits &Traits, 161 size_t Idx, 162 BlockCommandComment *&BCC, 163 StringRef Name, 164 ParagraphComment *&Paragraph) { 165 ::testing::AssertionResult AR = GetChildAt(C, Idx, BCC); 166 if (!AR) 167 return AR; 168 169 StringRef ActualName = BCC->getCommandName(Traits); 170 if (ActualName != Name) 171 return ::testing::AssertionFailure() 172 << "BlockCommandComment has name \"" << ActualName.str() << "\", " 173 "expected \"" << Name.str() << "\""; 174 175 Paragraph = BCC->getParagraph(); 176 177 return ::testing::AssertionSuccess(); 178 } 179 180 ::testing::AssertionResult HasParamCommandAt( 181 const Comment *C, 182 const CommandTraits &Traits, 183 size_t Idx, 184 ParamCommandComment *&PCC, 185 StringRef CommandName, 186 ParamCommandComment::PassDirection Direction, 187 bool IsDirectionExplicit, 188 StringRef ParamName, 189 ParagraphComment *&Paragraph) { 190 ::testing::AssertionResult AR = GetChildAt(C, Idx, PCC); 191 if (!AR) 192 return AR; 193 194 StringRef ActualCommandName = PCC->getCommandName(Traits); 195 if (ActualCommandName != CommandName) 196 return ::testing::AssertionFailure() 197 << "ParamCommandComment has name \"" << ActualCommandName.str() << "\", " 198 "expected \"" << CommandName.str() << "\""; 199 200 if (PCC->getDirection() != Direction) 201 return ::testing::AssertionFailure() 202 << "ParamCommandComment has direction " << PCC->getDirection() << ", " 203 "expected " << Direction; 204 205 if (PCC->isDirectionExplicit() != IsDirectionExplicit) 206 return ::testing::AssertionFailure() 207 << "ParamCommandComment has " 208 << (PCC->isDirectionExplicit() ? "explicit" : "implicit") 209 << " direction, " 210 "expected " << (IsDirectionExplicit ? "explicit" : "implicit"); 211 212 if (!ParamName.empty() && !PCC->hasParamName()) 213 return ::testing::AssertionFailure() 214 << "ParamCommandComment has no parameter name"; 215 216 StringRef ActualParamName = PCC->hasParamName() ? PCC->getParamNameAsWritten() : ""; 217 if (ActualParamName != ParamName) 218 return ::testing::AssertionFailure() 219 << "ParamCommandComment has parameter name \"" << ActualParamName.str() 220 << "\", " 221 "expected \"" << ParamName.str() << "\""; 222 223 Paragraph = PCC->getParagraph(); 224 225 return ::testing::AssertionSuccess(); 226 } 227 228 ::testing::AssertionResult HasTParamCommandAt( 229 const Comment *C, 230 const CommandTraits &Traits, 231 size_t Idx, 232 TParamCommandComment *&TPCC, 233 StringRef CommandName, 234 StringRef ParamName, 235 ParagraphComment *&Paragraph) { 236 ::testing::AssertionResult AR = GetChildAt(C, Idx, TPCC); 237 if (!AR) 238 return AR; 239 240 StringRef ActualCommandName = TPCC->getCommandName(Traits); 241 if (ActualCommandName != CommandName) 242 return ::testing::AssertionFailure() 243 << "TParamCommandComment has name \"" << ActualCommandName.str() << "\", " 244 "expected \"" << CommandName.str() << "\""; 245 246 if (!ParamName.empty() && !TPCC->hasParamName()) 247 return ::testing::AssertionFailure() 248 << "TParamCommandComment has no parameter name"; 249 250 StringRef ActualParamName = TPCC->hasParamName() ? TPCC->getParamNameAsWritten() : ""; 251 if (ActualParamName != ParamName) 252 return ::testing::AssertionFailure() 253 << "TParamCommandComment has parameter name \"" << ActualParamName.str() 254 << "\", " 255 "expected \"" << ParamName.str() << "\""; 256 257 Paragraph = TPCC->getParagraph(); 258 259 return ::testing::AssertionSuccess(); 260 } 261 262 ::testing::AssertionResult HasInlineCommandAt(const Comment *C, 263 const CommandTraits &Traits, 264 size_t Idx, 265 InlineCommandComment *&ICC, 266 StringRef Name) { 267 ::testing::AssertionResult AR = GetChildAt(C, Idx, ICC); 268 if (!AR) 269 return AR; 270 271 StringRef ActualName = ICC->getCommandName(Traits); 272 if (ActualName != Name) 273 return ::testing::AssertionFailure() 274 << "InlineCommandComment has name \"" << ActualName.str() << "\", " 275 "expected \"" << Name.str() << "\""; 276 277 return ::testing::AssertionSuccess(); 278 } 279 280 struct NoArgs {}; 281 282 ::testing::AssertionResult HasInlineCommandAt(const Comment *C, 283 const CommandTraits &Traits, 284 size_t Idx, 285 InlineCommandComment *&ICC, 286 StringRef Name, 287 NoArgs) { 288 ::testing::AssertionResult AR = HasInlineCommandAt(C, Traits, Idx, ICC, Name); 289 if (!AR) 290 return AR; 291 292 if (ICC->getNumArgs() != 0) 293 return ::testing::AssertionFailure() 294 << "InlineCommandComment has " << ICC->getNumArgs() << " arg(s), " 295 "expected 0"; 296 297 return ::testing::AssertionSuccess(); 298 } 299 300 ::testing::AssertionResult HasInlineCommandAt(const Comment *C, 301 const CommandTraits &Traits, 302 size_t Idx, 303 InlineCommandComment *&ICC, 304 StringRef Name, 305 StringRef Arg) { 306 ::testing::AssertionResult AR = HasInlineCommandAt(C, Traits, Idx, ICC, Name); 307 if (!AR) 308 return AR; 309 310 if (ICC->getNumArgs() != 1) 311 return ::testing::AssertionFailure() 312 << "InlineCommandComment has " << ICC->getNumArgs() << " arg(s), " 313 "expected 1"; 314 315 StringRef ActualArg = ICC->getArgText(0); 316 if (ActualArg != Arg) 317 return ::testing::AssertionFailure() 318 << "InlineCommandComment has argument \"" << ActualArg.str() << "\", " 319 "expected \"" << Arg.str() << "\""; 320 321 return ::testing::AssertionSuccess(); 322 } 323 324 ::testing::AssertionResult HasHTMLStartTagAt(const Comment *C, 325 size_t Idx, 326 HTMLStartTagComment *&HST, 327 StringRef TagName) { 328 ::testing::AssertionResult AR = GetChildAt(C, Idx, HST); 329 if (!AR) 330 return AR; 331 332 StringRef ActualTagName = HST->getTagName(); 333 if (ActualTagName != TagName) 334 return ::testing::AssertionFailure() 335 << "HTMLStartTagComment has name \"" << ActualTagName.str() << "\", " 336 "expected \"" << TagName.str() << "\""; 337 338 return ::testing::AssertionSuccess(); 339 } 340 341 struct SelfClosing {}; 342 343 ::testing::AssertionResult HasHTMLStartTagAt(const Comment *C, 344 size_t Idx, 345 HTMLStartTagComment *&HST, 346 StringRef TagName, 347 SelfClosing) { 348 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName); 349 if (!AR) 350 return AR; 351 352 if (!HST->isSelfClosing()) 353 return ::testing::AssertionFailure() 354 << "HTMLStartTagComment is not self-closing"; 355 356 return ::testing::AssertionSuccess(); 357 } 358 359 360 struct NoAttrs {}; 361 362 ::testing::AssertionResult HasHTMLStartTagAt(const Comment *C, 363 size_t Idx, 364 HTMLStartTagComment *&HST, 365 StringRef TagName, 366 NoAttrs) { 367 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName); 368 if (!AR) 369 return AR; 370 371 if (HST->isSelfClosing()) 372 return ::testing::AssertionFailure() 373 << "HTMLStartTagComment is self-closing"; 374 375 if (HST->getNumAttrs() != 0) 376 return ::testing::AssertionFailure() 377 << "HTMLStartTagComment has " << HST->getNumAttrs() << " attr(s), " 378 "expected 0"; 379 380 return ::testing::AssertionSuccess(); 381 } 382 383 ::testing::AssertionResult HasHTMLStartTagAt(const Comment *C, 384 size_t Idx, 385 HTMLStartTagComment *&HST, 386 StringRef TagName, 387 StringRef AttrName, 388 StringRef AttrValue) { 389 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName); 390 if (!AR) 391 return AR; 392 393 if (HST->isSelfClosing()) 394 return ::testing::AssertionFailure() 395 << "HTMLStartTagComment is self-closing"; 396 397 if (HST->getNumAttrs() != 1) 398 return ::testing::AssertionFailure() 399 << "HTMLStartTagComment has " << HST->getNumAttrs() << " attr(s), " 400 "expected 1"; 401 402 StringRef ActualName = HST->getAttr(0).Name; 403 if (ActualName != AttrName) 404 return ::testing::AssertionFailure() 405 << "HTMLStartTagComment has attr \"" << ActualName.str() << "\", " 406 "expected \"" << AttrName.str() << "\""; 407 408 StringRef ActualValue = HST->getAttr(0).Value; 409 if (ActualValue != AttrValue) 410 return ::testing::AssertionFailure() 411 << "HTMLStartTagComment has attr value \"" << ActualValue.str() << "\", " 412 "expected \"" << AttrValue.str() << "\""; 413 414 return ::testing::AssertionSuccess(); 415 } 416 417 ::testing::AssertionResult HasHTMLEndTagAt(const Comment *C, 418 size_t Idx, 419 HTMLEndTagComment *&HET, 420 StringRef TagName) { 421 ::testing::AssertionResult AR = GetChildAt(C, Idx, HET); 422 if (!AR) 423 return AR; 424 425 StringRef ActualTagName = HET->getTagName(); 426 if (ActualTagName != TagName) 427 return ::testing::AssertionFailure() 428 << "HTMLEndTagComment has name \"" << ActualTagName.str() << "\", " 429 "expected \"" << TagName.str() << "\""; 430 431 return ::testing::AssertionSuccess(); 432 } 433 434 ::testing::AssertionResult HasParagraphCommentAt(const Comment *C, 435 size_t Idx, 436 StringRef Text) { 437 ParagraphComment *PC; 438 439 { 440 ::testing::AssertionResult AR = GetChildAt(C, Idx, PC); 441 if (!AR) 442 return AR; 443 } 444 445 { 446 ::testing::AssertionResult AR = HasChildCount(PC, 1); 447 if (!AR) 448 return AR; 449 } 450 451 { 452 ::testing::AssertionResult AR = HasTextAt(PC, 0, Text); 453 if (!AR) 454 return AR; 455 } 456 457 return ::testing::AssertionSuccess(); 458 } 459 460 ::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, 461 const CommandTraits &Traits, 462 size_t Idx, 463 VerbatimBlockComment *&VBC, 464 StringRef Name, 465 StringRef CloseName) { 466 ::testing::AssertionResult AR = GetChildAt(C, Idx, VBC); 467 if (!AR) 468 return AR; 469 470 StringRef ActualName = VBC->getCommandName(Traits); 471 if (ActualName != Name) 472 return ::testing::AssertionFailure() 473 << "VerbatimBlockComment has name \"" << ActualName.str() << "\", " 474 "expected \"" << Name.str() << "\""; 475 476 StringRef ActualCloseName = VBC->getCloseName(); 477 if (ActualCloseName != CloseName) 478 return ::testing::AssertionFailure() 479 << "VerbatimBlockComment has closing command name \"" 480 << ActualCloseName.str() << "\", " 481 "expected \"" << CloseName.str() << "\""; 482 483 return ::testing::AssertionSuccess(); 484 } 485 486 struct NoLines {}; 487 struct Lines {}; 488 489 ::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, 490 const CommandTraits &Traits, 491 size_t Idx, 492 VerbatimBlockComment *&VBC, 493 StringRef Name, 494 StringRef CloseName, 495 NoLines) { 496 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name, 497 CloseName); 498 if (!AR) 499 return AR; 500 501 if (VBC->getNumLines() != 0) 502 return ::testing::AssertionFailure() 503 << "VerbatimBlockComment has " << VBC->getNumLines() << " lines(s), " 504 "expected 0"; 505 506 return ::testing::AssertionSuccess(); 507 } 508 509 ::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, 510 const CommandTraits &Traits, 511 size_t Idx, 512 VerbatimBlockComment *&VBC, 513 StringRef Name, 514 StringRef CloseName, 515 Lines, 516 StringRef Line0) { 517 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name, 518 CloseName); 519 if (!AR) 520 return AR; 521 522 if (VBC->getNumLines() != 1) 523 return ::testing::AssertionFailure() 524 << "VerbatimBlockComment has " << VBC->getNumLines() << " lines(s), " 525 "expected 1"; 526 527 StringRef ActualLine0 = VBC->getText(0); 528 if (ActualLine0 != Line0) 529 return ::testing::AssertionFailure() 530 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", " 531 "expected \"" << Line0.str() << "\""; 532 533 return ::testing::AssertionSuccess(); 534 } 535 536 ::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, 537 const CommandTraits &Traits, 538 size_t Idx, 539 VerbatimBlockComment *&VBC, 540 StringRef Name, 541 StringRef CloseName, 542 Lines, 543 StringRef Line0, 544 StringRef Line1) { 545 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name, 546 CloseName); 547 if (!AR) 548 return AR; 549 550 if (VBC->getNumLines() != 2) 551 return ::testing::AssertionFailure() 552 << "VerbatimBlockComment has " << VBC->getNumLines() << " lines(s), " 553 "expected 2"; 554 555 StringRef ActualLine0 = VBC->getText(0); 556 if (ActualLine0 != Line0) 557 return ::testing::AssertionFailure() 558 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", " 559 "expected \"" << Line0.str() << "\""; 560 561 StringRef ActualLine1 = VBC->getText(1); 562 if (ActualLine1 != Line1) 563 return ::testing::AssertionFailure() 564 << "VerbatimBlockComment has lines[1] \"" << ActualLine1.str() << "\", " 565 "expected \"" << Line1.str() << "\""; 566 567 return ::testing::AssertionSuccess(); 568 } 569 570 ::testing::AssertionResult HasVerbatimLineAt(const Comment *C, 571 const CommandTraits &Traits, 572 size_t Idx, 573 VerbatimLineComment *&VLC, 574 StringRef Name, 575 StringRef Text) { 576 ::testing::AssertionResult AR = GetChildAt(C, Idx, VLC); 577 if (!AR) 578 return AR; 579 580 StringRef ActualName = VLC->getCommandName(Traits); 581 if (ActualName != Name) 582 return ::testing::AssertionFailure() 583 << "VerbatimLineComment has name \"" << ActualName.str() << "\", " 584 "expected \"" << Name.str() << "\""; 585 586 StringRef ActualText = VLC->getText(); 587 if (ActualText != Text) 588 return ::testing::AssertionFailure() 589 << "VerbatimLineComment has text \"" << ActualText.str() << "\", " 590 "expected \"" << Text.str() << "\""; 591 592 return ::testing::AssertionSuccess(); 593 } 594 595 596 TEST_F(CommentParserTest, Basic1) { 597 const char *Source = "//"; 598 599 FullComment *FC = parseString(Source); 600 ASSERT_TRUE(HasChildCount(FC, 0)); 601 } 602 603 TEST_F(CommentParserTest, Basic2) { 604 const char *Source = "// Meow"; 605 606 FullComment *FC = parseString(Source); 607 ASSERT_TRUE(HasChildCount(FC, 1)); 608 609 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " Meow")); 610 } 611 612 TEST_F(CommentParserTest, Basic3) { 613 const char *Source = 614 "// Aaa\n" 615 "// Bbb"; 616 617 FullComment *FC = parseString(Source); 618 ASSERT_TRUE(HasChildCount(FC, 1)); 619 620 { 621 ParagraphComment *PC; 622 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 623 624 ASSERT_TRUE(HasChildCount(PC, 2)); 625 ASSERT_TRUE(HasTextWithNewlineAt(PC, 0, " Aaa")); 626 ASSERT_TRUE(HasTextAt(PC, 1, " Bbb")); 627 } 628 } 629 630 TEST_F(CommentParserTest, ParagraphSplitting1) { 631 const char *Sources[] = { 632 "// Aaa\n" 633 "//\n" 634 "// Bbb", 635 636 "// Aaa\n" 637 "// \n" 638 "// Bbb", 639 640 "// Aaa\n" 641 "//\t\n" 642 "// Bbb", 643 644 "// Aaa\n" 645 "//\n" 646 "//\n" 647 "// Bbb", 648 649 "/**\n" 650 " Aaa\n" 651 "\n" 652 " Bbb\n" 653 "*/", 654 655 "/**\n" 656 " Aaa\n" 657 " \n" 658 " Bbb\n" 659 "*/", 660 661 "/**\n" 662 " Aaa\n" 663 "\t \n" 664 " Bbb\n" 665 "*/", 666 }; 667 668 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 669 FullComment *FC = parseString(Sources[i]); 670 ASSERT_TRUE(HasChildCount(FC, 2)); 671 672 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " Aaa")); 673 ASSERT_TRUE(HasParagraphCommentAt(FC, 1, " Bbb")); 674 } 675 } 676 677 TEST_F(CommentParserTest, Paragraph1) { 678 const char *Source = 679 "// \\brief Aaa\n" 680 "//\n" 681 "// Bbb"; 682 683 FullComment *FC = parseString(Source); 684 ASSERT_TRUE(HasChildCount(FC, 3)); 685 686 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 687 { 688 BlockCommandComment *BCC; 689 ParagraphComment *PC; 690 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC)); 691 692 ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Aaa")); 693 } 694 ASSERT_TRUE(HasParagraphCommentAt(FC, 2, " Bbb")); 695 } 696 697 TEST_F(CommentParserTest, Paragraph2) { 698 const char *Source = "// \\brief \\author"; 699 700 FullComment *FC = parseString(Source); 701 ASSERT_TRUE(HasChildCount(FC, 3)); 702 703 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 704 { 705 BlockCommandComment *BCC; 706 ParagraphComment *PC; 707 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC)); 708 709 ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " ")); 710 } 711 { 712 BlockCommandComment *BCC; 713 ParagraphComment *PC; 714 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "author", PC)); 715 716 ASSERT_TRUE(GetChildAt(BCC, 0, PC)); 717 ASSERT_TRUE(HasChildCount(PC, 0)); 718 } 719 } 720 721 TEST_F(CommentParserTest, Paragraph3) { 722 const char *Source = 723 "// \\brief Aaa\n" 724 "// Bbb \\author\n" 725 "// Ccc"; 726 727 FullComment *FC = parseString(Source); 728 ASSERT_TRUE(HasChildCount(FC, 3)); 729 730 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 731 { 732 BlockCommandComment *BCC; 733 ParagraphComment *PC; 734 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC)); 735 736 ASSERT_TRUE(GetChildAt(BCC, 0, PC)); 737 ASSERT_TRUE(HasChildCount(PC, 2)); 738 ASSERT_TRUE(HasTextWithNewlineAt(PC, 0, " Aaa")); 739 ASSERT_TRUE(HasTextAt(PC, 1, " Bbb ")); 740 } 741 { 742 BlockCommandComment *BCC; 743 ParagraphComment *PC; 744 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "author", PC)); 745 746 ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Ccc")); 747 } 748 } 749 750 TEST_F(CommentParserTest, ParamCommand1) { 751 const char *Source = "// \\param aaa"; 752 753 FullComment *FC = parseString(Source); 754 ASSERT_TRUE(HasChildCount(FC, 2)); 755 756 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 757 { 758 ParamCommandComment *PCC; 759 ParagraphComment *PC; 760 ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", 761 ParamCommandComment::In, 762 /* IsDirectionExplicit = */ false, 763 "aaa", PC)); 764 ASSERT_TRUE(HasChildCount(PCC, 1)); 765 ASSERT_TRUE(HasChildCount(PC, 0)); 766 } 767 } 768 769 TEST_F(CommentParserTest, ParamCommand2) { 770 const char *Source = "// \\param\\brief"; 771 772 FullComment *FC = parseString(Source); 773 ASSERT_TRUE(HasChildCount(FC, 3)); 774 775 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 776 { 777 ParamCommandComment *PCC; 778 ParagraphComment *PC; 779 ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", 780 ParamCommandComment::In, 781 /* IsDirectionExplicit = */ false, 782 "", PC)); 783 ASSERT_TRUE(HasChildCount(PCC, 1)); 784 ASSERT_TRUE(HasChildCount(PC, 0)); 785 } 786 { 787 BlockCommandComment *BCC; 788 ParagraphComment *PC; 789 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "brief", PC)); 790 ASSERT_TRUE(HasChildCount(PC, 0)); 791 } 792 } 793 794 TEST_F(CommentParserTest, ParamCommand3) { 795 const char *Sources[] = { 796 "// \\param aaa Bbb\n", 797 "// \\param\n" 798 "// aaa Bbb\n", 799 "// \\param \n" 800 "// aaa Bbb\n", 801 "// \\param aaa\n" 802 "// Bbb\n" 803 }; 804 805 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 806 FullComment *FC = parseString(Sources[i]); 807 ASSERT_TRUE(HasChildCount(FC, 2)); 808 809 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 810 { 811 ParamCommandComment *PCC; 812 ParagraphComment *PC; 813 ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", 814 ParamCommandComment::In, 815 /* IsDirectionExplicit = */ false, 816 "aaa", PC)); 817 ASSERT_TRUE(HasChildCount(PCC, 1)); 818 ASSERT_TRUE(HasParagraphCommentAt(PCC, 0, " Bbb")); 819 } 820 } 821 } 822 823 TEST_F(CommentParserTest, ParamCommand4) { 824 const char *Sources[] = { 825 "// \\param [in] aaa Bbb\n", 826 "// \\param[in] aaa Bbb\n", 827 "// \\param\n" 828 "// [in] aaa Bbb\n", 829 "// \\param [in]\n" 830 "// aaa Bbb\n", 831 "// \\param [in] aaa\n" 832 "// Bbb\n", 833 }; 834 835 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 836 FullComment *FC = parseString(Sources[i]); 837 ASSERT_TRUE(HasChildCount(FC, 2)); 838 839 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 840 { 841 ParamCommandComment *PCC; 842 ParagraphComment *PC; 843 ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", 844 ParamCommandComment::In, 845 /* IsDirectionExplicit = */ true, 846 "aaa", PC)); 847 ASSERT_TRUE(HasChildCount(PCC, 1)); 848 ASSERT_TRUE(HasParagraphCommentAt(PCC, 0, " Bbb")); 849 } 850 } 851 } 852 853 TEST_F(CommentParserTest, ParamCommand5) { 854 const char *Sources[] = { 855 "// \\param [out] aaa Bbb\n", 856 "// \\param[out] aaa Bbb\n", 857 "// \\param\n" 858 "// [out] aaa Bbb\n", 859 "// \\param [out]\n" 860 "// aaa Bbb\n", 861 "// \\param [out] aaa\n" 862 "// Bbb\n", 863 }; 864 865 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 866 FullComment *FC = parseString(Sources[i]); 867 ASSERT_TRUE(HasChildCount(FC, 2)); 868 869 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 870 { 871 ParamCommandComment *PCC; 872 ParagraphComment *PC; 873 ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", 874 ParamCommandComment::Out, 875 /* IsDirectionExplicit = */ true, 876 "aaa", PC)); 877 ASSERT_TRUE(HasChildCount(PCC, 1)); 878 ASSERT_TRUE(HasParagraphCommentAt(PCC, 0, " Bbb")); 879 } 880 } 881 } 882 883 TEST_F(CommentParserTest, ParamCommand6) { 884 const char *Sources[] = { 885 "// \\param [in,out] aaa Bbb\n", 886 "// \\param[in,out] aaa Bbb\n", 887 "// \\param [in, out] aaa Bbb\n", 888 "// \\param [in,\n" 889 "// out] aaa Bbb\n", 890 "// \\param [in,out]\n" 891 "// aaa Bbb\n", 892 "// \\param [in,out] aaa\n" 893 "// Bbb\n" 894 }; 895 896 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 897 FullComment *FC = parseString(Sources[i]); 898 ASSERT_TRUE(HasChildCount(FC, 2)); 899 900 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 901 { 902 ParamCommandComment *PCC; 903 ParagraphComment *PC; 904 ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", 905 ParamCommandComment::InOut, 906 /* IsDirectionExplicit = */ true, 907 "aaa", PC)); 908 ASSERT_TRUE(HasChildCount(PCC, 1)); 909 ASSERT_TRUE(HasParagraphCommentAt(PCC, 0, " Bbb")); 910 } 911 } 912 } 913 914 TEST_F(CommentParserTest, ParamCommand7) { 915 const char *Source = 916 "// \\param aaa \\% Bbb \\$ ccc\n"; 917 918 FullComment *FC = parseString(Source); 919 ASSERT_TRUE(HasChildCount(FC, 2)); 920 921 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 922 { 923 ParamCommandComment *PCC; 924 ParagraphComment *PC; 925 ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", 926 ParamCommandComment::In, 927 /* IsDirectionExplicit = */ false, 928 "aaa", PC)); 929 ASSERT_TRUE(HasChildCount(PCC, 1)); 930 931 ASSERT_TRUE(HasChildCount(PC, 5)); 932 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 933 ASSERT_TRUE(HasTextAt(PC, 1, "%")); 934 ASSERT_TRUE(HasTextAt(PC, 2, " Bbb ")); 935 ASSERT_TRUE(HasTextAt(PC, 3, "$")); 936 ASSERT_TRUE(HasTextAt(PC, 4, " ccc")); 937 } 938 } 939 940 TEST_F(CommentParserTest, TParamCommand1) { 941 const char *Sources[] = { 942 "// \\tparam aaa Bbb\n", 943 "// \\tparam\n" 944 "// aaa Bbb\n", 945 "// \\tparam \n" 946 "// aaa Bbb\n", 947 "// \\tparam aaa\n" 948 "// Bbb\n" 949 }; 950 951 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 952 FullComment *FC = parseString(Sources[i]); 953 ASSERT_TRUE(HasChildCount(FC, 2)); 954 955 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 956 { 957 TParamCommandComment *TPCC; 958 ParagraphComment *PC; 959 ASSERT_TRUE(HasTParamCommandAt(FC, Traits, 1, TPCC, "tparam", 960 "aaa", PC)); 961 ASSERT_TRUE(HasChildCount(TPCC, 1)); 962 ASSERT_TRUE(HasParagraphCommentAt(TPCC, 0, " Bbb")); 963 } 964 } 965 } 966 967 TEST_F(CommentParserTest, TParamCommand2) { 968 const char *Source = "// \\tparam\\brief"; 969 970 FullComment *FC = parseString(Source); 971 ASSERT_TRUE(HasChildCount(FC, 3)); 972 973 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 974 { 975 TParamCommandComment *TPCC; 976 ParagraphComment *PC; 977 ASSERT_TRUE(HasTParamCommandAt(FC, Traits, 1, TPCC, "tparam", "", PC)); 978 ASSERT_TRUE(HasChildCount(TPCC, 1)); 979 ASSERT_TRUE(HasChildCount(PC, 0)); 980 } 981 { 982 BlockCommandComment *BCC; 983 ParagraphComment *PC; 984 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "brief", PC)); 985 ASSERT_TRUE(HasChildCount(PC, 0)); 986 } 987 } 988 989 990 TEST_F(CommentParserTest, InlineCommand1) { 991 const char *Source = "// \\c"; 992 993 FullComment *FC = parseString(Source); 994 ASSERT_TRUE(HasChildCount(FC, 1)); 995 996 { 997 ParagraphComment *PC; 998 InlineCommandComment *ICC; 999 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1000 1001 ASSERT_TRUE(HasChildCount(PC, 2)); 1002 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1003 ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", NoArgs())); 1004 } 1005 } 1006 1007 TEST_F(CommentParserTest, InlineCommand2) { 1008 const char *Source = "// \\c "; 1009 1010 FullComment *FC = parseString(Source); 1011 ASSERT_TRUE(HasChildCount(FC, 1)); 1012 1013 { 1014 ParagraphComment *PC; 1015 InlineCommandComment *ICC; 1016 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1017 1018 ASSERT_TRUE(HasChildCount(PC, 3)); 1019 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1020 ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", NoArgs())); 1021 ASSERT_TRUE(HasTextAt(PC, 2, " ")); 1022 } 1023 } 1024 1025 TEST_F(CommentParserTest, InlineCommand3) { 1026 const char *Source = "// \\c aaa\n"; 1027 1028 FullComment *FC = parseString(Source); 1029 ASSERT_TRUE(HasChildCount(FC, 1)); 1030 1031 { 1032 ParagraphComment *PC; 1033 InlineCommandComment *ICC; 1034 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1035 1036 ASSERT_TRUE(HasChildCount(PC, 2)); 1037 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1038 ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", "aaa")); 1039 } 1040 } 1041 1042 TEST_F(CommentParserTest, InlineCommand4) { 1043 const char *Source = "// \\c aaa bbb"; 1044 1045 FullComment *FC = parseString(Source); 1046 ASSERT_TRUE(HasChildCount(FC, 1)); 1047 1048 { 1049 ParagraphComment *PC; 1050 InlineCommandComment *ICC; 1051 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1052 1053 ASSERT_TRUE(HasChildCount(PC, 3)); 1054 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1055 ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", "aaa")); 1056 ASSERT_TRUE(HasTextAt(PC, 2, " bbb")); 1057 } 1058 } 1059 1060 TEST_F(CommentParserTest, InlineCommand5) { 1061 const char *Source = "// \\unknown aaa\n"; 1062 1063 FullComment *FC = parseString(Source); 1064 ASSERT_TRUE(HasChildCount(FC, 1)); 1065 1066 { 1067 ParagraphComment *PC; 1068 InlineCommandComment *ICC; 1069 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1070 1071 ASSERT_TRUE(HasChildCount(PC, 3)); 1072 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1073 ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "unknown", NoArgs())); 1074 ASSERT_TRUE(HasTextAt(PC, 2, " aaa")); 1075 } 1076 } 1077 1078 TEST_F(CommentParserTest, HTML1) { 1079 const char *Sources[] = { 1080 "// <a", 1081 "// <a>", 1082 "// <a >" 1083 }; 1084 1085 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1086 FullComment *FC = parseString(Sources[i]); 1087 ASSERT_TRUE(HasChildCount(FC, 1)); 1088 1089 { 1090 ParagraphComment *PC; 1091 HTMLStartTagComment *HST; 1092 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1093 1094 ASSERT_TRUE(HasChildCount(PC, 2)); 1095 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1096 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", NoAttrs())); 1097 } 1098 } 1099 } 1100 1101 TEST_F(CommentParserTest, HTML2) { 1102 const char *Sources[] = { 1103 "// <br/>", 1104 "// <br />" 1105 }; 1106 1107 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1108 FullComment *FC = parseString(Sources[i]); 1109 ASSERT_TRUE(HasChildCount(FC, 1)); 1110 1111 { 1112 ParagraphComment *PC; 1113 HTMLStartTagComment *HST; 1114 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1115 1116 ASSERT_TRUE(HasChildCount(PC, 2)); 1117 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1118 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "br", SelfClosing())); 1119 } 1120 } 1121 } 1122 1123 TEST_F(CommentParserTest, HTML3) { 1124 const char *Sources[] = { 1125 "// <a href", 1126 "// <a href ", 1127 "// <a href>", 1128 "// <a href >", 1129 }; 1130 1131 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1132 FullComment *FC = parseString(Sources[i]); 1133 ASSERT_TRUE(HasChildCount(FC, 1)); 1134 1135 { 1136 ParagraphComment *PC; 1137 HTMLStartTagComment *HST; 1138 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1139 1140 ASSERT_TRUE(HasChildCount(PC, 2)); 1141 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1142 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", "href", "")); 1143 } 1144 } 1145 } 1146 1147 TEST_F(CommentParserTest, HTML4) { 1148 const char *Sources[] = { 1149 "// <a href=\"bbb\"", 1150 "// <a href=\"bbb\">", 1151 }; 1152 1153 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1154 FullComment *FC = parseString(Sources[i]); 1155 ASSERT_TRUE(HasChildCount(FC, 1)); 1156 1157 { 1158 ParagraphComment *PC; 1159 HTMLStartTagComment *HST; 1160 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1161 1162 ASSERT_TRUE(HasChildCount(PC, 2)); 1163 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1164 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", "href", "bbb")); 1165 } 1166 } 1167 } 1168 1169 TEST_F(CommentParserTest, HTML5) { 1170 const char *Sources[] = { 1171 "// </a", 1172 "// </a>", 1173 "// </a >" 1174 }; 1175 1176 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1177 FullComment *FC = parseString(Sources[i]); 1178 ASSERT_TRUE(HasChildCount(FC, 1)); 1179 1180 { 1181 ParagraphComment *PC; 1182 HTMLEndTagComment *HET; 1183 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1184 1185 ASSERT_TRUE(HasChildCount(PC, 2)); 1186 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1187 ASSERT_TRUE(HasHTMLEndTagAt(PC, 1, HET, "a")); 1188 } 1189 } 1190 } 1191 1192 TEST_F(CommentParserTest, HTML6) { 1193 const char *Source = 1194 "// <pre>\n" 1195 "// Aaa\n" 1196 "// Bbb\n" 1197 "// </pre>\n"; 1198 1199 FullComment *FC = parseString(Source); 1200 ASSERT_TRUE(HasChildCount(FC, 1)); 1201 1202 { 1203 ParagraphComment *PC; 1204 HTMLStartTagComment *HST; 1205 HTMLEndTagComment *HET; 1206 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 1207 1208 ASSERT_TRUE(HasChildCount(PC, 6)); 1209 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 1210 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "pre", NoAttrs())); 1211 ASSERT_TRUE(HasTextWithNewlineAt(PC, 2, " Aaa")); 1212 ASSERT_TRUE(HasTextWithNewlineAt(PC, 3, " Bbb")); 1213 ASSERT_TRUE(HasTextAt(PC, 4, " ")); 1214 ASSERT_TRUE(HasHTMLEndTagAt(PC, 5, HET, "pre")); 1215 } 1216 } 1217 1218 TEST_F(CommentParserTest, VerbatimBlock1) { 1219 const char *Source = "// \\verbatim\\endverbatim\n"; 1220 1221 FullComment *FC = parseString(Source); 1222 ASSERT_TRUE(HasChildCount(FC, 2)); 1223 1224 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1225 { 1226 VerbatimBlockComment *VCC; 1227 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VCC, 1228 "verbatim", "endverbatim", 1229 NoLines())); 1230 } 1231 } 1232 1233 TEST_F(CommentParserTest, VerbatimBlock2) { 1234 const char *Source = "// \\verbatim Aaa \\endverbatim\n"; 1235 1236 FullComment *FC = parseString(Source); 1237 ASSERT_TRUE(HasChildCount(FC, 2)); 1238 1239 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1240 { 1241 VerbatimBlockComment *VBC; 1242 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, 1243 "verbatim", "endverbatim", 1244 Lines(), " Aaa ")); 1245 } 1246 } 1247 1248 TEST_F(CommentParserTest, VerbatimBlock3) { 1249 const char *Source = "// \\verbatim Aaa\n"; 1250 1251 FullComment *FC = parseString(Source); 1252 ASSERT_TRUE(HasChildCount(FC, 2)); 1253 1254 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1255 { 1256 VerbatimBlockComment *VBC; 1257 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, "verbatim", "", 1258 Lines(), " Aaa")); 1259 } 1260 } 1261 1262 TEST_F(CommentParserTest, VerbatimBlock4) { 1263 const char *Source = 1264 "//\\verbatim\n" 1265 "//\\endverbatim\n"; 1266 1267 FullComment *FC = parseString(Source); 1268 ASSERT_TRUE(HasChildCount(FC, 1)); 1269 1270 { 1271 VerbatimBlockComment *VBC; 1272 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 0, VBC, 1273 "verbatim", "endverbatim", 1274 NoLines())); 1275 } 1276 } 1277 1278 TEST_F(CommentParserTest, VerbatimBlock5) { 1279 const char *Sources[] = { 1280 "//\\verbatim\n" 1281 "// Aaa\n" 1282 "//\\endverbatim\n", 1283 1284 "/*\\verbatim\n" 1285 " * Aaa\n" 1286 " *\\endverbatim*/" 1287 }; 1288 1289 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1290 FullComment *FC = parseString(Sources[i]); 1291 ASSERT_TRUE(HasChildCount(FC, 1)); 1292 1293 { 1294 VerbatimBlockComment *VBC; 1295 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 0, VBC, 1296 "verbatim", "endverbatim", 1297 Lines(), " Aaa")); 1298 } 1299 } 1300 } 1301 1302 TEST_F(CommentParserTest, VerbatimBlock6) { 1303 const char *Sources[] = { 1304 "// \\verbatim\n" 1305 "// Aaa\n" 1306 "// \\endverbatim\n", 1307 1308 "/* \\verbatim\n" 1309 " * Aaa\n" 1310 " * \\endverbatim*/" 1311 }; 1312 1313 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1314 FullComment *FC = parseString(Sources[i]); 1315 ASSERT_TRUE(HasChildCount(FC, 2)); 1316 1317 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1318 { 1319 VerbatimBlockComment *VBC; 1320 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, 1321 "verbatim", "endverbatim", 1322 Lines(), " Aaa")); 1323 } 1324 } 1325 } 1326 1327 TEST_F(CommentParserTest, VerbatimBlock7) { 1328 const char *Sources[] = { 1329 "// \\verbatim\n" 1330 "// Aaa\n" 1331 "// Bbb\n" 1332 "// \\endverbatim\n", 1333 1334 "/* \\verbatim\n" 1335 " * Aaa\n" 1336 " * Bbb\n" 1337 " * \\endverbatim*/" 1338 }; 1339 1340 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1341 FullComment *FC = parseString(Sources[i]); 1342 ASSERT_TRUE(HasChildCount(FC, 2)); 1343 1344 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1345 { 1346 VerbatimBlockComment *VBC; 1347 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, 1348 "verbatim", "endverbatim", 1349 Lines(), " Aaa", " Bbb")); 1350 } 1351 } 1352 } 1353 1354 TEST_F(CommentParserTest, VerbatimBlock8) { 1355 const char *Sources[] = { 1356 "// \\verbatim\n" 1357 "// Aaa\n" 1358 "//\n" 1359 "// Bbb\n" 1360 "// \\endverbatim\n", 1361 1362 "/* \\verbatim\n" 1363 " * Aaa\n" 1364 " *\n" 1365 " * Bbb\n" 1366 " * \\endverbatim*/" 1367 }; 1368 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1369 FullComment *FC = parseString(Sources[i]); 1370 ASSERT_TRUE(HasChildCount(FC, 2)); 1371 1372 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1373 { 1374 VerbatimBlockComment *VBC; 1375 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, 1376 "verbatim", "endverbatim")); 1377 ASSERT_EQ(3U, VBC->getNumLines()); 1378 ASSERT_EQ(" Aaa", VBC->getText(0)); 1379 ASSERT_EQ("", VBC->getText(1)); 1380 ASSERT_EQ(" Bbb", VBC->getText(2)); 1381 } 1382 } 1383 } 1384 1385 TEST_F(CommentParserTest, VerbatimLine1) { 1386 const char *Sources[] = { 1387 "// \\fn", 1388 "// \\fn\n" 1389 }; 1390 1391 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1392 FullComment *FC = parseString(Sources[i]); 1393 ASSERT_TRUE(HasChildCount(FC, 2)); 1394 1395 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1396 { 1397 VerbatimLineComment *VLC; 1398 ASSERT_TRUE(HasVerbatimLineAt(FC, Traits, 1, VLC, "fn", "")); 1399 } 1400 } 1401 } 1402 1403 TEST_F(CommentParserTest, VerbatimLine2) { 1404 const char *Sources[] = { 1405 "/// \\fn void *foo(const char *zzz = \"\\$\");\n//", 1406 "/** \\fn void *foo(const char *zzz = \"\\$\");*/" 1407 }; 1408 1409 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1410 FullComment *FC = parseString(Sources[i]); 1411 ASSERT_TRUE(HasChildCount(FC, 2)); 1412 1413 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1414 { 1415 VerbatimLineComment *VLC; 1416 ASSERT_TRUE(HasVerbatimLineAt(FC, Traits, 1, VLC, "fn", 1417 " void *foo(const char *zzz = \"\\$\");")); 1418 } 1419 } 1420 } 1421 1422 TEST_F(CommentParserTest, Deprecated) { 1423 const char *Sources[] = { 1424 "/** @deprecated*/", 1425 "/// @deprecated\n" 1426 }; 1427 1428 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1429 FullComment *FC = parseString(Sources[i]); 1430 ASSERT_TRUE(HasChildCount(FC, 2)); 1431 1432 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1433 { 1434 BlockCommandComment *BCC; 1435 ParagraphComment *PC; 1436 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "deprecated", PC)); 1437 ASSERT_TRUE(HasChildCount(PC, 0)); 1438 } 1439 } 1440 } 1441 1442 } // unnamed namespace 1443 1444 } // end namespace comments 1445 } // end namespace clang 1446 1447