clang API Documentation
00001 //===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines comment AST nodes. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_CLANG_AST_COMMENT_H 00015 #define LLVM_CLANG_AST_COMMENT_H 00016 00017 #include "clang/AST/CommentCommandTraits.h" 00018 #include "clang/AST/DeclObjC.h" 00019 #include "clang/AST/Type.h" 00020 #include "clang/Basic/SourceLocation.h" 00021 #include "llvm/ADT/ArrayRef.h" 00022 #include "llvm/ADT/StringRef.h" 00023 00024 namespace clang { 00025 class Decl; 00026 class ParmVarDecl; 00027 class TemplateParameterList; 00028 00029 namespace comments { 00030 class FullComment; 00031 00032 /// Describes the syntax that was used in a documentation command. 00033 /// 00034 /// Exact values of this enumeration are important because they used to select 00035 /// parts of diagnostic messages. Audit diagnostics before changing or adding 00036 /// a new value. 00037 enum CommandMarkerKind { 00038 /// Command started with a backslash character: 00039 /// \code 00040 /// \foo 00041 /// \endcode 00042 CMK_Backslash = 0, 00043 00044 /// Command started with an 'at' character: 00045 /// \code 00046 /// @foo 00047 /// \endcode 00048 CMK_At = 1 00049 }; 00050 00051 /// Any part of the comment. 00052 /// Abstract class. 00053 class Comment { 00054 protected: 00055 /// Preferred location to show caret. 00056 SourceLocation Loc; 00057 00058 /// Source range of this AST node. 00059 SourceRange Range; 00060 00061 class CommentBitfields { 00062 friend class Comment; 00063 00064 /// Type of this AST node. 00065 unsigned Kind : 8; 00066 }; 00067 enum { NumCommentBits = 8 }; 00068 00069 class InlineContentCommentBitfields { 00070 friend class InlineContentComment; 00071 00072 unsigned : NumCommentBits; 00073 00074 /// True if there is a newline after this inline content node. 00075 /// (There is no separate AST node for a newline.) 00076 unsigned HasTrailingNewline : 1; 00077 }; 00078 enum { NumInlineContentCommentBits = NumCommentBits + 1 }; 00079 00080 class TextCommentBitfields { 00081 friend class TextComment; 00082 00083 unsigned : NumInlineContentCommentBits; 00084 00085 /// True if \c IsWhitespace field contains a valid value. 00086 mutable unsigned IsWhitespaceValid : 1; 00087 00088 /// True if this comment AST node contains only whitespace. 00089 mutable unsigned IsWhitespace : 1; 00090 }; 00091 enum { NumTextCommentBits = NumInlineContentCommentBits + 2 }; 00092 00093 class InlineCommandCommentBitfields { 00094 friend class InlineCommandComment; 00095 00096 unsigned : NumInlineContentCommentBits; 00097 00098 unsigned RenderKind : 2; 00099 unsigned CommandID : CommandInfo::NumCommandIDBits; 00100 }; 00101 enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 + 00102 CommandInfo::NumCommandIDBits }; 00103 00104 class HTMLTagCommentBitfields { 00105 friend class HTMLTagComment; 00106 00107 unsigned : NumInlineContentCommentBits; 00108 00109 /// True if we found that this tag is malformed in some way. 00110 unsigned IsMalformed : 1; 00111 }; 00112 enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 }; 00113 00114 class HTMLStartTagCommentBitfields { 00115 friend class HTMLStartTagComment; 00116 00117 unsigned : NumHTMLTagCommentBits; 00118 00119 /// True if this tag is self-closing (e. g., <br />). This is based on tag 00120 /// spelling in comment (plain <br> would not set this flag). 00121 unsigned IsSelfClosing : 1; 00122 }; 00123 enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 }; 00124 00125 class ParagraphCommentBitfields { 00126 friend class ParagraphComment; 00127 00128 unsigned : NumCommentBits; 00129 00130 /// True if \c IsWhitespace field contains a valid value. 00131 mutable unsigned IsWhitespaceValid : 1; 00132 00133 /// True if this comment AST node contains only whitespace. 00134 mutable unsigned IsWhitespace : 1; 00135 }; 00136 enum { NumParagraphCommentBits = NumCommentBits + 2 }; 00137 00138 class BlockCommandCommentBitfields { 00139 friend class BlockCommandComment; 00140 00141 unsigned : NumCommentBits; 00142 00143 unsigned CommandID : CommandInfo::NumCommandIDBits; 00144 00145 /// Describes the syntax that was used in a documentation command. 00146 /// Contains values from CommandMarkerKind enum. 00147 unsigned CommandMarker : 1; 00148 }; 00149 enum { NumBlockCommandCommentBits = NumCommentBits + 00150 CommandInfo::NumCommandIDBits + 1 }; 00151 00152 class ParamCommandCommentBitfields { 00153 friend class ParamCommandComment; 00154 00155 unsigned : NumBlockCommandCommentBits; 00156 00157 /// Parameter passing direction, see ParamCommandComment::PassDirection. 00158 unsigned Direction : 2; 00159 00160 /// True if direction was specified explicitly in the comment. 00161 unsigned IsDirectionExplicit : 1; 00162 }; 00163 enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 }; 00164 00165 union { 00166 CommentBitfields CommentBits; 00167 InlineContentCommentBitfields InlineContentCommentBits; 00168 TextCommentBitfields TextCommentBits; 00169 InlineCommandCommentBitfields InlineCommandCommentBits; 00170 HTMLTagCommentBitfields HTMLTagCommentBits; 00171 HTMLStartTagCommentBitfields HTMLStartTagCommentBits; 00172 ParagraphCommentBitfields ParagraphCommentBits; 00173 BlockCommandCommentBitfields BlockCommandCommentBits; 00174 ParamCommandCommentBitfields ParamCommandCommentBits; 00175 }; 00176 00177 void setSourceRange(SourceRange SR) { 00178 Range = SR; 00179 } 00180 00181 void setLocation(SourceLocation L) { 00182 Loc = L; 00183 } 00184 00185 public: 00186 enum CommentKind { 00187 NoCommentKind = 0, 00188 #define COMMENT(CLASS, PARENT) CLASS##Kind, 00189 #define COMMENT_RANGE(BASE, FIRST, LAST) \ 00190 First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind, 00191 #define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \ 00192 First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind 00193 #define ABSTRACT_COMMENT(COMMENT) 00194 #include "clang/AST/CommentNodes.inc" 00195 }; 00196 00197 Comment(CommentKind K, 00198 SourceLocation LocBegin, 00199 SourceLocation LocEnd) : 00200 Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) { 00201 CommentBits.Kind = K; 00202 } 00203 00204 CommentKind getCommentKind() const { 00205 return static_cast<CommentKind>(CommentBits.Kind); 00206 } 00207 00208 const char *getCommentKindName() const; 00209 00210 void dump() const; 00211 void dumpColor() const; 00212 void dump(const ASTContext &Context) const; 00213 void dump(raw_ostream &OS, const CommandTraits *Traits, 00214 const SourceManager *SM) const; 00215 00216 SourceRange getSourceRange() const LLVM_READONLY { return Range; } 00217 00218 SourceLocation getLocStart() const LLVM_READONLY { 00219 return Range.getBegin(); 00220 } 00221 00222 SourceLocation getLocEnd() const LLVM_READONLY { 00223 return Range.getEnd(); 00224 } 00225 00226 SourceLocation getLocation() const LLVM_READONLY { return Loc; } 00227 00228 typedef Comment * const *child_iterator; 00229 00230 child_iterator child_begin() const; 00231 child_iterator child_end() const; 00232 00233 // TODO: const child iterator 00234 00235 unsigned child_count() const { 00236 return child_end() - child_begin(); 00237 } 00238 }; 00239 00240 /// Inline content (contained within a block). 00241 /// Abstract class. 00242 class InlineContentComment : public Comment { 00243 protected: 00244 InlineContentComment(CommentKind K, 00245 SourceLocation LocBegin, 00246 SourceLocation LocEnd) : 00247 Comment(K, LocBegin, LocEnd) { 00248 InlineContentCommentBits.HasTrailingNewline = 0; 00249 } 00250 00251 public: 00252 static bool classof(const Comment *C) { 00253 return C->getCommentKind() >= FirstInlineContentCommentConstant && 00254 C->getCommentKind() <= LastInlineContentCommentConstant; 00255 } 00256 00257 void addTrailingNewline() { 00258 InlineContentCommentBits.HasTrailingNewline = 1; 00259 } 00260 00261 bool hasTrailingNewline() const { 00262 return InlineContentCommentBits.HasTrailingNewline; 00263 } 00264 }; 00265 00266 /// Plain text. 00267 class TextComment : public InlineContentComment { 00268 StringRef Text; 00269 00270 public: 00271 TextComment(SourceLocation LocBegin, 00272 SourceLocation LocEnd, 00273 StringRef Text) : 00274 InlineContentComment(TextCommentKind, LocBegin, LocEnd), 00275 Text(Text) { 00276 TextCommentBits.IsWhitespaceValid = false; 00277 } 00278 00279 static bool classof(const Comment *C) { 00280 return C->getCommentKind() == TextCommentKind; 00281 } 00282 00283 child_iterator child_begin() const { return nullptr; } 00284 00285 child_iterator child_end() const { return nullptr; } 00286 00287 StringRef getText() const LLVM_READONLY { return Text; } 00288 00289 bool isWhitespace() const { 00290 if (TextCommentBits.IsWhitespaceValid) 00291 return TextCommentBits.IsWhitespace; 00292 00293 TextCommentBits.IsWhitespace = isWhitespaceNoCache(); 00294 TextCommentBits.IsWhitespaceValid = true; 00295 return TextCommentBits.IsWhitespace; 00296 } 00297 00298 private: 00299 bool isWhitespaceNoCache() const; 00300 }; 00301 00302 /// A command with word-like arguments that is considered inline content. 00303 class InlineCommandComment : public InlineContentComment { 00304 public: 00305 struct Argument { 00306 SourceRange Range; 00307 StringRef Text; 00308 00309 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } 00310 }; 00311 00312 /// The most appropriate rendering mode for this command, chosen on command 00313 /// semantics in Doxygen. 00314 enum RenderKind { 00315 RenderNormal, 00316 RenderBold, 00317 RenderMonospaced, 00318 RenderEmphasized 00319 }; 00320 00321 protected: 00322 /// Command arguments. 00323 ArrayRef<Argument> Args; 00324 00325 public: 00326 InlineCommandComment(SourceLocation LocBegin, 00327 SourceLocation LocEnd, 00328 unsigned CommandID, 00329 RenderKind RK, 00330 ArrayRef<Argument> Args) : 00331 InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), 00332 Args(Args) { 00333 InlineCommandCommentBits.RenderKind = RK; 00334 InlineCommandCommentBits.CommandID = CommandID; 00335 } 00336 00337 static bool classof(const Comment *C) { 00338 return C->getCommentKind() == InlineCommandCommentKind; 00339 } 00340 00341 child_iterator child_begin() const { return nullptr; } 00342 00343 child_iterator child_end() const { return nullptr; } 00344 00345 unsigned getCommandID() const { 00346 return InlineCommandCommentBits.CommandID; 00347 } 00348 00349 StringRef getCommandName(const CommandTraits &Traits) const { 00350 return Traits.getCommandInfo(getCommandID())->Name; 00351 } 00352 00353 SourceRange getCommandNameRange() const { 00354 return SourceRange(getLocStart().getLocWithOffset(-1), 00355 getLocEnd()); 00356 } 00357 00358 RenderKind getRenderKind() const { 00359 return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind); 00360 } 00361 00362 unsigned getNumArgs() const { 00363 return Args.size(); 00364 } 00365 00366 StringRef getArgText(unsigned Idx) const { 00367 return Args[Idx].Text; 00368 } 00369 00370 SourceRange getArgRange(unsigned Idx) const { 00371 return Args[Idx].Range; 00372 } 00373 }; 00374 00375 /// Abstract class for opening and closing HTML tags. HTML tags are always 00376 /// treated as inline content (regardless HTML semantics). 00377 class HTMLTagComment : public InlineContentComment { 00378 protected: 00379 StringRef TagName; 00380 SourceRange TagNameRange; 00381 00382 HTMLTagComment(CommentKind K, 00383 SourceLocation LocBegin, 00384 SourceLocation LocEnd, 00385 StringRef TagName, 00386 SourceLocation TagNameBegin, 00387 SourceLocation TagNameEnd) : 00388 InlineContentComment(K, LocBegin, LocEnd), 00389 TagName(TagName), 00390 TagNameRange(TagNameBegin, TagNameEnd) { 00391 setLocation(TagNameBegin); 00392 HTMLTagCommentBits.IsMalformed = 0; 00393 } 00394 00395 public: 00396 static bool classof(const Comment *C) { 00397 return C->getCommentKind() >= FirstHTMLTagCommentConstant && 00398 C->getCommentKind() <= LastHTMLTagCommentConstant; 00399 } 00400 00401 StringRef getTagName() const LLVM_READONLY { return TagName; } 00402 00403 SourceRange getTagNameSourceRange() const LLVM_READONLY { 00404 SourceLocation L = getLocation(); 00405 return SourceRange(L.getLocWithOffset(1), 00406 L.getLocWithOffset(1 + TagName.size())); 00407 } 00408 00409 bool isMalformed() const { 00410 return HTMLTagCommentBits.IsMalformed; 00411 } 00412 00413 void setIsMalformed() { 00414 HTMLTagCommentBits.IsMalformed = 1; 00415 } 00416 }; 00417 00418 /// An opening HTML tag with attributes. 00419 class HTMLStartTagComment : public HTMLTagComment { 00420 public: 00421 class Attribute { 00422 public: 00423 SourceLocation NameLocBegin; 00424 StringRef Name; 00425 00426 SourceLocation EqualsLoc; 00427 00428 SourceRange ValueRange; 00429 StringRef Value; 00430 00431 Attribute() { } 00432 00433 Attribute(SourceLocation NameLocBegin, StringRef Name) : 00434 NameLocBegin(NameLocBegin), Name(Name), 00435 EqualsLoc(SourceLocation()), 00436 ValueRange(SourceRange()), Value(StringRef()) 00437 { } 00438 00439 Attribute(SourceLocation NameLocBegin, StringRef Name, 00440 SourceLocation EqualsLoc, 00441 SourceRange ValueRange, StringRef Value) : 00442 NameLocBegin(NameLocBegin), Name(Name), 00443 EqualsLoc(EqualsLoc), 00444 ValueRange(ValueRange), Value(Value) 00445 { } 00446 00447 SourceLocation getNameLocEnd() const { 00448 return NameLocBegin.getLocWithOffset(Name.size()); 00449 } 00450 00451 SourceRange getNameRange() const { 00452 return SourceRange(NameLocBegin, getNameLocEnd()); 00453 } 00454 }; 00455 00456 private: 00457 ArrayRef<Attribute> Attributes; 00458 00459 public: 00460 HTMLStartTagComment(SourceLocation LocBegin, 00461 StringRef TagName) : 00462 HTMLTagComment(HTMLStartTagCommentKind, 00463 LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()), 00464 TagName, 00465 LocBegin.getLocWithOffset(1), 00466 LocBegin.getLocWithOffset(1 + TagName.size())) { 00467 HTMLStartTagCommentBits.IsSelfClosing = false; 00468 } 00469 00470 static bool classof(const Comment *C) { 00471 return C->getCommentKind() == HTMLStartTagCommentKind; 00472 } 00473 00474 child_iterator child_begin() const { return nullptr; } 00475 00476 child_iterator child_end() const { return nullptr; } 00477 00478 unsigned getNumAttrs() const { 00479 return Attributes.size(); 00480 } 00481 00482 const Attribute &getAttr(unsigned Idx) const { 00483 return Attributes[Idx]; 00484 } 00485 00486 void setAttrs(ArrayRef<Attribute> Attrs) { 00487 Attributes = Attrs; 00488 if (!Attrs.empty()) { 00489 const Attribute &Attr = Attrs.back(); 00490 SourceLocation L = Attr.ValueRange.getEnd(); 00491 if (L.isValid()) 00492 Range.setEnd(L); 00493 else { 00494 Range.setEnd(Attr.getNameLocEnd()); 00495 } 00496 } 00497 } 00498 00499 void setGreaterLoc(SourceLocation GreaterLoc) { 00500 Range.setEnd(GreaterLoc); 00501 } 00502 00503 bool isSelfClosing() const { 00504 return HTMLStartTagCommentBits.IsSelfClosing; 00505 } 00506 00507 void setSelfClosing() { 00508 HTMLStartTagCommentBits.IsSelfClosing = true; 00509 } 00510 }; 00511 00512 /// A closing HTML tag. 00513 class HTMLEndTagComment : public HTMLTagComment { 00514 public: 00515 HTMLEndTagComment(SourceLocation LocBegin, 00516 SourceLocation LocEnd, 00517 StringRef TagName) : 00518 HTMLTagComment(HTMLEndTagCommentKind, 00519 LocBegin, LocEnd, 00520 TagName, 00521 LocBegin.getLocWithOffset(2), 00522 LocBegin.getLocWithOffset(2 + TagName.size())) 00523 { } 00524 00525 static bool classof(const Comment *C) { 00526 return C->getCommentKind() == HTMLEndTagCommentKind; 00527 } 00528 00529 child_iterator child_begin() const { return nullptr; } 00530 00531 child_iterator child_end() const { return nullptr; } 00532 }; 00533 00534 /// Block content (contains inline content). 00535 /// Abstract class. 00536 class BlockContentComment : public Comment { 00537 protected: 00538 BlockContentComment(CommentKind K, 00539 SourceLocation LocBegin, 00540 SourceLocation LocEnd) : 00541 Comment(K, LocBegin, LocEnd) 00542 { } 00543 00544 public: 00545 static bool classof(const Comment *C) { 00546 return C->getCommentKind() >= FirstBlockContentCommentConstant && 00547 C->getCommentKind() <= LastBlockContentCommentConstant; 00548 } 00549 }; 00550 00551 /// A single paragraph that contains inline content. 00552 class ParagraphComment : public BlockContentComment { 00553 ArrayRef<InlineContentComment *> Content; 00554 00555 public: 00556 ParagraphComment(ArrayRef<InlineContentComment *> Content) : 00557 BlockContentComment(ParagraphCommentKind, 00558 SourceLocation(), 00559 SourceLocation()), 00560 Content(Content) { 00561 if (Content.empty()) { 00562 ParagraphCommentBits.IsWhitespace = true; 00563 ParagraphCommentBits.IsWhitespaceValid = true; 00564 return; 00565 } 00566 00567 ParagraphCommentBits.IsWhitespaceValid = false; 00568 00569 setSourceRange(SourceRange(Content.front()->getLocStart(), 00570 Content.back()->getLocEnd())); 00571 setLocation(Content.front()->getLocStart()); 00572 } 00573 00574 static bool classof(const Comment *C) { 00575 return C->getCommentKind() == ParagraphCommentKind; 00576 } 00577 00578 child_iterator child_begin() const { 00579 return reinterpret_cast<child_iterator>(Content.begin()); 00580 } 00581 00582 child_iterator child_end() const { 00583 return reinterpret_cast<child_iterator>(Content.end()); 00584 } 00585 00586 bool isWhitespace() const { 00587 if (ParagraphCommentBits.IsWhitespaceValid) 00588 return ParagraphCommentBits.IsWhitespace; 00589 00590 ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache(); 00591 ParagraphCommentBits.IsWhitespaceValid = true; 00592 return ParagraphCommentBits.IsWhitespace; 00593 } 00594 00595 private: 00596 bool isWhitespaceNoCache() const; 00597 }; 00598 00599 /// A command that has zero or more word-like arguments (number of word-like 00600 /// arguments depends on command name) and a paragraph as an argument 00601 /// (e. g., \\brief). 00602 class BlockCommandComment : public BlockContentComment { 00603 public: 00604 struct Argument { 00605 SourceRange Range; 00606 StringRef Text; 00607 00608 Argument() { } 00609 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } 00610 }; 00611 00612 protected: 00613 /// Word-like arguments. 00614 ArrayRef<Argument> Args; 00615 00616 /// Paragraph argument. 00617 ParagraphComment *Paragraph; 00618 00619 BlockCommandComment(CommentKind K, 00620 SourceLocation LocBegin, 00621 SourceLocation LocEnd, 00622 unsigned CommandID, 00623 CommandMarkerKind CommandMarker) : 00624 BlockContentComment(K, LocBegin, LocEnd), 00625 Paragraph(nullptr) { 00626 setLocation(getCommandNameBeginLoc()); 00627 BlockCommandCommentBits.CommandID = CommandID; 00628 BlockCommandCommentBits.CommandMarker = CommandMarker; 00629 } 00630 00631 public: 00632 BlockCommandComment(SourceLocation LocBegin, 00633 SourceLocation LocEnd, 00634 unsigned CommandID, 00635 CommandMarkerKind CommandMarker) : 00636 BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), 00637 Paragraph(nullptr) { 00638 setLocation(getCommandNameBeginLoc()); 00639 BlockCommandCommentBits.CommandID = CommandID; 00640 BlockCommandCommentBits.CommandMarker = CommandMarker; 00641 } 00642 00643 static bool classof(const Comment *C) { 00644 return C->getCommentKind() >= FirstBlockCommandCommentConstant && 00645 C->getCommentKind() <= LastBlockCommandCommentConstant; 00646 } 00647 00648 child_iterator child_begin() const { 00649 return reinterpret_cast<child_iterator>(&Paragraph); 00650 } 00651 00652 child_iterator child_end() const { 00653 return reinterpret_cast<child_iterator>(&Paragraph + 1); 00654 } 00655 00656 unsigned getCommandID() const { 00657 return BlockCommandCommentBits.CommandID; 00658 } 00659 00660 StringRef getCommandName(const CommandTraits &Traits) const { 00661 return Traits.getCommandInfo(getCommandID())->Name; 00662 } 00663 00664 SourceLocation getCommandNameBeginLoc() const { 00665 return getLocStart().getLocWithOffset(1); 00666 } 00667 00668 SourceRange getCommandNameRange(const CommandTraits &Traits) const { 00669 StringRef Name = getCommandName(Traits); 00670 return SourceRange(getCommandNameBeginLoc(), 00671 getLocStart().getLocWithOffset(1 + Name.size())); 00672 } 00673 00674 unsigned getNumArgs() const { 00675 return Args.size(); 00676 } 00677 00678 StringRef getArgText(unsigned Idx) const { 00679 return Args[Idx].Text; 00680 } 00681 00682 SourceRange getArgRange(unsigned Idx) const { 00683 return Args[Idx].Range; 00684 } 00685 00686 void setArgs(ArrayRef<Argument> A) { 00687 Args = A; 00688 if (Args.size() > 0) { 00689 SourceLocation NewLocEnd = Args.back().Range.getEnd(); 00690 if (NewLocEnd.isValid()) 00691 setSourceRange(SourceRange(getLocStart(), NewLocEnd)); 00692 } 00693 } 00694 00695 ParagraphComment *getParagraph() const LLVM_READONLY { 00696 return Paragraph; 00697 } 00698 00699 bool hasNonWhitespaceParagraph() const { 00700 return Paragraph && !Paragraph->isWhitespace(); 00701 } 00702 00703 void setParagraph(ParagraphComment *PC) { 00704 Paragraph = PC; 00705 SourceLocation NewLocEnd = PC->getLocEnd(); 00706 if (NewLocEnd.isValid()) 00707 setSourceRange(SourceRange(getLocStart(), NewLocEnd)); 00708 } 00709 00710 CommandMarkerKind getCommandMarker() const LLVM_READONLY { 00711 return static_cast<CommandMarkerKind>( 00712 BlockCommandCommentBits.CommandMarker); 00713 } 00714 }; 00715 00716 /// Doxygen \\param command. 00717 class ParamCommandComment : public BlockCommandComment { 00718 private: 00719 /// Parameter index in the function declaration. 00720 unsigned ParamIndex; 00721 00722 public: 00723 enum : unsigned { 00724 InvalidParamIndex = ~0U, 00725 VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U 00726 }; 00727 00728 ParamCommandComment(SourceLocation LocBegin, 00729 SourceLocation LocEnd, 00730 unsigned CommandID, 00731 CommandMarkerKind CommandMarker) : 00732 BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, 00733 CommandID, CommandMarker), 00734 ParamIndex(InvalidParamIndex) { 00735 ParamCommandCommentBits.Direction = In; 00736 ParamCommandCommentBits.IsDirectionExplicit = false; 00737 } 00738 00739 static bool classof(const Comment *C) { 00740 return C->getCommentKind() == ParamCommandCommentKind; 00741 } 00742 00743 enum PassDirection { 00744 In, 00745 Out, 00746 InOut 00747 }; 00748 00749 static const char *getDirectionAsString(PassDirection D); 00750 00751 PassDirection getDirection() const LLVM_READONLY { 00752 return static_cast<PassDirection>(ParamCommandCommentBits.Direction); 00753 } 00754 00755 bool isDirectionExplicit() const LLVM_READONLY { 00756 return ParamCommandCommentBits.IsDirectionExplicit; 00757 } 00758 00759 void setDirection(PassDirection Direction, bool Explicit) { 00760 ParamCommandCommentBits.Direction = Direction; 00761 ParamCommandCommentBits.IsDirectionExplicit = Explicit; 00762 } 00763 00764 bool hasParamName() const { 00765 return getNumArgs() > 0; 00766 } 00767 00768 StringRef getParamName(const FullComment *FC) const; 00769 00770 StringRef getParamNameAsWritten() const { 00771 return Args[0].Text; 00772 } 00773 00774 SourceRange getParamNameRange() const { 00775 return Args[0].Range; 00776 } 00777 00778 bool isParamIndexValid() const LLVM_READONLY { 00779 return ParamIndex != InvalidParamIndex; 00780 } 00781 00782 bool isVarArgParam() const LLVM_READONLY { 00783 return ParamIndex == VarArgParamIndex; 00784 } 00785 00786 void setIsVarArgParam() { 00787 ParamIndex = VarArgParamIndex; 00788 assert(isParamIndexValid()); 00789 } 00790 00791 unsigned getParamIndex() const LLVM_READONLY { 00792 assert(isParamIndexValid()); 00793 assert(!isVarArgParam()); 00794 return ParamIndex; 00795 } 00796 00797 void setParamIndex(unsigned Index) { 00798 ParamIndex = Index; 00799 assert(isParamIndexValid()); 00800 assert(!isVarArgParam()); 00801 } 00802 }; 00803 00804 /// Doxygen \\tparam command, describes a template parameter. 00805 class TParamCommandComment : public BlockCommandComment { 00806 private: 00807 /// If this template parameter name was resolved (found in template parameter 00808 /// list), then this stores a list of position indexes in all template 00809 /// parameter lists. 00810 /// 00811 /// For example: 00812 /// \verbatim 00813 /// template<typename C, template<typename T> class TT> 00814 /// void test(TT<int> aaa); 00815 /// \endverbatim 00816 /// For C: Position = { 0 } 00817 /// For TT: Position = { 1 } 00818 /// For T: Position = { 1, 0 } 00819 ArrayRef<unsigned> Position; 00820 00821 public: 00822 TParamCommandComment(SourceLocation LocBegin, 00823 SourceLocation LocEnd, 00824 unsigned CommandID, 00825 CommandMarkerKind CommandMarker) : 00826 BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID, 00827 CommandMarker) 00828 { } 00829 00830 static bool classof(const Comment *C) { 00831 return C->getCommentKind() == TParamCommandCommentKind; 00832 } 00833 00834 bool hasParamName() const { 00835 return getNumArgs() > 0; 00836 } 00837 00838 StringRef getParamName(const FullComment *FC) const; 00839 00840 StringRef getParamNameAsWritten() const { 00841 return Args[0].Text; 00842 } 00843 00844 SourceRange getParamNameRange() const { 00845 return Args[0].Range; 00846 } 00847 00848 bool isPositionValid() const LLVM_READONLY { 00849 return !Position.empty(); 00850 } 00851 00852 unsigned getDepth() const { 00853 assert(isPositionValid()); 00854 return Position.size(); 00855 } 00856 00857 unsigned getIndex(unsigned Depth) const { 00858 assert(isPositionValid()); 00859 return Position[Depth]; 00860 } 00861 00862 void setPosition(ArrayRef<unsigned> NewPosition) { 00863 Position = NewPosition; 00864 assert(isPositionValid()); 00865 } 00866 }; 00867 00868 /// A line of text contained in a verbatim block. 00869 class VerbatimBlockLineComment : public Comment { 00870 StringRef Text; 00871 00872 public: 00873 VerbatimBlockLineComment(SourceLocation LocBegin, 00874 StringRef Text) : 00875 Comment(VerbatimBlockLineCommentKind, 00876 LocBegin, 00877 LocBegin.getLocWithOffset(Text.size())), 00878 Text(Text) 00879 { } 00880 00881 static bool classof(const Comment *C) { 00882 return C->getCommentKind() == VerbatimBlockLineCommentKind; 00883 } 00884 00885 child_iterator child_begin() const { return nullptr; } 00886 00887 child_iterator child_end() const { return nullptr; } 00888 00889 StringRef getText() const LLVM_READONLY { 00890 return Text; 00891 } 00892 }; 00893 00894 /// A verbatim block command (e. g., preformatted code). Verbatim block has an 00895 /// opening and a closing command and contains multiple lines of text 00896 /// (VerbatimBlockLineComment nodes). 00897 class VerbatimBlockComment : public BlockCommandComment { 00898 protected: 00899 StringRef CloseName; 00900 SourceLocation CloseNameLocBegin; 00901 ArrayRef<VerbatimBlockLineComment *> Lines; 00902 00903 public: 00904 VerbatimBlockComment(SourceLocation LocBegin, 00905 SourceLocation LocEnd, 00906 unsigned CommandID) : 00907 BlockCommandComment(VerbatimBlockCommentKind, 00908 LocBegin, LocEnd, CommandID, 00909 CMK_At) // FIXME: improve source fidelity. 00910 { } 00911 00912 static bool classof(const Comment *C) { 00913 return C->getCommentKind() == VerbatimBlockCommentKind; 00914 } 00915 00916 child_iterator child_begin() const { 00917 return reinterpret_cast<child_iterator>(Lines.begin()); 00918 } 00919 00920 child_iterator child_end() const { 00921 return reinterpret_cast<child_iterator>(Lines.end()); 00922 } 00923 00924 void setCloseName(StringRef Name, SourceLocation LocBegin) { 00925 CloseName = Name; 00926 CloseNameLocBegin = LocBegin; 00927 } 00928 00929 void setLines(ArrayRef<VerbatimBlockLineComment *> L) { 00930 Lines = L; 00931 } 00932 00933 StringRef getCloseName() const { 00934 return CloseName; 00935 } 00936 00937 unsigned getNumLines() const { 00938 return Lines.size(); 00939 } 00940 00941 StringRef getText(unsigned LineIdx) const { 00942 return Lines[LineIdx]->getText(); 00943 } 00944 }; 00945 00946 /// A verbatim line command. Verbatim line has an opening command, a single 00947 /// line of text (up to the newline after the opening command) and has no 00948 /// closing command. 00949 class VerbatimLineComment : public BlockCommandComment { 00950 protected: 00951 StringRef Text; 00952 SourceLocation TextBegin; 00953 00954 public: 00955 VerbatimLineComment(SourceLocation LocBegin, 00956 SourceLocation LocEnd, 00957 unsigned CommandID, 00958 SourceLocation TextBegin, 00959 StringRef Text) : 00960 BlockCommandComment(VerbatimLineCommentKind, 00961 LocBegin, LocEnd, 00962 CommandID, 00963 CMK_At), // FIXME: improve source fidelity. 00964 Text(Text), 00965 TextBegin(TextBegin) 00966 { } 00967 00968 static bool classof(const Comment *C) { 00969 return C->getCommentKind() == VerbatimLineCommentKind; 00970 } 00971 00972 child_iterator child_begin() const { return nullptr; } 00973 00974 child_iterator child_end() const { return nullptr; } 00975 00976 StringRef getText() const { 00977 return Text; 00978 } 00979 00980 SourceRange getTextRange() const { 00981 return SourceRange(TextBegin, getLocEnd()); 00982 } 00983 }; 00984 00985 /// Information about the declaration, useful to clients of FullComment. 00986 struct DeclInfo { 00987 /// Declaration the comment is actually attached to (in the source). 00988 /// Should not be NULL. 00989 const Decl *CommentDecl; 00990 00991 /// CurrentDecl is the declaration with which the FullComment is associated. 00992 /// 00993 /// It can be different from \c CommentDecl. It happens when we we decide 00994 /// that the comment originally attached to \c CommentDecl is fine for 00995 /// \c CurrentDecl too (for example, for a redeclaration or an overrider of 00996 /// \c CommentDecl). 00997 /// 00998 /// The information in the DeclInfo corresponds to CurrentDecl. 00999 const Decl *CurrentDecl; 01000 01001 /// Parameters that can be referenced by \\param if \c CommentDecl is something 01002 /// that we consider a "function". 01003 ArrayRef<const ParmVarDecl *> ParamVars; 01004 01005 /// Function return type if \c CommentDecl is something that we consider 01006 /// a "function". 01007 QualType ReturnType; 01008 01009 /// Template parameters that can be referenced by \\tparam if \c CommentDecl is 01010 /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is 01011 /// true). 01012 const TemplateParameterList *TemplateParameters; 01013 01014 /// A simplified description of \c CommentDecl kind that should be good enough 01015 /// for documentation rendering purposes. 01016 enum DeclKind { 01017 /// Everything else not explicitly mentioned below. 01018 OtherKind, 01019 01020 /// Something that we consider a "function": 01021 /// \li function, 01022 /// \li function template, 01023 /// \li function template specialization, 01024 /// \li member function, 01025 /// \li member function template, 01026 /// \li member function template specialization, 01027 /// \li ObjC method, 01028 /// \li a typedef for a function pointer, member function pointer, 01029 /// ObjC block. 01030 FunctionKind, 01031 01032 /// Something that we consider a "class": 01033 /// \li class/struct, 01034 /// \li class template, 01035 /// \li class template (partial) specialization. 01036 ClassKind, 01037 01038 /// Something that we consider a "variable": 01039 /// \li namespace scope variables; 01040 /// \li static and non-static class data members; 01041 /// \li enumerators. 01042 VariableKind, 01043 01044 /// A C++ namespace. 01045 NamespaceKind, 01046 01047 /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration), 01048 /// see \c TypedefNameDecl. 01049 TypedefKind, 01050 01051 /// An enumeration or scoped enumeration. 01052 EnumKind 01053 }; 01054 01055 /// What kind of template specialization \c CommentDecl is. 01056 enum TemplateDeclKind { 01057 NotTemplate, 01058 Template, 01059 TemplateSpecialization, 01060 TemplatePartialSpecialization 01061 }; 01062 01063 /// If false, only \c CommentDecl is valid. 01064 unsigned IsFilled : 1; 01065 01066 /// Simplified kind of \c CommentDecl, see \c DeclKind enum. 01067 unsigned Kind : 3; 01068 01069 /// Is \c CommentDecl a template declaration. 01070 unsigned TemplateKind : 2; 01071 01072 /// Is \c CommentDecl an ObjCMethodDecl. 01073 unsigned IsObjCMethod : 1; 01074 01075 /// Is \c CommentDecl a non-static member function of C++ class or 01076 /// instance method of ObjC class. 01077 /// Can be true only if \c IsFunctionDecl is true. 01078 unsigned IsInstanceMethod : 1; 01079 01080 /// Is \c CommentDecl a static member function of C++ class or 01081 /// class method of ObjC class. 01082 /// Can be true only if \c IsFunctionDecl is true. 01083 unsigned IsClassMethod : 1; 01084 01085 void fill(); 01086 01087 DeclKind getKind() const LLVM_READONLY { 01088 return static_cast<DeclKind>(Kind); 01089 } 01090 01091 TemplateDeclKind getTemplateKind() const LLVM_READONLY { 01092 return static_cast<TemplateDeclKind>(TemplateKind); 01093 } 01094 }; 01095 01096 /// A full comment attached to a declaration, contains block content. 01097 class FullComment : public Comment { 01098 ArrayRef<BlockContentComment *> Blocks; 01099 DeclInfo *ThisDeclInfo; 01100 01101 public: 01102 FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) : 01103 Comment(FullCommentKind, SourceLocation(), SourceLocation()), 01104 Blocks(Blocks), ThisDeclInfo(D) { 01105 if (Blocks.empty()) 01106 return; 01107 01108 setSourceRange(SourceRange(Blocks.front()->getLocStart(), 01109 Blocks.back()->getLocEnd())); 01110 setLocation(Blocks.front()->getLocStart()); 01111 } 01112 01113 static bool classof(const Comment *C) { 01114 return C->getCommentKind() == FullCommentKind; 01115 } 01116 01117 child_iterator child_begin() const { 01118 return reinterpret_cast<child_iterator>(Blocks.begin()); 01119 } 01120 01121 child_iterator child_end() const { 01122 return reinterpret_cast<child_iterator>(Blocks.end()); 01123 } 01124 01125 const Decl *getDecl() const LLVM_READONLY { 01126 return ThisDeclInfo->CommentDecl; 01127 } 01128 01129 const DeclInfo *getDeclInfo() const LLVM_READONLY { 01130 if (!ThisDeclInfo->IsFilled) 01131 ThisDeclInfo->fill(); 01132 return ThisDeclInfo; 01133 } 01134 01135 ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; } 01136 01137 }; 01138 } // end namespace comments 01139 } // end namespace clang 01140 01141 #endif 01142