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