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