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