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