Comment.h revision b740316a122b5ceaaa7cf50557b1b39af5fbbf5f
1//===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===// 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// This file defines comment AST nodes. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_AST_COMMENT_H 15#define LLVM_CLANG_AST_COMMENT_H 16 17#include "clang/Basic/SourceLocation.h" 18#include "llvm/ADT/ArrayRef.h" 19#include "llvm/ADT/StringRef.h" 20 21namespace clang { 22namespace comments { 23 24/// Any part of the comment. 25/// Abstract class. 26class Comment { 27protected: 28 /// Preferred location to show caret. 29 SourceLocation Loc; 30 31 /// Source range of this AST node. 32 SourceRange Range; 33 34 class CommentBitfields { 35 friend class Comment; 36 37 /// Type of this AST node. 38 unsigned Kind : 8; 39 }; 40 enum { NumCommentBits = 8 }; 41 42 class InlineContentCommentBitfields { 43 friend class InlineContentComment; 44 45 unsigned : NumCommentBits; 46 47 /// True if there is a newline after this inline content node. 48 /// (There is no separate AST node for a newline.) 49 unsigned HasTrailingNewline : 1; 50 }; 51 enum { NumInlineContentCommentBits = NumCommentBits + 1 }; 52 53 class TextCommentBitfields { 54 friend class TextComment; 55 56 unsigned : NumInlineContentCommentBits; 57 58 /// True if \c IsWhitespace field contains a valid value. 59 mutable unsigned IsWhitespaceValid : 1; 60 61 /// True if this comment AST node contains only whitespace. 62 mutable unsigned IsWhitespace : 1; 63 }; 64 enum { NumTextCommentBits = NumInlineContentCommentBits + 2 }; 65 66 class InlineCommandCommentBitfields { 67 friend class InlineCommandComment; 68 69 unsigned : NumInlineContentCommentBits; 70 71 unsigned RenderKind : 2; 72 }; 73 enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 1 }; 74 75 class HTMLStartTagCommentBitfields { 76 friend class HTMLStartTagComment; 77 78 unsigned : NumInlineContentCommentBits; 79 80 /// True if this tag is self-closing (e. g., <br />). This is based on tag 81 /// spelling in comment (plain <br> would not set this flag). 82 unsigned IsSelfClosing : 1; 83 }; 84 enum { NumHTMLStartTagCommentBits = NumInlineContentCommentBits + 1 }; 85 86 class ParagraphCommentBitfields { 87 friend class ParagraphComment; 88 89 unsigned : NumCommentBits; 90 91 /// True if \c IsWhitespace field contains a valid value. 92 mutable unsigned IsWhitespaceValid : 1; 93 94 /// True if this comment AST node contains only whitespace. 95 mutable unsigned IsWhitespace : 1; 96 }; 97 enum { NumParagraphCommentBits = NumCommentBits + 2 }; 98 99 class ParamCommandCommentBitfields { 100 friend class ParamCommandComment; 101 102 unsigned : NumCommentBits; 103 104 /// Parameter passing direction, see ParamCommandComment::PassDirection. 105 unsigned Direction : 2; 106 107 /// True if direction was specified explicitly in the comment. 108 unsigned IsDirectionExplicit : 1; 109 }; 110 enum { NumParamCommandCommentBits = 11 }; 111 112 union { 113 CommentBitfields CommentBits; 114 InlineContentCommentBitfields InlineContentCommentBits; 115 TextCommentBitfields TextCommentBits; 116 InlineCommandCommentBitfields InlineCommandCommentBits; 117 HTMLStartTagCommentBitfields HTMLStartTagCommentBits; 118 ParagraphCommentBitfields ParagraphCommentBits; 119 ParamCommandCommentBitfields ParamCommandCommentBits; 120 }; 121 122 void setSourceRange(SourceRange SR) { 123 Range = SR; 124 } 125 126 void setLocation(SourceLocation L) { 127 Loc = L; 128 } 129 130public: 131 enum CommentKind { 132 NoCommentKind = 0, 133#define COMMENT(CLASS, PARENT) CLASS##Kind, 134#define COMMENT_RANGE(BASE, FIRST, LAST) \ 135 First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind, 136#define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \ 137 First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind 138#define ABSTRACT_COMMENT(COMMENT) 139#include "clang/AST/CommentNodes.inc" 140 }; 141 142 Comment(CommentKind K, 143 SourceLocation LocBegin, 144 SourceLocation LocEnd) : 145 Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) { 146 CommentBits.Kind = K; 147 } 148 149 CommentKind getCommentKind() const { 150 return static_cast<CommentKind>(CommentBits.Kind); 151 } 152 153 const char *getCommentKindName() const; 154 155 LLVM_ATTRIBUTE_USED void dump() const; 156 LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const; 157 void dump(llvm::raw_ostream &OS, SourceManager *SM) const; 158 159 static bool classof(const Comment *) { return true; } 160 161 SourceRange getSourceRange() const LLVM_READONLY { return Range; } 162 163 SourceLocation getLocStart() const LLVM_READONLY { 164 return Range.getBegin(); 165 } 166 167 SourceLocation getLocEnd() const LLVM_READONLY { 168 return Range.getEnd(); 169 } 170 171 SourceLocation getLocation() const LLVM_READONLY { return Loc; } 172 173 typedef Comment * const *child_iterator; 174 175 child_iterator child_begin() const; 176 child_iterator child_end() const; 177 178 // TODO: const child iterator 179 180 unsigned child_count() const { 181 return child_end() - child_begin(); 182 } 183}; 184 185/// Inline content (contained within a block). 186/// Abstract class. 187class InlineContentComment : public Comment { 188protected: 189 InlineContentComment(CommentKind K, 190 SourceLocation LocBegin, 191 SourceLocation LocEnd) : 192 Comment(K, LocBegin, LocEnd) { 193 InlineContentCommentBits.HasTrailingNewline = 0; 194 } 195 196public: 197 static bool classof(const Comment *C) { 198 return C->getCommentKind() >= FirstInlineContentCommentConstant && 199 C->getCommentKind() <= LastInlineContentCommentConstant; 200 } 201 202 static bool classof(const InlineContentComment *) { return true; } 203 204 void addTrailingNewline() { 205 InlineContentCommentBits.HasTrailingNewline = 1; 206 } 207 208 bool hasTrailingNewline() const { 209 return InlineContentCommentBits.HasTrailingNewline; 210 } 211}; 212 213/// Plain text. 214class TextComment : public InlineContentComment { 215 StringRef Text; 216 217public: 218 TextComment(SourceLocation LocBegin, 219 SourceLocation LocEnd, 220 StringRef Text) : 221 InlineContentComment(TextCommentKind, LocBegin, LocEnd), 222 Text(Text) { 223 TextCommentBits.IsWhitespaceValid = false; 224 } 225 226 static bool classof(const Comment *C) { 227 return C->getCommentKind() == TextCommentKind; 228 } 229 230 static bool classof(const TextComment *) { return true; } 231 232 child_iterator child_begin() const { return NULL; } 233 234 child_iterator child_end() const { return NULL; } 235 236 StringRef getText() const LLVM_READONLY { return Text; } 237 238 bool isWhitespace() const { 239 if (TextCommentBits.IsWhitespaceValid) 240 return TextCommentBits.IsWhitespace; 241 242 TextCommentBits.IsWhitespace = isWhitespaceNoCache(); 243 TextCommentBits.IsWhitespaceValid = true; 244 return TextCommentBits.IsWhitespace; 245 } 246 247private: 248 bool isWhitespaceNoCache() const; 249}; 250 251/// A command with word-like arguments that is considered inline content. 252class InlineCommandComment : public InlineContentComment { 253public: 254 struct Argument { 255 SourceRange Range; 256 StringRef Text; 257 258 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } 259 }; 260 261 /// The most appropriate rendering mode for this command, chosen on command 262 /// semantics in Doxygen. 263 enum RenderKind { 264 RenderNormal, 265 RenderBold, 266 RenderMonospaced, 267 RenderEmphasized 268 }; 269 270protected: 271 /// Command name. 272 StringRef Name; 273 274 /// Command arguments. 275 llvm::ArrayRef<Argument> Args; 276 277public: 278 InlineCommandComment(SourceLocation LocBegin, 279 SourceLocation LocEnd, 280 StringRef Name, 281 RenderKind RK, 282 llvm::ArrayRef<Argument> Args) : 283 InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), 284 Name(Name), Args(Args) { 285 InlineCommandCommentBits.RenderKind = RK; 286 } 287 288 static bool classof(const Comment *C) { 289 return C->getCommentKind() == InlineCommandCommentKind; 290 } 291 292 static bool classof(const InlineCommandComment *) { return true; } 293 294 child_iterator child_begin() const { return NULL; } 295 296 child_iterator child_end() const { return NULL; } 297 298 StringRef getCommandName() const { 299 return Name; 300 } 301 302 SourceRange getCommandNameRange() const { 303 return SourceRange(getLocStart().getLocWithOffset(-1), 304 getLocEnd()); 305 } 306 307 RenderKind getRenderKind() const { 308 return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind); 309 } 310 311 unsigned getNumArgs() const { 312 return Args.size(); 313 } 314 315 StringRef getArgText(unsigned Idx) const { 316 return Args[Idx].Text; 317 } 318 319 SourceRange getArgRange(unsigned Idx) const { 320 return Args[Idx].Range; 321 } 322}; 323 324/// Abstract class for opening and closing HTML tags. HTML tags are always 325/// treated as inline content (regardless HTML semantics); opening and closing 326/// tags are not matched. 327class HTMLTagComment : public InlineContentComment { 328protected: 329 StringRef TagName; 330 SourceRange TagNameRange; 331 332 HTMLTagComment(CommentKind K, 333 SourceLocation LocBegin, 334 SourceLocation LocEnd, 335 StringRef TagName, 336 SourceLocation TagNameBegin, 337 SourceLocation TagNameEnd) : 338 InlineContentComment(K, LocBegin, LocEnd), 339 TagName(TagName), 340 TagNameRange(TagNameBegin, TagNameEnd) { 341 setLocation(TagNameBegin); 342 } 343 344public: 345 static bool classof(const Comment *C) { 346 return C->getCommentKind() >= FirstHTMLTagCommentConstant && 347 C->getCommentKind() <= LastHTMLTagCommentConstant; 348 } 349 350 static bool classof(const HTMLTagComment *) { return true; } 351 352 StringRef getTagName() const LLVM_READONLY { return TagName; } 353 354 SourceRange getTagNameSourceRange() const LLVM_READONLY { 355 SourceLocation L = getLocation(); 356 return SourceRange(L.getLocWithOffset(1), 357 L.getLocWithOffset(1 + TagName.size())); 358 } 359}; 360 361/// An opening HTML tag with attributes. 362class HTMLStartTagComment : public HTMLTagComment { 363public: 364 class Attribute { 365 public: 366 SourceLocation NameLocBegin; 367 StringRef Name; 368 369 SourceLocation EqualsLoc; 370 371 SourceRange ValueRange; 372 StringRef Value; 373 374 Attribute() { } 375 376 Attribute(SourceLocation NameLocBegin, StringRef Name) : 377 NameLocBegin(NameLocBegin), Name(Name), 378 EqualsLoc(SourceLocation()), 379 ValueRange(SourceRange()), Value(StringRef()) 380 { } 381 382 Attribute(SourceLocation NameLocBegin, StringRef Name, 383 SourceLocation EqualsLoc, 384 SourceRange ValueRange, StringRef Value) : 385 NameLocBegin(NameLocBegin), Name(Name), 386 EqualsLoc(EqualsLoc), 387 ValueRange(ValueRange), Value(Value) 388 { } 389 390 SourceLocation getNameLocEnd() const { 391 return NameLocBegin.getLocWithOffset(Name.size()); 392 } 393 394 SourceRange getNameRange() const { 395 return SourceRange(NameLocBegin, getNameLocEnd()); 396 } 397 }; 398 399private: 400 ArrayRef<Attribute> Attributes; 401 402public: 403 HTMLStartTagComment(SourceLocation LocBegin, 404 StringRef TagName) : 405 HTMLTagComment(HTMLStartTagCommentKind, 406 LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()), 407 TagName, 408 LocBegin.getLocWithOffset(1), 409 LocBegin.getLocWithOffset(1 + TagName.size())) { 410 HTMLStartTagCommentBits.IsSelfClosing = false; 411 } 412 413 static bool classof(const Comment *C) { 414 return C->getCommentKind() == HTMLStartTagCommentKind; 415 } 416 417 static bool classof(const HTMLStartTagComment *) { return true; } 418 419 child_iterator child_begin() const { return NULL; } 420 421 child_iterator child_end() const { return NULL; } 422 423 unsigned getNumAttrs() const { 424 return Attributes.size(); 425 } 426 427 const Attribute &getAttr(unsigned Idx) const { 428 return Attributes[Idx]; 429 } 430 431 void setAttrs(ArrayRef<Attribute> Attrs) { 432 Attributes = Attrs; 433 if (!Attrs.empty()) { 434 const Attribute &Attr = Attrs.back(); 435 SourceLocation L = Attr.ValueRange.getEnd(); 436 if (L.isValid()) 437 Range.setEnd(L); 438 else { 439 Range.setEnd(Attr.getNameLocEnd()); 440 } 441 } 442 } 443 444 void setGreaterLoc(SourceLocation GreaterLoc) { 445 Range.setEnd(GreaterLoc); 446 } 447 448 bool isSelfClosing() const { 449 return HTMLStartTagCommentBits.IsSelfClosing; 450 } 451 452 void setSelfClosing() { 453 HTMLStartTagCommentBits.IsSelfClosing = true; 454 } 455}; 456 457/// A closing HTML tag. 458class HTMLEndTagComment : public HTMLTagComment { 459public: 460 HTMLEndTagComment(SourceLocation LocBegin, 461 SourceLocation LocEnd, 462 StringRef TagName) : 463 HTMLTagComment(HTMLEndTagCommentKind, 464 LocBegin, LocEnd, 465 TagName, 466 LocBegin.getLocWithOffset(2), 467 LocBegin.getLocWithOffset(2 + TagName.size())) 468 { } 469 470 static bool classof(const Comment *C) { 471 return C->getCommentKind() == HTMLEndTagCommentKind; 472 } 473 474 static bool classof(const HTMLEndTagComment *) { return true; } 475 476 child_iterator child_begin() const { return NULL; } 477 478 child_iterator child_end() const { return NULL; } 479}; 480 481/// Block content (contains inline content). 482/// Abstract class. 483class BlockContentComment : public Comment { 484protected: 485 BlockContentComment(CommentKind K, 486 SourceLocation LocBegin, 487 SourceLocation LocEnd) : 488 Comment(K, LocBegin, LocEnd) 489 { } 490 491public: 492 static bool classof(const Comment *C) { 493 return C->getCommentKind() >= FirstBlockContentCommentConstant && 494 C->getCommentKind() <= LastBlockContentCommentConstant; 495 } 496 497 static bool classof(const BlockContentComment *) { return true; } 498}; 499 500/// A single paragraph that contains inline content. 501class ParagraphComment : public BlockContentComment { 502 llvm::ArrayRef<InlineContentComment *> Content; 503 504public: 505 ParagraphComment(llvm::ArrayRef<InlineContentComment *> Content) : 506 BlockContentComment(ParagraphCommentKind, 507 SourceLocation(), 508 SourceLocation()), 509 Content(Content) { 510 if (Content.empty()) { 511 ParagraphCommentBits.IsWhitespace = true; 512 ParagraphCommentBits.IsWhitespaceValid = true; 513 return; 514 } 515 516 ParagraphCommentBits.IsWhitespaceValid = false; 517 518 setSourceRange(SourceRange(Content.front()->getLocStart(), 519 Content.back()->getLocEnd())); 520 setLocation(Content.front()->getLocStart()); 521 } 522 523 static bool classof(const Comment *C) { 524 return C->getCommentKind() == ParagraphCommentKind; 525 } 526 527 static bool classof(const ParagraphComment *) { return true; } 528 529 child_iterator child_begin() const { 530 return reinterpret_cast<child_iterator>(Content.begin()); 531 } 532 533 child_iterator child_end() const { 534 return reinterpret_cast<child_iterator>(Content.end()); 535 } 536 537 bool isWhitespace() const { 538 if (ParagraphCommentBits.IsWhitespaceValid) 539 return ParagraphCommentBits.IsWhitespace; 540 541 ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache(); 542 ParagraphCommentBits.IsWhitespaceValid = true; 543 return ParagraphCommentBits.IsWhitespace; 544 } 545 546private: 547 bool isWhitespaceNoCache() const; 548}; 549 550/// A command that has zero or more word-like arguments (number of word-like 551/// arguments depends on command name) and a paragraph as an argument 552/// (e. g., \\brief). 553class BlockCommandComment : public BlockContentComment { 554public: 555 struct Argument { 556 SourceRange Range; 557 StringRef Text; 558 559 Argument() { } 560 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } 561 }; 562 563protected: 564 /// Command name. 565 StringRef Name; 566 567 /// Word-like arguments. 568 llvm::ArrayRef<Argument> Args; 569 570 /// Paragraph argument. 571 ParagraphComment *Paragraph; 572 573 BlockCommandComment(CommentKind K, 574 SourceLocation LocBegin, 575 SourceLocation LocEnd, 576 StringRef Name) : 577 BlockContentComment(K, LocBegin, LocEnd), 578 Name(Name), 579 Paragraph(NULL) { 580 setLocation(getCommandNameRange().getBegin()); 581 } 582 583public: 584 BlockCommandComment(SourceLocation LocBegin, 585 SourceLocation LocEnd, 586 StringRef Name) : 587 BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), 588 Name(Name), 589 Paragraph(NULL) { 590 setLocation(getCommandNameRange().getBegin()); 591 } 592 593 static bool classof(const Comment *C) { 594 return C->getCommentKind() >= FirstBlockCommandCommentConstant && 595 C->getCommentKind() <= LastBlockCommandCommentConstant; 596 } 597 598 static bool classof(const BlockCommandComment *) { return true; } 599 600 child_iterator child_begin() const { 601 return reinterpret_cast<child_iterator>(&Paragraph); 602 } 603 604 child_iterator child_end() const { 605 return reinterpret_cast<child_iterator>(&Paragraph + 1); 606 } 607 608 StringRef getCommandName() const { 609 return Name; 610 } 611 612 SourceRange getCommandNameRange() const { 613 return SourceRange(getLocStart().getLocWithOffset(1), 614 getLocStart().getLocWithOffset(1 + Name.size())); 615 } 616 617 unsigned getNumArgs() const { 618 return Args.size(); 619 } 620 621 StringRef getArgText(unsigned Idx) const { 622 return Args[Idx].Text; 623 } 624 625 SourceRange getArgRange(unsigned Idx) const { 626 return Args[Idx].Range; 627 } 628 629 void setArgs(llvm::ArrayRef<Argument> A) { 630 Args = A; 631 if (Args.size() > 0) { 632 SourceLocation NewLocEnd = Args.back().Range.getEnd(); 633 if (NewLocEnd.isValid()) 634 setSourceRange(SourceRange(getLocStart(), NewLocEnd)); 635 } 636 } 637 638 ParagraphComment *getParagraph() const LLVM_READONLY { 639 return Paragraph; 640 } 641 642 bool hasNonWhitespaceParagraph() const { 643 return Paragraph && !Paragraph->isWhitespace(); 644 } 645 646 void setParagraph(ParagraphComment *PC) { 647 Paragraph = PC; 648 SourceLocation NewLocEnd = PC->getLocEnd(); 649 if (NewLocEnd.isValid()) 650 setSourceRange(SourceRange(getLocStart(), NewLocEnd)); 651 } 652}; 653 654/// Doxygen \\param command. 655class ParamCommandComment : public BlockCommandComment { 656private: 657 /// Parameter index in the function declaration. 658 unsigned ParamIndex; 659 660public: 661 enum { InvalidParamIndex = ~0U }; 662 663 ParamCommandComment(SourceLocation LocBegin, 664 SourceLocation LocEnd, 665 StringRef Name) : 666 BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, Name), 667 ParamIndex(InvalidParamIndex) { 668 ParamCommandCommentBits.Direction = In; 669 ParamCommandCommentBits.IsDirectionExplicit = false; 670 } 671 672 static bool classof(const Comment *C) { 673 return C->getCommentKind() == ParamCommandCommentKind; 674 } 675 676 static bool classof(const ParamCommandComment *) { return true; } 677 678 enum PassDirection { 679 In, 680 Out, 681 InOut 682 }; 683 684 static const char *getDirectionAsString(PassDirection D); 685 686 PassDirection getDirection() const LLVM_READONLY { 687 return static_cast<PassDirection>(ParamCommandCommentBits.Direction); 688 } 689 690 bool isDirectionExplicit() const LLVM_READONLY { 691 return ParamCommandCommentBits.IsDirectionExplicit; 692 } 693 694 void setDirection(PassDirection Direction, bool Explicit) { 695 ParamCommandCommentBits.Direction = Direction; 696 ParamCommandCommentBits.IsDirectionExplicit = Explicit; 697 } 698 699 bool hasParamName() const { 700 return getNumArgs() > 0; 701 } 702 703 StringRef getParamName() const { 704 return Args[0].Text; 705 } 706 707 SourceRange getParamNameRange() const { 708 return Args[0].Range; 709 } 710 711 bool isParamIndexValid() const LLVM_READONLY { 712 return ParamIndex != InvalidParamIndex; 713 } 714 715 unsigned getParamIndex() const LLVM_READONLY { 716 assert(isParamIndexValid()); 717 return ParamIndex; 718 } 719 720 void setParamIndex(unsigned Index) { 721 ParamIndex = Index; 722 assert(isParamIndexValid()); 723 } 724}; 725 726/// A line of text contained in a verbatim block. 727class VerbatimBlockLineComment : public Comment { 728 StringRef Text; 729 730public: 731 VerbatimBlockLineComment(SourceLocation LocBegin, 732 StringRef Text) : 733 Comment(VerbatimBlockLineCommentKind, 734 LocBegin, 735 LocBegin.getLocWithOffset(Text.size())), 736 Text(Text) 737 { } 738 739 static bool classof(const Comment *C) { 740 return C->getCommentKind() == VerbatimBlockLineCommentKind; 741 } 742 743 static bool classof(const VerbatimBlockLineComment *) { return true; } 744 745 child_iterator child_begin() const { return NULL; } 746 747 child_iterator child_end() const { return NULL; } 748 749 StringRef getText() const LLVM_READONLY { 750 return Text; 751 } 752}; 753 754/// A verbatim block command (e. g., preformatted code). Verbatim block has an 755/// opening and a closing command and contains multiple lines of text 756/// (VerbatimBlockLineComment nodes). 757class VerbatimBlockComment : public BlockCommandComment { 758protected: 759 StringRef CloseName; 760 SourceLocation CloseNameLocBegin; 761 llvm::ArrayRef<VerbatimBlockLineComment *> Lines; 762 763public: 764 VerbatimBlockComment(SourceLocation LocBegin, 765 SourceLocation LocEnd, 766 StringRef Name) : 767 BlockCommandComment(VerbatimBlockCommentKind, 768 LocBegin, LocEnd, Name) 769 { } 770 771 static bool classof(const Comment *C) { 772 return C->getCommentKind() == VerbatimBlockCommentKind; 773 } 774 775 static bool classof(const VerbatimBlockComment *) { return true; } 776 777 child_iterator child_begin() const { 778 return reinterpret_cast<child_iterator>(Lines.begin()); 779 } 780 781 child_iterator child_end() const { 782 return reinterpret_cast<child_iterator>(Lines.end()); 783 } 784 785 void setCloseName(StringRef Name, SourceLocation LocBegin) { 786 CloseName = Name; 787 CloseNameLocBegin = LocBegin; 788 } 789 790 void setLines(llvm::ArrayRef<VerbatimBlockLineComment *> L) { 791 Lines = L; 792 } 793 794 StringRef getCloseName() const { 795 return CloseName; 796 } 797 798 unsigned getNumLines() const { 799 return Lines.size(); 800 } 801 802 StringRef getText(unsigned LineIdx) const { 803 return Lines[LineIdx]->getText(); 804 } 805}; 806 807/// A verbatim line command. Verbatim line has an opening command, a single 808/// line of text (up to the newline after the opening command) and has no 809/// closing command. 810class VerbatimLineComment : public BlockCommandComment { 811protected: 812 StringRef Text; 813 SourceLocation TextBegin; 814 815public: 816 VerbatimLineComment(SourceLocation LocBegin, 817 SourceLocation LocEnd, 818 StringRef Name, 819 SourceLocation TextBegin, 820 StringRef Text) : 821 BlockCommandComment(VerbatimLineCommentKind, 822 LocBegin, LocEnd, 823 Name), 824 Text(Text), 825 TextBegin(TextBegin) 826 { } 827 828 static bool classof(const Comment *C) { 829 return C->getCommentKind() == VerbatimLineCommentKind; 830 } 831 832 static bool classof(const VerbatimLineComment *) { return true; } 833 834 child_iterator child_begin() const { return NULL; } 835 836 child_iterator child_end() const { return NULL; } 837 838 StringRef getText() const { 839 return Text; 840 } 841 842 SourceRange getTextRange() const { 843 return SourceRange(TextBegin, getLocEnd()); 844 } 845}; 846 847/// A full comment attached to a declaration, contains block content. 848class FullComment : public Comment { 849 llvm::ArrayRef<BlockContentComment *> Blocks; 850 851public: 852 FullComment(llvm::ArrayRef<BlockContentComment *> Blocks) : 853 Comment(FullCommentKind, SourceLocation(), SourceLocation()), 854 Blocks(Blocks) { 855 if (Blocks.empty()) 856 return; 857 858 setSourceRange(SourceRange(Blocks.front()->getLocStart(), 859 Blocks.back()->getLocEnd())); 860 setLocation(Blocks.front()->getLocStart()); 861 } 862 863 static bool classof(const Comment *C) { 864 return C->getCommentKind() == FullCommentKind; 865 } 866 867 static bool classof(const FullComment *) { return true; } 868 869 child_iterator child_begin() const { 870 return reinterpret_cast<child_iterator>(Blocks.begin()); 871 } 872 873 child_iterator child_end() const { 874 return reinterpret_cast<child_iterator>(Blocks.end()); 875 } 876}; 877 878} // end namespace comments 879} // end namespace clang 880 881#endif 882 883