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