18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/Support/Allocator.h"
22 using namespace clang;
26 std::pair<RawComment::CommentKind, bool> getCommentKind(StringRef Comment,
27 bool ParseAllComments) {
28 const size_t MinCommentLength = ParseAllComments ? 2 : 3;
29 if ((Comment.size() < MinCommentLength) || Comment[0] !=
'/')
33 if (Comment[1] ==
'/') {
34 if (Comment.size() < 3)
37 if (Comment[2] ==
'/')
39 else if (Comment[2] ==
'!')
44 assert(Comment.size() >= 4);
48 if (Comment[1] !=
'*' ||
49 Comment[Comment.size() - 2] !=
'*' ||
50 Comment[Comment.size() - 1] !=
'/')
53 if (Comment[2] ==
'*')
55 else if (Comment[2] ==
'!')
60 const bool TrailingComment = (Comment.size() > 3) && (Comment[3] ==
'<');
61 return std::make_pair(K, TrailingComment);
64 bool mergedCommentIsTrailingComment(StringRef Comment) {
65 return (Comment.size() > 3) && (Comment[3] ==
'<');
75 unsigned C1 =
SM.getPresumedColumnNumber(L1, &Invalid);
77 unsigned C2 =
SM.getPresumedColumnNumber(L2, &Invalid);
93 for (
unsigned I =
P; I != 0; --I) {
94 char C = Buffer[I - 1];
112 Range(SR), RawTextValid(
false), BriefTextValid(
false),
114 IsAlmostTrailingComment(
false) {
122 std::pair<CommentKind, bool> K =
128 unsigned BeginOffset;
129 std::tie(BeginFileID, BeginOffset) =
131 if (BeginOffset != 0) {
132 bool Invalid =
false;
142 IsTrailingComment |= K.second;
144 IsAlmostTrailingComment = RawText.startswith(
"//<") ||
145 RawText.startswith(
"/*<");
149 IsTrailingComment || mergedCommentIsTrailingComment(RawText);
153 StringRef RawComment::getRawTextSlow(
const SourceManager &SourceMgr)
const {
156 unsigned BeginOffset;
159 std::tie(BeginFileID, BeginOffset) =
163 const unsigned Length = EndOffset - BeginOffset;
168 assert(BeginFileID == EndFileID);
170 bool Invalid =
false;
171 const char *BufferStart = SourceMgr.
getBufferData(BeginFileID,
176 return StringRef(BufferStart + BeginOffset, Length);
179 const char *RawComment::extractBriefText(
const ASTContext &Context)
const {
186 llvm::BumpPtrAllocator Allocator;
191 RawText.begin(), RawText.end());
195 const unsigned BriefTextLength = Result.size();
196 char *BriefTextPtr =
new (Context)
char[BriefTextLength + 1];
197 memcpy(BriefTextPtr, Result.c_str(), BriefTextLength + 1);
198 BriefText = BriefTextPtr;
199 BriefTextValid =
true;
206 const Decl *D)
const {
213 RawText.begin(), RawText.end());
223 return P.parseFullComment();
228 unsigned MaxNewlinesAllowed) {
229 std::pair<FileID, unsigned> Loc1Info =
SM.getDecomposedLoc(Loc1);
230 std::pair<FileID, unsigned> Loc2Info =
SM.getDecomposedLoc(Loc2);
233 if (Loc1Info.first != Loc2Info.first)
236 bool Invalid =
false;
237 const char *Buffer =
SM.getBufferData(Loc1Info.first, &Invalid).data();
241 unsigned NumNewlines = 0;
242 assert(Loc1Info.second <= Loc2Info.second &&
"Loc1 after Loc2!");
244 for (
unsigned I = Loc1Info.second; I != Loc2Info.second; ++I) {
259 if (NumNewlines > MaxNewlinesAllowed)
263 if (I + 1 != Loc2Info.second &&
264 (Buffer[I + 1] ==
'\n' || Buffer[I + 1] ==
'\r') &&
265 Buffer[I] != Buffer[I + 1])
276 llvm::BumpPtrAllocator &Allocator) {
284 std::pair<FileID, unsigned> Loc =
287 const FileID CommentFile = Loc.first;
288 const unsigned CommentOffset = Loc.second;
292 if (OrderedComments[CommentFile].
empty()) {
293 OrderedComments[CommentFile][CommentOffset] =
298 const RawComment &C1 = *OrderedComments[CommentFile].rbegin()->second;
317 commentsStartOnSameColumn(SourceMgr, C1, C2))) &&
321 *OrderedComments[CommentFile].rbegin()->second =
322 RawComment(SourceMgr, MergedRange, CommentOpts,
true);
324 OrderedComments[CommentFile][CommentOffset] =
329 const std::map<unsigned, RawComment *> *
331 auto CommentsInFile = OrderedComments.find(
File);
332 if (CommentsInFile == OrderedComments.end())
335 return &CommentsInFile->second;
342 auto Cached = CommentBeginLine.find(C);
343 if (Cached != CommentBeginLine.end())
344 return Cached->second;
346 CommentBeginLine[C] =
Line;
351 auto Cached = CommentEndOffset.find(C);
352 if (Cached != CommentEndOffset.end())
353 return Cached->second;
356 CommentEndOffset[C] =
Offset;
362 llvm::StringRef CommentText =
getRawText(SourceMgr);
363 if (CommentText.empty())
369 Result +=
Line.Text +
"\n";
371 auto LastChar = Result.find_last_not_of(
'\n');
372 Result.erase(LastChar + 1, Result.size());
377 std::vector<RawComment::CommentLine>
380 llvm::StringRef CommentText =
getRawText(SourceMgr);
381 if (CommentText.empty())
384 llvm::BumpPtrAllocator Allocator;
390 CommentText.begin(), CommentText.end(),
393 std::vector<RawComment::CommentLine> Result;
398 unsigned IndentColumn = 0;
408 unsigned PreviousLine = 0;
413 auto LexLine = [&](
bool IsFirstLine) ->
bool {
422 if (Loc.
getLine() != PreviousLine) {
423 Result.emplace_back(
"", Loc, Loc);
429 llvm::StringRef TokText = L.
getSpelling(Tok, SourceMgr);
430 bool LocInvalid =
false;
433 assert(!LocInvalid &&
"getFormattedText for invalid location");
436 size_t WhitespaceLen = TokText.find_first_not_of(
" \t");
437 if (WhitespaceLen == StringRef::npos)
438 WhitespaceLen = TokText.size();
442 IndentColumn = TokColumn + WhitespaceLen;
452 std::max<int>(
static_cast<int>(IndentColumn) - TokColumn, 0));
453 llvm::StringRef Trimmed = TokText.drop_front(SkipLen);
464 if (
End.getLine() != PreviousLine) {
466 PreviousLine =
End.getLine();
482 while (LexLine(
false))