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