CommentParser.cpp revision debd16f75fdfa3fb0a498f89450ea574dfb3af4e
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(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 StringRef ActualParamName = PCC->getParamName(); 209 if (ActualParamName != ParamName) 210 return ::testing::AssertionFailure() 211 << "ParamCommandComment has name \"" << ActualParamName.str() << "\", " 212 "expected \"" << ParamName.str() << "\""; 213 214 Paragraph = PCC->getParagraph(); 215 216 return ::testing::AssertionSuccess(); 217} 218 219::testing::AssertionResult HasInlineCommandAt(const Comment *C, 220 size_t Idx, 221 InlineCommandComment *&ICC, 222 StringRef Name) { 223 ::testing::AssertionResult AR = GetChildAt(C, Idx, ICC); 224 if (!AR) 225 return AR; 226 227 StringRef ActualName = ICC->getCommandName(); 228 if (ActualName != Name) 229 return ::testing::AssertionFailure() 230 << "InlineCommandComment has name \"" << ActualName.str() << "\", " 231 "expected \"" << Name.str() << "\""; 232 233 return ::testing::AssertionSuccess(); 234} 235 236struct NoArgs {}; 237 238::testing::AssertionResult HasInlineCommandAt(const Comment *C, 239 size_t Idx, 240 InlineCommandComment *&ICC, 241 StringRef Name, 242 NoArgs) { 243 ::testing::AssertionResult AR = HasInlineCommandAt(C, Idx, ICC, Name); 244 if (!AR) 245 return AR; 246 247 if (ICC->getNumArgs() != 0) 248 return ::testing::AssertionFailure() 249 << "InlineCommandComment has " << ICC->getNumArgs() << " arg(s), " 250 "expected 0"; 251 252 return ::testing::AssertionSuccess(); 253} 254 255::testing::AssertionResult HasInlineCommandAt(const Comment *C, 256 size_t Idx, 257 InlineCommandComment *&ICC, 258 StringRef Name, 259 StringRef Arg) { 260 ::testing::AssertionResult AR = HasInlineCommandAt(C, Idx, ICC, Name); 261 if (!AR) 262 return AR; 263 264 if (ICC->getNumArgs() != 1) 265 return ::testing::AssertionFailure() 266 << "InlineCommandComment has " << ICC->getNumArgs() << " arg(s), " 267 "expected 1"; 268 269 StringRef ActualArg = ICC->getArgText(0); 270 if (ActualArg != Arg) 271 return ::testing::AssertionFailure() 272 << "InlineCommandComment has argument \"" << ActualArg.str() << "\", " 273 "expected \"" << Arg.str() << "\""; 274 275 return ::testing::AssertionSuccess(); 276} 277 278::testing::AssertionResult HasHTMLStartTagAt(const Comment *C, 279 size_t Idx, 280 HTMLStartTagComment *&HST, 281 StringRef TagName) { 282 ::testing::AssertionResult AR = GetChildAt(C, Idx, HST); 283 if (!AR) 284 return AR; 285 286 StringRef ActualTagName = HST->getTagName(); 287 if (ActualTagName != TagName) 288 return ::testing::AssertionFailure() 289 << "HTMLStartTagComment has name \"" << ActualTagName.str() << "\", " 290 "expected \"" << TagName.str() << "\""; 291 292 return ::testing::AssertionSuccess(); 293} 294 295struct SelfClosing {}; 296 297::testing::AssertionResult HasHTMLStartTagAt(const Comment *C, 298 size_t Idx, 299 HTMLStartTagComment *&HST, 300 StringRef TagName, 301 SelfClosing) { 302 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName); 303 if (!AR) 304 return AR; 305 306 if (!HST->isSelfClosing()) 307 return ::testing::AssertionFailure() 308 << "HTMLStartTagComment is not self-closing"; 309 310 return ::testing::AssertionSuccess(); 311} 312 313 314struct NoAttrs {}; 315 316::testing::AssertionResult HasHTMLStartTagAt(const Comment *C, 317 size_t Idx, 318 HTMLStartTagComment *&HST, 319 StringRef TagName, 320 NoAttrs) { 321 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName); 322 if (!AR) 323 return AR; 324 325 if (HST->isSelfClosing()) 326 return ::testing::AssertionFailure() 327 << "HTMLStartTagComment is self-closing"; 328 329 if (HST->getNumAttrs() != 0) 330 return ::testing::AssertionFailure() 331 << "HTMLStartTagComment has " << HST->getNumAttrs() << " attr(s), " 332 "expected 0"; 333 334 return ::testing::AssertionSuccess(); 335} 336 337::testing::AssertionResult HasHTMLStartTagAt(const Comment *C, 338 size_t Idx, 339 HTMLStartTagComment *&HST, 340 StringRef TagName, 341 StringRef AttrName, 342 StringRef AttrValue) { 343 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName); 344 if (!AR) 345 return AR; 346 347 if (HST->isSelfClosing()) 348 return ::testing::AssertionFailure() 349 << "HTMLStartTagComment is self-closing"; 350 351 if (HST->getNumAttrs() != 1) 352 return ::testing::AssertionFailure() 353 << "HTMLStartTagComment has " << HST->getNumAttrs() << " attr(s), " 354 "expected 1"; 355 356 StringRef ActualName = HST->getAttr(0).Name; 357 if (ActualName != AttrName) 358 return ::testing::AssertionFailure() 359 << "HTMLStartTagComment has attr \"" << ActualName.str() << "\", " 360 "expected \"" << AttrName.str() << "\""; 361 362 StringRef ActualValue = HST->getAttr(0).Value; 363 if (ActualValue != AttrValue) 364 return ::testing::AssertionFailure() 365 << "HTMLStartTagComment has attr value \"" << ActualValue.str() << "\", " 366 "expected \"" << AttrValue.str() << "\""; 367 368 return ::testing::AssertionSuccess(); 369} 370 371::testing::AssertionResult HasHTMLEndTagAt(const Comment *C, 372 size_t Idx, 373 HTMLEndTagComment *&HET, 374 StringRef TagName) { 375 ::testing::AssertionResult AR = GetChildAt(C, Idx, HET); 376 if (!AR) 377 return AR; 378 379 StringRef ActualTagName = HET->getTagName(); 380 if (ActualTagName != TagName) 381 return ::testing::AssertionFailure() 382 << "HTMLEndTagComment has name \"" << ActualTagName.str() << "\", " 383 "expected \"" << TagName.str() << "\""; 384 385 return ::testing::AssertionSuccess(); 386} 387 388::testing::AssertionResult HasParagraphCommentAt(const Comment *C, 389 size_t Idx, 390 StringRef Text) { 391 ParagraphComment *PC; 392 393 { 394 ::testing::AssertionResult AR = GetChildAt(C, Idx, PC); 395 if (!AR) 396 return AR; 397 } 398 399 { 400 ::testing::AssertionResult AR = HasChildCount(PC, 1); 401 if (!AR) 402 return AR; 403 } 404 405 { 406 ::testing::AssertionResult AR = HasTextAt(PC, 0, Text); 407 if (!AR) 408 return AR; 409 } 410 411 return ::testing::AssertionSuccess(); 412} 413 414::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, 415 size_t Idx, 416 VerbatimBlockComment *&VBC, 417 StringRef Name, 418 StringRef CloseName) { 419 ::testing::AssertionResult AR = GetChildAt(C, Idx, VBC); 420 if (!AR) 421 return AR; 422 423 StringRef ActualName = VBC->getCommandName(); 424 if (ActualName != Name) 425 return ::testing::AssertionFailure() 426 << "VerbatimBlockComment has name \"" << ActualName.str() << "\", " 427 "expected \"" << Name.str() << "\""; 428 429 StringRef ActualCloseName = VBC->getCloseName(); 430 if (ActualCloseName != CloseName) 431 return ::testing::AssertionFailure() 432 << "VerbatimBlockComment has closing command name \"" 433 << ActualCloseName.str() << "\", " 434 "expected \"" << CloseName.str() << "\""; 435 436 return ::testing::AssertionSuccess(); 437} 438 439struct NoLines {}; 440struct Lines {}; 441 442::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, 443 size_t Idx, 444 VerbatimBlockComment *&VBC, 445 StringRef Name, 446 StringRef CloseName, 447 NoLines) { 448 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name, 449 CloseName); 450 if (!AR) 451 return AR; 452 453 if (VBC->getNumLines() != 0) 454 return ::testing::AssertionFailure() 455 << "VerbatimBlockComment has " << VBC->getNumLines() << " lines(s), " 456 "expected 0"; 457 458 return ::testing::AssertionSuccess(); 459} 460 461::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, 462 size_t Idx, 463 VerbatimBlockComment *&VBC, 464 StringRef Name, 465 StringRef CloseName, 466 Lines, 467 StringRef Line0) { 468 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name, 469 CloseName); 470 if (!AR) 471 return AR; 472 473 if (VBC->getNumLines() != 1) 474 return ::testing::AssertionFailure() 475 << "VerbatimBlockComment has " << VBC->getNumLines() << " lines(s), " 476 "expected 1"; 477 478 StringRef ActualLine0 = VBC->getText(0); 479 if (ActualLine0 != Line0) 480 return ::testing::AssertionFailure() 481 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", " 482 "expected \"" << Line0.str() << "\""; 483 484 return ::testing::AssertionSuccess(); 485} 486 487::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, 488 size_t Idx, 489 VerbatimBlockComment *&VBC, 490 StringRef Name, 491 StringRef CloseName, 492 Lines, 493 StringRef Line0, 494 StringRef Line1) { 495 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name, 496 CloseName); 497 if (!AR) 498 return AR; 499 500 if (VBC->getNumLines() != 2) 501 return ::testing::AssertionFailure() 502 << "VerbatimBlockComment has " << VBC->getNumLines() << " lines(s), " 503 "expected 2"; 504 505 StringRef ActualLine0 = VBC->getText(0); 506 if (ActualLine0 != Line0) 507 return ::testing::AssertionFailure() 508 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", " 509 "expected \"" << Line0.str() << "\""; 510 511 StringRef ActualLine1 = VBC->getText(1); 512 if (ActualLine1 != Line1) 513 return ::testing::AssertionFailure() 514 << "VerbatimBlockComment has lines[1] \"" << ActualLine1.str() << "\", " 515 "expected \"" << Line1.str() << "\""; 516 517 return ::testing::AssertionSuccess(); 518} 519 520::testing::AssertionResult HasVerbatimLineAt(const Comment *C, 521 size_t Idx, 522 VerbatimLineComment *&VLC, 523 StringRef Name, 524 StringRef Text) { 525 ::testing::AssertionResult AR = GetChildAt(C, Idx, VLC); 526 if (!AR) 527 return AR; 528 529 StringRef ActualName = VLC->getCommandName(); 530 if (ActualName != Name) 531 return ::testing::AssertionFailure() 532 << "VerbatimLineComment has name \"" << ActualName.str() << "\", " 533 "expected \"" << Name.str() << "\""; 534 535 StringRef ActualText = VLC->getText(); 536 if (ActualText != Text) 537 return ::testing::AssertionFailure() 538 << "VerbatimLineComment has text \"" << ActualText.str() << "\", " 539 "expected \"" << Text.str() << "\""; 540 541 return ::testing::AssertionSuccess(); 542} 543 544 545TEST_F(CommentParserTest, Basic1) { 546 const char *Source = "//"; 547 548 FullComment *FC = parseString(Source); 549 ASSERT_TRUE(HasChildCount(FC, 0)); 550} 551 552TEST_F(CommentParserTest, Basic2) { 553 const char *Source = "// Meow"; 554 555 FullComment *FC = parseString(Source); 556 ASSERT_TRUE(HasChildCount(FC, 1)); 557 558 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " Meow")); 559} 560 561TEST_F(CommentParserTest, Basic3) { 562 const char *Source = 563 "// Aaa\n" 564 "// Bbb"; 565 566 FullComment *FC = parseString(Source); 567 ASSERT_TRUE(HasChildCount(FC, 1)); 568 569 { 570 ParagraphComment *PC; 571 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 572 573 ASSERT_TRUE(HasChildCount(PC, 2)); 574 ASSERT_TRUE(HasTextWithNewlineAt(PC, 0, " Aaa")); 575 ASSERT_TRUE(HasTextAt(PC, 1, " Bbb")); 576 } 577} 578 579TEST_F(CommentParserTest, Paragraph1) { 580 const char *Sources[] = { 581 "// Aaa\n" 582 "//\n" 583 "// Bbb", 584 585 "// Aaa\n" 586 "//\n" 587 "//\n" 588 "// Bbb", 589 }; 590 591 592 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 593 FullComment *FC = parseString(Sources[i]); 594 ASSERT_TRUE(HasChildCount(FC, 2)); 595 596 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " Aaa")); 597 ASSERT_TRUE(HasParagraphCommentAt(FC, 1, " Bbb")); 598 } 599} 600 601TEST_F(CommentParserTest, Paragraph2) { 602 const char *Source = 603 "// \\brief Aaa\n" 604 "//\n" 605 "// Bbb"; 606 607 FullComment *FC = parseString(Source); 608 ASSERT_TRUE(HasChildCount(FC, 3)); 609 610 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 611 { 612 BlockCommandComment *BCC; 613 ParagraphComment *PC; 614 ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC)); 615 616 ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Aaa")); 617 } 618 ASSERT_TRUE(HasParagraphCommentAt(FC, 2, " Bbb")); 619} 620 621TEST_F(CommentParserTest, Paragraph3) { 622 const char *Source = "// \\brief \\author"; 623 624 FullComment *FC = parseString(Source); 625 ASSERT_TRUE(HasChildCount(FC, 3)); 626 627 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 628 { 629 BlockCommandComment *BCC; 630 ParagraphComment *PC; 631 ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC)); 632 633 ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " ")); 634 } 635 { 636 BlockCommandComment *BCC; 637 ParagraphComment *PC; 638 ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC)); 639 640 ASSERT_TRUE(GetChildAt(BCC, 0, PC)); 641 ASSERT_TRUE(HasChildCount(PC, 0)); 642 } 643} 644 645TEST_F(CommentParserTest, Paragraph4) { 646 const char *Source = 647 "// \\brief Aaa\n" 648 "// Bbb \\author\n" 649 "// Ccc"; 650 651 FullComment *FC = parseString(Source); 652 ASSERT_TRUE(HasChildCount(FC, 3)); 653 654 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 655 { 656 BlockCommandComment *BCC; 657 ParagraphComment *PC; 658 ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC)); 659 660 ASSERT_TRUE(GetChildAt(BCC, 0, PC)); 661 ASSERT_TRUE(HasChildCount(PC, 2)); 662 ASSERT_TRUE(HasTextWithNewlineAt(PC, 0, " Aaa")); 663 ASSERT_TRUE(HasTextAt(PC, 1, " Bbb ")); 664 } 665 { 666 BlockCommandComment *BCC; 667 ParagraphComment *PC; 668 ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC)); 669 670 ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Ccc")); 671 } 672} 673 674TEST_F(CommentParserTest, ParamCommand1) { 675 const char *Source = 676 "// \\param aaa\n" 677 "// \\param [in] aaa\n" 678 "// \\param [out] aaa\n" 679 "// \\param [in,out] aaa\n" 680 "// \\param [in, out] aaa\n"; 681 682 FullComment *FC = parseString(Source); 683 ASSERT_TRUE(HasChildCount(FC, 6)); 684 685 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 686 { 687 ParamCommandComment *PCC; 688 ParagraphComment *PC; 689 ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param", 690 ParamCommandComment::In, 691 /* IsDirectionExplicit = */ false, 692 "aaa", PC)); 693 ASSERT_TRUE(HasChildCount(PCC, 1)); 694 ASSERT_TRUE(HasChildCount(PC, 1)); 695 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 696 } 697 { 698 ParamCommandComment *PCC; 699 ParagraphComment *PC; 700 ASSERT_TRUE(HasParamCommandAt(FC, 2, PCC, "param", 701 ParamCommandComment::In, 702 /* IsDirectionExplicit = */ true, 703 "aaa", PC)); 704 ASSERT_TRUE(HasChildCount(PCC, 1)); 705 ASSERT_TRUE(HasChildCount(PC, 1)); 706 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 707 } 708 { 709 ParamCommandComment *PCC; 710 ParagraphComment *PC; 711 ASSERT_TRUE(HasParamCommandAt(FC, 3, PCC, "param", 712 ParamCommandComment::Out, 713 /* IsDirectionExplicit = */ true, 714 "aaa", PC)); 715 ASSERT_TRUE(HasChildCount(PCC, 1)); 716 ASSERT_TRUE(HasChildCount(PC, 1)); 717 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 718 } 719 { 720 ParamCommandComment *PCC; 721 ParagraphComment *PC; 722 ASSERT_TRUE(HasParamCommandAt(FC, 4, PCC, "param", 723 ParamCommandComment::InOut, 724 /* IsDirectionExplicit = */ true, 725 "aaa", PC)); 726 ASSERT_TRUE(HasChildCount(PCC, 1)); 727 ASSERT_TRUE(HasChildCount(PC, 1)); 728 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 729 } 730 { 731 ParamCommandComment *PCC; 732 ParagraphComment *PC; 733 ASSERT_TRUE(HasParamCommandAt(FC, 5, PCC, "param", 734 ParamCommandComment::InOut, 735 /* IsDirectionExplicit = */ true, 736 "aaa", PC)); 737 ASSERT_TRUE(HasChildCount(PCC, 1)); 738 ASSERT_TRUE(HasChildCount(PC, 0)); 739 } 740} 741 742TEST_F(CommentParserTest, InlineCommand1) { 743 const char *Source = "// \\c"; 744 745 FullComment *FC = parseString(Source); 746 ASSERT_TRUE(HasChildCount(FC, 1)); 747 748 { 749 ParagraphComment *PC; 750 InlineCommandComment *ICC; 751 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 752 753 ASSERT_TRUE(HasChildCount(PC, 2)); 754 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 755 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs())); 756 } 757} 758 759TEST_F(CommentParserTest, InlineCommand2) { 760 const char *Source = "// \\c "; 761 762 FullComment *FC = parseString(Source); 763 ASSERT_TRUE(HasChildCount(FC, 1)); 764 765 { 766 ParagraphComment *PC; 767 InlineCommandComment *ICC; 768 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 769 770 ASSERT_TRUE(HasChildCount(PC, 3)); 771 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 772 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs())); 773 ASSERT_TRUE(HasTextAt(PC, 2, " ")); 774 } 775} 776 777TEST_F(CommentParserTest, InlineCommand3) { 778 const char *Source = "// \\c aaa\n"; 779 780 FullComment *FC = parseString(Source); 781 ASSERT_TRUE(HasChildCount(FC, 1)); 782 783 { 784 ParagraphComment *PC; 785 InlineCommandComment *ICC; 786 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 787 788 ASSERT_TRUE(HasChildCount(PC, 2)); 789 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 790 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa")); 791 } 792} 793 794TEST_F(CommentParserTest, InlineCommand4) { 795 const char *Source = "// \\c aaa bbb"; 796 797 FullComment *FC = parseString(Source); 798 ASSERT_TRUE(HasChildCount(FC, 1)); 799 800 { 801 ParagraphComment *PC; 802 InlineCommandComment *ICC; 803 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 804 805 ASSERT_TRUE(HasChildCount(PC, 3)); 806 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 807 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa")); 808 ASSERT_TRUE(HasTextAt(PC, 2, " bbb")); 809 } 810} 811 812TEST_F(CommentParserTest, InlineCommand5) { 813 const char *Source = "// \\unknown aaa\n"; 814 815 FullComment *FC = parseString(Source); 816 ASSERT_TRUE(HasChildCount(FC, 1)); 817 818 { 819 ParagraphComment *PC; 820 InlineCommandComment *ICC; 821 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 822 823 ASSERT_TRUE(HasChildCount(PC, 3)); 824 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 825 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "unknown", NoArgs())); 826 ASSERT_TRUE(HasTextAt(PC, 2, " aaa")); 827 } 828} 829 830TEST_F(CommentParserTest, HTML1) { 831 const char *Sources[] = { 832 "// <a", 833 "// <a>", 834 "// <a >" 835 }; 836 837 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 838 FullComment *FC = parseString(Sources[i]); 839 ASSERT_TRUE(HasChildCount(FC, 1)); 840 841 { 842 ParagraphComment *PC; 843 HTMLStartTagComment *HST; 844 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 845 846 ASSERT_TRUE(HasChildCount(PC, 2)); 847 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 848 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", NoAttrs())); 849 } 850 } 851} 852 853TEST_F(CommentParserTest, HTML2) { 854 const char *Sources[] = { 855 "// <br/>", 856 "// <br />" 857 }; 858 859 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 860 FullComment *FC = parseString(Sources[i]); 861 ASSERT_TRUE(HasChildCount(FC, 1)); 862 863 { 864 ParagraphComment *PC; 865 HTMLStartTagComment *HST; 866 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 867 868 ASSERT_TRUE(HasChildCount(PC, 2)); 869 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 870 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "br", SelfClosing())); 871 } 872 } 873} 874 875TEST_F(CommentParserTest, HTML3) { 876 const char *Sources[] = { 877 "// <a href", 878 "// <a href ", 879 "// <a href>", 880 "// <a href >", 881 }; 882 883 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 884 FullComment *FC = parseString(Sources[i]); 885 ASSERT_TRUE(HasChildCount(FC, 1)); 886 887 { 888 ParagraphComment *PC; 889 HTMLStartTagComment *HST; 890 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 891 892 ASSERT_TRUE(HasChildCount(PC, 2)); 893 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 894 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", "href", "")); 895 } 896 } 897} 898 899TEST_F(CommentParserTest, HTML4) { 900 const char *Sources[] = { 901 "// <a href=\"bbb\"", 902 "// <a href=\"bbb\">", 903 }; 904 905 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 906 FullComment *FC = parseString(Sources[i]); 907 ASSERT_TRUE(HasChildCount(FC, 1)); 908 909 { 910 ParagraphComment *PC; 911 HTMLStartTagComment *HST; 912 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 913 914 ASSERT_TRUE(HasChildCount(PC, 2)); 915 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 916 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", "href", "bbb")); 917 } 918 } 919} 920 921TEST_F(CommentParserTest, HTML5) { 922 const char *Sources[] = { 923 "// </a", 924 "// </a>", 925 "// </a >" 926 }; 927 928 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 929 FullComment *FC = parseString(Sources[i]); 930 ASSERT_TRUE(HasChildCount(FC, 1)); 931 932 { 933 ParagraphComment *PC; 934 HTMLEndTagComment *HET; 935 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 936 937 ASSERT_TRUE(HasChildCount(PC, 2)); 938 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 939 ASSERT_TRUE(HasHTMLEndTagAt(PC, 1, HET, "a")); 940 } 941 } 942} 943 944TEST_F(CommentParserTest, HTML6) { 945 const char *Source = 946 "// <pre>\n" 947 "// Aaa\n" 948 "// Bbb\n" 949 "// </pre>\n"; 950 951 FullComment *FC = parseString(Source); 952 ASSERT_TRUE(HasChildCount(FC, 1)); 953 954 { 955 ParagraphComment *PC; 956 HTMLStartTagComment *HST; 957 HTMLEndTagComment *HET; 958 ASSERT_TRUE(GetChildAt(FC, 0, PC)); 959 960 ASSERT_TRUE(HasChildCount(PC, 6)); 961 ASSERT_TRUE(HasTextAt(PC, 0, " ")); 962 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "pre", NoAttrs())); 963 ASSERT_TRUE(HasTextWithNewlineAt(PC, 2, " Aaa")); 964 ASSERT_TRUE(HasTextWithNewlineAt(PC, 3, " Bbb")); 965 ASSERT_TRUE(HasTextAt(PC, 4, " ")); 966 ASSERT_TRUE(HasHTMLEndTagAt(PC, 5, HET, "pre")); 967 } 968} 969 970TEST_F(CommentParserTest, VerbatimBlock1) { 971 const char *Source = "// \\verbatim\\endverbatim\n"; 972 973 FullComment *FC = parseString(Source); 974 ASSERT_TRUE(HasChildCount(FC, 2)); 975 976 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 977 { 978 VerbatimBlockComment *VCC; 979 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VCC, "verbatim", "endverbatim", 980 NoLines())); 981 } 982} 983 984TEST_F(CommentParserTest, VerbatimBlock2) { 985 const char *Source = "// \\verbatim Aaa \\endverbatim\n"; 986 987 FullComment *FC = parseString(Source); 988 ASSERT_TRUE(HasChildCount(FC, 2)); 989 990 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 991 { 992 VerbatimBlockComment *VBC; 993 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim", 994 Lines(), " Aaa ")); 995 } 996} 997 998TEST_F(CommentParserTest, VerbatimBlock3) { 999 const char *Source = "// \\verbatim Aaa\n"; 1000 1001 FullComment *FC = parseString(Source); 1002 ASSERT_TRUE(HasChildCount(FC, 2)); 1003 1004 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1005 { 1006 VerbatimBlockComment *VBC; 1007 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "", 1008 Lines(), " Aaa")); 1009 } 1010} 1011 1012TEST_F(CommentParserTest, VerbatimBlock4) { 1013 const char *Source = 1014 "//\\verbatim\n" 1015 "//\\endverbatim\n"; 1016 1017 FullComment *FC = parseString(Source); 1018 ASSERT_TRUE(HasChildCount(FC, 1)); 1019 1020 { 1021 VerbatimBlockComment *VBC; 1022 ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", "endverbatim", 1023 NoLines())); 1024 } 1025} 1026 1027TEST_F(CommentParserTest, VerbatimBlock5) { 1028 const char *Sources[] = { 1029 "//\\verbatim\n" 1030 "// Aaa\n" 1031 "//\\endverbatim\n", 1032 1033 "/*\\verbatim\n" 1034 " * Aaa\n" 1035 " *\\endverbatim*/" 1036 }; 1037 1038 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1039 FullComment *FC = parseString(Sources[i]); 1040 ASSERT_TRUE(HasChildCount(FC, 1)); 1041 1042 { 1043 VerbatimBlockComment *VBC; 1044 ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", "endverbatim", 1045 Lines(), " Aaa")); 1046 } 1047 } 1048} 1049 1050TEST_F(CommentParserTest, VerbatimBlock6) { 1051 const char *Sources[] = { 1052 "// \\verbatim\n" 1053 "// Aaa\n" 1054 "// \\endverbatim\n", 1055 1056 "/* \\verbatim\n" 1057 " * Aaa\n" 1058 " * \\endverbatim*/" 1059 }; 1060 1061 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1062 FullComment *FC = parseString(Sources[i]); 1063 ASSERT_TRUE(HasChildCount(FC, 2)); 1064 1065 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1066 { 1067 VerbatimBlockComment *VBC; 1068 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim", 1069 Lines(), " Aaa")); 1070 } 1071 } 1072} 1073 1074TEST_F(CommentParserTest, VerbatimBlock7) { 1075 const char *Sources[] = { 1076 "// \\verbatim\n" 1077 "// Aaa\n" 1078 "// Bbb\n" 1079 "// \\endverbatim\n", 1080 1081 "/* \\verbatim\n" 1082 " * Aaa\n" 1083 " * Bbb\n" 1084 " * \\endverbatim*/" 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, 2)); 1090 1091 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1092 { 1093 VerbatimBlockComment *VBC; 1094 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim", 1095 Lines(), " Aaa", " Bbb")); 1096 } 1097 } 1098} 1099 1100TEST_F(CommentParserTest, VerbatimBlock8) { 1101 const char *Sources[] = { 1102 "// \\verbatim\n" 1103 "// Aaa\n" 1104 "//\n" 1105 "// Bbb\n" 1106 "// \\endverbatim\n", 1107 1108 "/* \\verbatim\n" 1109 " * Aaa\n" 1110 " *\n" 1111 " * Bbb\n" 1112 " * \\endverbatim*/" 1113 }; 1114 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1115 FullComment *FC = parseString(Sources[i]); 1116 ASSERT_TRUE(HasChildCount(FC, 2)); 1117 1118 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1119 { 1120 VerbatimBlockComment *VBC; 1121 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim")); 1122 ASSERT_EQ(3U, VBC->getNumLines()); 1123 ASSERT_EQ(" Aaa", VBC->getText(0)); 1124 ASSERT_EQ("", VBC->getText(1)); 1125 ASSERT_EQ(" Bbb", VBC->getText(2)); 1126 } 1127 } 1128} 1129 1130TEST_F(CommentParserTest, VerbatimLine1) { 1131 const char *Sources[] = { 1132 "// \\fn", 1133 "// \\fn\n" 1134 }; 1135 1136 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1137 FullComment *FC = parseString(Sources[i]); 1138 ASSERT_TRUE(HasChildCount(FC, 2)); 1139 1140 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1141 { 1142 VerbatimLineComment *VLC; 1143 ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn", "")); 1144 } 1145 } 1146} 1147 1148TEST_F(CommentParserTest, VerbatimLine2) { 1149 const char *Sources[] = { 1150 "/// \\fn void *foo(const char *zzz = \"\\$\");\n//", 1151 "/** \\fn void *foo(const char *zzz = \"\\$\");*/" 1152 }; 1153 1154 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) { 1155 FullComment *FC = parseString(Sources[i]); 1156 ASSERT_TRUE(HasChildCount(FC, 2)); 1157 1158 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); 1159 { 1160 VerbatimLineComment *VLC; 1161 ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn", 1162 " void *foo(const char *zzz = \"\\$\");")); 1163 } 1164 } 1165} 1166 1167} // unnamed namespace 1168 1169} // end namespace comments 1170} // end namespace clang 1171 1172