1 //===--- RawCommentList.h - Classes for processing raw comments -*- 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 #ifndef LLVM_CLANG_AST_RAW_COMMENT_LIST_H 11 #define LLVM_CLANG_AST_RAW_COMMENT_LIST_H 12 13 #include "clang/Basic/SourceManager.h" 14 #include "llvm/ADT/ArrayRef.h" 15 16 namespace clang { 17 18 class ASTContext; 19 class ASTReader; 20 class Decl; 21 22 namespace comments { 23 class FullComment; 24 } // end namespace comments 25 26 class RawComment { 27 public: 28 enum CommentKind { 29 RCK_Invalid, ///< Invalid comment 30 RCK_OrdinaryBCPL, ///< Any normal BCPL comments 31 RCK_OrdinaryC, ///< Any normal C comment 32 RCK_BCPLSlash, ///< \code /// stuff \endcode 33 RCK_BCPLExcl, ///< \code //! stuff \endcode 34 RCK_JavaDoc, ///< \code /** stuff */ \endcode 35 RCK_Qt, ///< \code /*! stuff */ \endcode, also used by HeaderDoc 36 RCK_Merged ///< Two or more documentation comments merged together 37 }; 38 RawComment()39 RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { } 40 41 RawComment(const SourceManager &SourceMgr, SourceRange SR, 42 bool Merged = false); 43 getKind()44 CommentKind getKind() const LLVM_READONLY { 45 return (CommentKind) Kind; 46 } 47 isInvalid()48 bool isInvalid() const LLVM_READONLY { 49 return Kind == RCK_Invalid; 50 } 51 isMerged()52 bool isMerged() const LLVM_READONLY { 53 return Kind == RCK_Merged; 54 } 55 56 /// Is this comment attached to any declaration? isAttached()57 bool isAttached() const LLVM_READONLY { 58 return IsAttached; 59 } 60 setAttached()61 void setAttached() { 62 IsAttached = true; 63 } 64 65 /// Returns true if it is a comment that should be put after a member: 66 /// \code ///< stuff \endcode 67 /// \code //!< stuff \endcode 68 /// \code /**< stuff */ \endcode 69 /// \code /*!< stuff */ \endcode isTrailingComment()70 bool isTrailingComment() const LLVM_READONLY { 71 assert(isDocumentation()); 72 return IsTrailingComment; 73 } 74 75 /// Returns true if it is a probable typo: 76 /// \code //< stuff \endcode 77 /// \code /*< stuff */ \endcode isAlmostTrailingComment()78 bool isAlmostTrailingComment() const LLVM_READONLY { 79 return IsAlmostTrailingComment; 80 } 81 82 /// Returns true if this comment is not a documentation comment. isOrdinary()83 bool isOrdinary() const LLVM_READONLY { 84 return (Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC); 85 } 86 87 /// Returns true if this comment any kind of a documentation comment. isDocumentation()88 bool isDocumentation() const LLVM_READONLY { 89 return !isInvalid() && !isOrdinary(); 90 } 91 92 /// Returns raw comment text with comment markers. getRawText(const SourceManager & SourceMgr)93 StringRef getRawText(const SourceManager &SourceMgr) const { 94 if (RawTextValid) 95 return RawText; 96 97 RawText = getRawTextSlow(SourceMgr); 98 RawTextValid = true; 99 return RawText; 100 } 101 getSourceRange()102 SourceRange getSourceRange() const LLVM_READONLY { 103 return Range; 104 } 105 106 unsigned getBeginLine(const SourceManager &SM) const; 107 unsigned getEndLine(const SourceManager &SM) const; 108 getBriefText(const ASTContext & Context)109 const char *getBriefText(const ASTContext &Context) const { 110 if (BriefTextValid) 111 return BriefText; 112 113 return extractBriefText(Context); 114 } 115 116 /// Parse the comment, assuming it is attached to decl \c D. 117 comments::FullComment *parse(const ASTContext &Context, const Decl *D) const; 118 119 private: 120 SourceRange Range; 121 122 mutable StringRef RawText; 123 mutable const char *BriefText; 124 125 mutable bool RawTextValid : 1; ///< True if RawText is valid 126 mutable bool BriefTextValid : 1; ///< True if BriefText is valid 127 128 unsigned Kind : 3; 129 130 /// True if comment is attached to a declaration in ASTContext. 131 bool IsAttached : 1; 132 133 bool IsTrailingComment : 1; 134 bool IsAlmostTrailingComment : 1; 135 136 mutable bool BeginLineValid : 1; ///< True if BeginLine is valid 137 mutable bool EndLineValid : 1; ///< True if EndLine is valid 138 mutable unsigned BeginLine; ///< Cached line number 139 mutable unsigned EndLine; ///< Cached line number 140 141 /// \brief Constructor for AST deserialization. RawComment(SourceRange SR,CommentKind K,bool IsTrailingComment,bool IsAlmostTrailingComment)142 RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment, 143 bool IsAlmostTrailingComment) : 144 Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K), 145 IsAttached(false), IsTrailingComment(IsTrailingComment), 146 IsAlmostTrailingComment(IsAlmostTrailingComment), 147 BeginLineValid(false), EndLineValid(false) 148 { } 149 150 StringRef getRawTextSlow(const SourceManager &SourceMgr) const; 151 152 const char *extractBriefText(const ASTContext &Context) const; 153 154 friend class ASTReader; 155 }; 156 157 /// \brief Compare comments' source locations. 158 template<> 159 class BeforeThanCompare<RawComment> { 160 const SourceManager &SM; 161 162 public: BeforeThanCompare(const SourceManager & SM)163 explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { } 164 operator()165 bool operator()(const RawComment &LHS, const RawComment &RHS) { 166 return SM.isBeforeInTranslationUnit(LHS.getSourceRange().getBegin(), 167 RHS.getSourceRange().getBegin()); 168 } 169 operator()170 bool operator()(const RawComment *LHS, const RawComment *RHS) { 171 return operator()(*LHS, *RHS); 172 } 173 }; 174 175 /// \brief This class represents all comments included in the translation unit, 176 /// sorted in order of appearance in the translation unit. 177 class RawCommentList { 178 public: RawCommentList(SourceManager & SourceMgr)179 RawCommentList(SourceManager &SourceMgr) : 180 SourceMgr(SourceMgr), OnlyWhitespaceSeen(true) { } 181 182 void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator); 183 getComments()184 ArrayRef<RawComment *> getComments() const { 185 return Comments; 186 } 187 188 private: 189 SourceManager &SourceMgr; 190 std::vector<RawComment *> Comments; 191 SourceLocation PrevCommentEndLoc; 192 bool OnlyWhitespaceSeen; 193 addCommentsToFront(const std::vector<RawComment * > & C)194 void addCommentsToFront(const std::vector<RawComment *> &C) { 195 size_t OldSize = Comments.size(); 196 Comments.resize(C.size() + OldSize); 197 std::copy_backward(Comments.begin(), Comments.begin() + OldSize, 198 Comments.end()); 199 std::copy(C.begin(), C.end(), Comments.begin()); 200 } 201 202 friend class ASTReader; 203 }; 204 205 } // end namespace clang 206 207 #endif 208 209