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