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