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