1aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko//===--- RawCommentList.cpp - Processing raw comments -----------*- C++ -*-===// 2aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko// 3aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko// The LLVM Compiler Infrastructure 4aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko// 5aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko// This file is distributed under the University of Illinois Open Source 6aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko// License. See LICENSE.TXT for details. 7aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko// 8aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko//===----------------------------------------------------------------------===// 9aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 10f95d4125c01fa7b98722ae8cfbceac4a87d037b4Chandler Carruth#include "clang/AST/RawCommentList.h" 112d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko#include "clang/AST/ASTContext.h" 12f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko#include "clang/AST/Comment.h" 132d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko#include "clang/AST/CommentBriefParser.h" 14aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko#include "clang/AST/CommentCommandTraits.h" 1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/CommentLexer.h" 1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/CommentParser.h" 1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/CommentSema.h" 18aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko#include "llvm/ADT/STLExtras.h" 19aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 20aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenkousing namespace clang; 21aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 22aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenkonamespace { 23aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko/// Get comment kind and bool describing if it is a trailing comment. 24002f9281e010202b87cc120195b67df06ef3e17fDmitri Gribenkostd::pair<RawComment::CommentKind, bool> getCommentKind(StringRef Comment, 25002f9281e010202b87cc120195b67df06ef3e17fDmitri Gribenko bool ParseAllComments) { 26002f9281e010202b87cc120195b67df06ef3e17fDmitri Gribenko const size_t MinCommentLength = ParseAllComments ? 2 : 3; 27002f9281e010202b87cc120195b67df06ef3e17fDmitri Gribenko if ((Comment.size() < MinCommentLength) || Comment[0] != '/') 28c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara return std::make_pair(RawComment::RCK_Invalid, false); 29aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 30aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko RawComment::CommentKind K; 31aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (Comment[1] == '/') { 32aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (Comment.size() < 3) 33c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara return std::make_pair(RawComment::RCK_OrdinaryBCPL, false); 34aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 35aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (Comment[2] == '/') 36c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara K = RawComment::RCK_BCPLSlash; 37aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko else if (Comment[2] == '!') 38c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara K = RawComment::RCK_BCPLExcl; 39aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko else 40c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara return std::make_pair(RawComment::RCK_OrdinaryBCPL, false); 41aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko } else { 42aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko assert(Comment.size() >= 4); 43aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 44aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // Comment lexer does not understand escapes in comment markers, so pretend 45aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // that this is not a comment. 46aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (Comment[1] != '*' || 47aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko Comment[Comment.size() - 2] != '*' || 48aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko Comment[Comment.size() - 1] != '/') 49c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara return std::make_pair(RawComment::RCK_Invalid, false); 50aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 51aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (Comment[2] == '*') 52c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara K = RawComment::RCK_JavaDoc; 53aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko else if (Comment[2] == '!') 54c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara K = RawComment::RCK_Qt; 55aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko else 56c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara return std::make_pair(RawComment::RCK_OrdinaryC, false); 57aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko } 58aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko const bool TrailingComment = (Comment.size() > 3) && (Comment[3] == '<'); 59aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return std::make_pair(K, TrailingComment); 60aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} 61aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 62aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenkobool mergedCommentIsTrailingComment(StringRef Comment) { 63aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return (Comment.size() > 3) && (Comment[3] == '<'); 64aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} 65aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} // unnamed namespace 66aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 67aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri GribenkoRawComment::RawComment(const SourceManager &SourceMgr, SourceRange SR, 686fd7d3067dd06584ef3940e88e31fea1a0e83588Dmitri Gribenko bool Merged, bool ParseAllComments) : 691e15e3b78c396c829789e616b313e656814f5947Dmitri Gribenko Range(SR), RawTextValid(false), BriefTextValid(false), 70c41ace950dcf2254c9aa48e73647b89c35109f80Dmitri Gribenko IsAttached(false), IsAlmostTrailingComment(false), 716fd7d3067dd06584ef3940e88e31fea1a0e83588Dmitri Gribenko ParseAllComments(ParseAllComments), 72aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko BeginLineValid(false), EndLineValid(false) { 73aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // Extract raw comment text, if possible. 749530a8bf275f91f95147e1fb205dc85bea1ae45cDmitri Gribenko if (SR.getBegin() == SR.getEnd() || getRawText(SourceMgr).empty()) { 75c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara Kind = RCK_Invalid; 76aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return; 77aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko } 78aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 79aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (!Merged) { 80aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // Guess comment kind. 81002f9281e010202b87cc120195b67df06ef3e17fDmitri Gribenko std::pair<CommentKind, bool> K = getCommentKind(RawText, ParseAllComments); 82aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko Kind = K.first; 83aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko IsTrailingComment = K.second; 84aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 85aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko IsAlmostTrailingComment = RawText.startswith("//<") || 86aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko RawText.startswith("/*<"); 87aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko } else { 88c50a0e3900f1b44503be48457508af372f4dd05aAbramo Bagnara Kind = RCK_Merged; 89aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko IsTrailingComment = mergedCommentIsTrailingComment(RawText); 90aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko } 91aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} 92aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 93aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenkounsigned RawComment::getBeginLine(const SourceManager &SM) const { 94aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (BeginLineValid) 95aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return BeginLine; 96aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 97aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Range.getBegin()); 98aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko BeginLine = SM.getLineNumber(LocInfo.first, LocInfo.second); 99aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko BeginLineValid = true; 100aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return BeginLine; 101aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} 102aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 103aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenkounsigned RawComment::getEndLine(const SourceManager &SM) const { 104aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (EndLineValid) 105aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return EndLine; 106aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 107aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Range.getEnd()); 108aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko EndLine = SM.getLineNumber(LocInfo.first, LocInfo.second); 109aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko EndLineValid = true; 110aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return EndLine; 111aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} 112aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 113aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri GribenkoStringRef RawComment::getRawTextSlow(const SourceManager &SourceMgr) const { 114aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko FileID BeginFileID; 115aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko FileID EndFileID; 116aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko unsigned BeginOffset; 117aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko unsigned EndOffset; 118aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 119aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko llvm::tie(BeginFileID, BeginOffset) = 120aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko SourceMgr.getDecomposedLoc(Range.getBegin()); 121aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko llvm::tie(EndFileID, EndOffset) = 122aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko SourceMgr.getDecomposedLoc(Range.getEnd()); 123aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 124aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko const unsigned Length = EndOffset - BeginOffset; 125aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (Length < 2) 126aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return StringRef(); 127aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 128aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // The comment can't begin in one file and end in another. 129aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko assert(BeginFileID == EndFileID); 130aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 131aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko bool Invalid = false; 132aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko const char *BufferStart = SourceMgr.getBufferData(BeginFileID, 133aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko &Invalid).data(); 134aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (Invalid) 135aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return StringRef(); 136aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 137aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return StringRef(BufferStart + BeginOffset, Length); 138aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} 139aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 140d99ef536b241071b6f4c01db6525dc03242ac30bDmitri Gribenkoconst char *RawComment::extractBriefText(const ASTContext &Context) const { 1412d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko // Make sure that RawText is valid. 1422d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko getRawText(Context.getSourceManager()); 1432d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko 144477a9f58c1b197f315befd03b42a8a0b3a2f0ff9Dmitri Gribenko // Since we will be copying the resulting text, all allocations made during 145477a9f58c1b197f315befd03b42a8a0b3a2f0ff9Dmitri Gribenko // parsing are garbage after resulting string is formed. Thus we can use 146477a9f58c1b197f315befd03b42a8a0b3a2f0ff9Dmitri Gribenko // a separate allocator for all temporary stuff. 147477a9f58c1b197f315befd03b42a8a0b3a2f0ff9Dmitri Gribenko llvm::BumpPtrAllocator Allocator; 148477a9f58c1b197f315befd03b42a8a0b3a2f0ff9Dmitri Gribenko 149ad6fd9f93ce0d328397e8d57ef7117ced24fc8e2Fariborz Jahanian comments::Lexer L(Allocator, Context.getDiagnostics(), 150ad6fd9f93ce0d328397e8d57ef7117ced24fc8e2Fariborz Jahanian Context.getCommentCommandTraits(), 151e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko Range.getBegin(), 1522d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko RawText.begin(), RawText.end()); 153e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko comments::BriefParser P(L, Context.getCommentCommandTraits()); 1542d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko 1552d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko const std::string Result = P.Parse(); 1562d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko const unsigned BriefTextLength = Result.size(); 1572d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko char *BriefTextPtr = new (Context) char[BriefTextLength + 1]; 1582d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko memcpy(BriefTextPtr, Result.c_str(), BriefTextLength + 1); 159d99ef536b241071b6f4c01db6525dc03242ac30bDmitri Gribenko BriefText = BriefTextPtr; 1602d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko BriefTextValid = true; 1612d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko 162d99ef536b241071b6f4c01db6525dc03242ac30bDmitri Gribenko return BriefTextPtr; 1632d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko} 1642d44d77fed3200e2eff289f55493317e90d3398cDmitri Gribenko 165c41ace950dcf2254c9aa48e73647b89c35109f80Dmitri Gribenkocomments::FullComment *RawComment::parse(const ASTContext &Context, 1661952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko const Preprocessor *PP, 167c41ace950dcf2254c9aa48e73647b89c35109f80Dmitri Gribenko const Decl *D) const { 168f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko // Make sure that RawText is valid. 169f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko getRawText(Context.getSourceManager()); 170f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko 171ad6fd9f93ce0d328397e8d57ef7117ced24fc8e2Fariborz Jahanian comments::Lexer L(Context.getAllocator(), Context.getDiagnostics(), 172ad6fd9f93ce0d328397e8d57ef7117ced24fc8e2Fariborz Jahanian Context.getCommentCommandTraits(), 173af503a6f218cbef8704609812668360b0cbd0b60Dmitri Gribenko getSourceRange().getBegin(), 174f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko RawText.begin(), RawText.end()); 175f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko comments::Sema S(Context.getAllocator(), Context.getSourceManager(), 176e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko Context.getDiagnostics(), 1771952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko Context.getCommentCommandTraits(), 1781952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko PP); 179c41ace950dcf2254c9aa48e73647b89c35109f80Dmitri Gribenko S.setDecl(D); 180f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko comments::Parser P(L, S, Context.getAllocator(), Context.getSourceManager(), 181e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko Context.getDiagnostics(), 182e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko Context.getCommentCommandTraits()); 183f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko 184c41ace950dcf2254c9aa48e73647b89c35109f80Dmitri Gribenko return P.parseFullComment(); 185f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko} 186f50555eedef33fd5a67d369aa0ae8a6f1d201543Dmitri Gribenko 187aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenkonamespace { 188aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenkobool containsOnlyWhitespace(StringRef Str) { 189aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return Str.find_first_not_of(" \t\f\v\r\n") == StringRef::npos; 190aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} 191aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 1924a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenkobool onlyWhitespaceBetween(SourceManager &SM, 1934a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko SourceLocation Loc1, SourceLocation Loc2) { 1944a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko std::pair<FileID, unsigned> Loc1Info = SM.getDecomposedLoc(Loc1); 1954a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko std::pair<FileID, unsigned> Loc2Info = SM.getDecomposedLoc(Loc2); 1964a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko 1974a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko // Question does not make sense if locations are in different files. 1984a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko if (Loc1Info.first != Loc2Info.first) 199aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return false; 200aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 201aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko bool Invalid = false; 2024a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko const char *Buffer = SM.getBufferData(Loc1Info.first, &Invalid).data(); 203aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (Invalid) 204aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return false; 205aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 2064a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko StringRef Text(Buffer + Loc1Info.second, Loc2Info.second - Loc1Info.second); 2074a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko return containsOnlyWhitespace(Text); 208aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} 209aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} // unnamed namespace 210aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 211811c820257746b1799b790b6adc7804f44154011Dmitri Gribenkovoid RawCommentList::addComment(const RawComment &RC, 212811c820257746b1799b790b6adc7804f44154011Dmitri Gribenko llvm::BumpPtrAllocator &Allocator) { 213aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (RC.isInvalid()) 214aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return; 215aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 216e601b237e495bb15a5e5df2e20c61fa01a6c4df0Dmitri Gribenko // Check if the comments are not in source order. 217e601b237e495bb15a5e5df2e20c61fa01a6c4df0Dmitri Gribenko while (!Comments.empty() && 218e601b237e495bb15a5e5df2e20c61fa01a6c4df0Dmitri Gribenko !SourceMgr.isBeforeInTranslationUnit( 219811c820257746b1799b790b6adc7804f44154011Dmitri Gribenko Comments.back()->getSourceRange().getBegin(), 220e601b237e495bb15a5e5df2e20c61fa01a6c4df0Dmitri Gribenko RC.getSourceRange().getBegin())) { 221e601b237e495bb15a5e5df2e20c61fa01a6c4df0Dmitri Gribenko // If they are, just pop a few last comments that don't fit. 222e601b237e495bb15a5e5df2e20c61fa01a6c4df0Dmitri Gribenko // This happens if an \#include directive contains comments. 223e601b237e495bb15a5e5df2e20c61fa01a6c4df0Dmitri Gribenko Comments.pop_back(); 224e601b237e495bb15a5e5df2e20c61fa01a6c4df0Dmitri Gribenko } 225aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 226aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (OnlyWhitespaceSeen) { 2274a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko if (!onlyWhitespaceBetween(SourceMgr, 2284a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko PrevCommentEndLoc, 2294a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko RC.getSourceRange().getBegin())) 230aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko OnlyWhitespaceSeen = false; 231aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko } 232aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 2334a66557c297e1e5a71a3da4ceca1969800e7de70Dmitri Gribenko PrevCommentEndLoc = RC.getSourceRange().getEnd(); 234aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 235aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // Ordinary comments are not interesting for us. 236aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (RC.isOrdinary()) 237aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return; 238aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 239aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // If this is the first Doxygen comment, save it (because there isn't 240aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // anything to merge it with). 241aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (Comments.empty()) { 242811c820257746b1799b790b6adc7804f44154011Dmitri Gribenko Comments.push_back(new (Allocator) RawComment(RC)); 243aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko OnlyWhitespaceSeen = true; 244aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko return; 245aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko } 246aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 247811c820257746b1799b790b6adc7804f44154011Dmitri Gribenko const RawComment &C1 = *Comments.back(); 248aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko const RawComment &C2 = RC; 249aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 250aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // Merge comments only if there is only whitespace between them. 251aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko // Can't merge trailing and non-trailing comments. 252c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko // Merge comments if they are on same or consecutive lines. 253c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko bool Merged = false; 254aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko if (OnlyWhitespaceSeen && 255c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko (C1.isTrailingComment() == C2.isTrailingComment())) { 256c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko unsigned C1EndLine = C1.getEndLine(SourceMgr); 257c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko unsigned C2BeginLine = C2.getBeginLine(SourceMgr); 258c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko if (C1EndLine + 1 == C2BeginLine || C1EndLine == C2BeginLine) { 259c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko SourceRange MergedRange(C1.getSourceRange().getBegin(), 260c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko C2.getSourceRange().getEnd()); 2616fd7d3067dd06584ef3940e88e31fea1a0e83588Dmitri Gribenko *Comments.back() = RawComment(SourceMgr, MergedRange, true, 2626fd7d3067dd06584ef3940e88e31fea1a0e83588Dmitri Gribenko RC.isParseAllComments()); 263c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko Merged = true; 264c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko } 265c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko } 266c88c6a490ee946d80e306efaf83ae41b8f002741Dmitri Gribenko if (!Merged) 267811c820257746b1799b790b6adc7804f44154011Dmitri Gribenko Comments.push_back(new (Allocator) RawComment(RC)); 268aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko 269aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko OnlyWhitespaceSeen = true; 270aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko} 271