• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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