Comment.h revision 749ace614b6ea1ae11d194a60b18e1e43e1db243
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(comments::FullComment *FC) const; 710 711 SourceRange getParamNameRange() const { 712 return Args[0].Range; 713 } 714 715 bool isParamIndexValid() const LLVM_READONLY { 716 return ParamIndex != InvalidParamIndex; 717 } 718 719 unsigned getParamIndex() const LLVM_READONLY { 720 assert(isParamIndexValid()); 721 return ParamIndex; 722 } 723 724 void setParamIndex(unsigned Index) { 725 ParamIndex = Index; 726 assert(isParamIndexValid()); 727 } 728}; 729 730/// Doxygen \\tparam command, describes a template parameter. 731class TParamCommandComment : public BlockCommandComment { 732private: 733 /// If this template parameter name was resolved (found in template parameter 734 /// list), then this stores a list of position indexes in all template 735 /// parameter lists. 736 /// 737 /// For example: 738 /// \verbatim 739 /// template<typename C, template<typename T> class TT> 740 /// void test(TT<int> aaa); 741 /// \endverbatim 742 /// For C: Position = { 0 } 743 /// For TT: Position = { 1 } 744 /// For T: Position = { 1, 0 } 745 llvm::ArrayRef<unsigned> Position; 746 747public: 748 TParamCommandComment(SourceLocation LocBegin, 749 SourceLocation LocEnd, 750 unsigned CommandID) : 751 BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID) 752 { } 753 754 static bool classof(const Comment *C) { 755 return C->getCommentKind() == TParamCommandCommentKind; 756 } 757 758 bool hasParamName() const { 759 return getNumArgs() > 0; 760 } 761 762 StringRef getParamName() const { 763 return Args[0].Text; 764 } 765 766 SourceRange getParamNameRange() const { 767 return Args[0].Range; 768 } 769 770 bool isPositionValid() const LLVM_READONLY { 771 return !Position.empty(); 772 } 773 774 unsigned getDepth() const { 775 assert(isPositionValid()); 776 return Position.size(); 777 } 778 779 unsigned getIndex(unsigned Depth) const { 780 assert(isPositionValid()); 781 return Position[Depth]; 782 } 783 784 void setPosition(ArrayRef<unsigned> NewPosition) { 785 Position = NewPosition; 786 assert(isPositionValid()); 787 } 788}; 789 790/// A line of text contained in a verbatim block. 791class VerbatimBlockLineComment : public Comment { 792 StringRef Text; 793 794public: 795 VerbatimBlockLineComment(SourceLocation LocBegin, 796 StringRef Text) : 797 Comment(VerbatimBlockLineCommentKind, 798 LocBegin, 799 LocBegin.getLocWithOffset(Text.size())), 800 Text(Text) 801 { } 802 803 static bool classof(const Comment *C) { 804 return C->getCommentKind() == VerbatimBlockLineCommentKind; 805 } 806 807 child_iterator child_begin() const { return NULL; } 808 809 child_iterator child_end() const { return NULL; } 810 811 StringRef getText() const LLVM_READONLY { 812 return Text; 813 } 814}; 815 816/// A verbatim block command (e. g., preformatted code). Verbatim block has an 817/// opening and a closing command and contains multiple lines of text 818/// (VerbatimBlockLineComment nodes). 819class VerbatimBlockComment : public BlockCommandComment { 820protected: 821 StringRef CloseName; 822 SourceLocation CloseNameLocBegin; 823 llvm::ArrayRef<VerbatimBlockLineComment *> Lines; 824 825public: 826 VerbatimBlockComment(SourceLocation LocBegin, 827 SourceLocation LocEnd, 828 unsigned CommandID) : 829 BlockCommandComment(VerbatimBlockCommentKind, 830 LocBegin, LocEnd, CommandID) 831 { } 832 833 static bool classof(const Comment *C) { 834 return C->getCommentKind() == VerbatimBlockCommentKind; 835 } 836 837 child_iterator child_begin() const { 838 return reinterpret_cast<child_iterator>(Lines.begin()); 839 } 840 841 child_iterator child_end() const { 842 return reinterpret_cast<child_iterator>(Lines.end()); 843 } 844 845 void setCloseName(StringRef Name, SourceLocation LocBegin) { 846 CloseName = Name; 847 CloseNameLocBegin = LocBegin; 848 } 849 850 void setLines(llvm::ArrayRef<VerbatimBlockLineComment *> L) { 851 Lines = L; 852 } 853 854 StringRef getCloseName() const { 855 return CloseName; 856 } 857 858 unsigned getNumLines() const { 859 return Lines.size(); 860 } 861 862 StringRef getText(unsigned LineIdx) const { 863 return Lines[LineIdx]->getText(); 864 } 865}; 866 867/// A verbatim line command. Verbatim line has an opening command, a single 868/// line of text (up to the newline after the opening command) and has no 869/// closing command. 870class VerbatimLineComment : public BlockCommandComment { 871protected: 872 StringRef Text; 873 SourceLocation TextBegin; 874 875public: 876 VerbatimLineComment(SourceLocation LocBegin, 877 SourceLocation LocEnd, 878 unsigned CommandID, 879 SourceLocation TextBegin, 880 StringRef Text) : 881 BlockCommandComment(VerbatimLineCommentKind, 882 LocBegin, LocEnd, 883 CommandID), 884 Text(Text), 885 TextBegin(TextBegin) 886 { } 887 888 static bool classof(const Comment *C) { 889 return C->getCommentKind() == VerbatimLineCommentKind; 890 } 891 892 child_iterator child_begin() const { return NULL; } 893 894 child_iterator child_end() const { return NULL; } 895 896 StringRef getText() const { 897 return Text; 898 } 899 900 SourceRange getTextRange() const { 901 return SourceRange(TextBegin, getLocEnd()); 902 } 903}; 904 905/// Information about the declaration, useful to clients of FullComment. 906struct DeclInfo { 907 /// Declaration the comment is attached to. Should not be NULL. 908 const Decl *CommentDecl; 909 910 /// Parameters that can be referenced by \\param if \c CommentDecl is something 911 /// that we consider a "function". 912 ArrayRef<const ParmVarDecl *> ParamVars; 913 914 /// Function result type if \c CommentDecl is something that we consider 915 /// a "function". 916 QualType ResultType; 917 918 /// Template parameters that can be referenced by \\tparam if \c CommentDecl is 919 /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is 920 /// true). 921 const TemplateParameterList *TemplateParameters; 922 923 /// A simplified description of \c CommentDecl kind that should be good enough 924 /// for documentation rendering purposes. 925 enum DeclKind { 926 /// Everything else not explicitly mentioned below. 927 OtherKind, 928 929 /// Something that we consider a "function": 930 /// \li function, 931 /// \li function template, 932 /// \li function template specialization, 933 /// \li member function, 934 /// \li member function template, 935 /// \li member function template specialization, 936 /// \li ObjC method, 937 /// \li a typedef for a function pointer, member function pointer, 938 /// ObjC block. 939 FunctionKind, 940 941 /// Something that we consider a "class": 942 /// \li class/struct, 943 /// \li class template, 944 /// \li class template (partial) specialization. 945 ClassKind, 946 947 /// Something that we consider a "variable": 948 /// \li namespace scope variables; 949 /// \li static and non-static class data members; 950 /// \li enumerators. 951 VariableKind, 952 953 /// A C++ namespace. 954 NamespaceKind, 955 956 /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration), 957 /// see \c TypedefNameDecl. 958 TypedefKind, 959 960 /// An enumeration or scoped enumeration. 961 EnumKind 962 }; 963 964 /// What kind of template specialization \c CommentDecl is. 965 enum TemplateDeclKind { 966 NotTemplate, 967 Template, 968 TemplateSpecialization, 969 TemplatePartialSpecialization 970 }; 971 972 /// If false, only \c CommentDecl is valid. 973 unsigned IsFilled : 1; 974 975 /// Simplified kind of \c CommentDecl, see\c DeclKind enum. 976 unsigned Kind : 3; 977 978 /// Is \c CommentDecl a template declaration. 979 unsigned TemplateKind : 2; 980 981 /// Is \c CommentDecl an ObjCMethodDecl. 982 unsigned IsObjCMethod : 1; 983 984 /// Is \c ThisDecl a non-static member function of C++ class or 985 /// instance method of ObjC class. 986 /// Can be true only if \c IsFunctionDecl is true. 987 unsigned IsInstanceMethod : 1; 988 989 /// Is \c CommentDecl a static member function of C++ class or 990 /// class method of ObjC class. 991 /// Can be true only if \c IsFunctionDecl is true. 992 unsigned IsClassMethod : 1; 993 994 void fill(); 995 996 DeclKind getKind() const LLVM_READONLY { 997 return static_cast<DeclKind>(Kind); 998 } 999 1000 TemplateDeclKind getTemplateKind() const LLVM_READONLY { 1001 return static_cast<TemplateDeclKind>(TemplateKind); 1002 } 1003}; 1004 1005/// A full comment attached to a declaration, contains block content. 1006class FullComment : public Comment { 1007 llvm::ArrayRef<BlockContentComment *> Blocks; 1008 DeclInfo *ThisDeclInfo; 1009 1010public: 1011 FullComment(llvm::ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) : 1012 Comment(FullCommentKind, SourceLocation(), SourceLocation()), 1013 Blocks(Blocks), ThisDeclInfo(D) { 1014 if (Blocks.empty()) 1015 return; 1016 1017 setSourceRange(SourceRange(Blocks.front()->getLocStart(), 1018 Blocks.back()->getLocEnd())); 1019 setLocation(Blocks.front()->getLocStart()); 1020 } 1021 1022 static bool classof(const Comment *C) { 1023 return C->getCommentKind() == FullCommentKind; 1024 } 1025 1026 child_iterator child_begin() const { 1027 return reinterpret_cast<child_iterator>(Blocks.begin()); 1028 } 1029 1030 child_iterator child_end() const { 1031 return reinterpret_cast<child_iterator>(Blocks.end()); 1032 } 1033 1034 const Decl *getDecl() const LLVM_READONLY { 1035 return ThisDeclInfo->CommentDecl; 1036 } 1037 1038 const DeclInfo *getDeclInfo() const LLVM_READONLY { 1039 if (!ThisDeclInfo->IsFilled) 1040 ThisDeclInfo->fill(); 1041 return ThisDeclInfo; 1042 } 1043 1044 DeclInfo *getThisDeclInfo() const LLVM_READONLY { 1045 return ThisDeclInfo; 1046 } 1047 1048 llvm::ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; } 1049 1050}; 1051} // end namespace comments 1052} // end namespace clang 1053 1054#endif 1055 1056