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