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