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