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