16 #include "llvm/Support/Debug.h" 17 #include "llvm/Support/Regex.h" 19 #define DEBUG_TYPE "namespace-end-comments-fixer" 27 static const int kShortNamespaceMaxLines = 1;
31 std::string computeName(
const FormatToken *NamespaceTok) {
32 assert(NamespaceTok &&
33 NamespaceTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&
34 "expecting a namespace token");
35 std::string
name =
"";
37 if (NamespaceTok->is(TT_NamespaceMacro)) {
40 assert(Tok && Tok->is(tok::l_paren) &&
"expected an opening parenthesis");
42 while (Tok && !Tok->isOneOf(tok::r_paren, tok::comma)) {
44 Tok = Tok->getNextNonComment();
51 const FormatToken *FirstNSTok =
Tok;
52 while (Tok && !Tok->is(tok::l_brace) && !Tok->is(tok::coloncolon)) {
58 while (Tok && !Tok->is(tok::l_brace)) {
60 if (Tok->is(tok::kw_inline))
62 Tok = Tok->getNextNonComment();
68 std::string computeEndCommentText(StringRef NamespaceName,
bool AddNewline,
69 const FormatToken *NamespaceTok) {
70 std::string
text =
"// ";
71 text += NamespaceTok->TokenText;
72 if (NamespaceTok->is(TT_NamespaceMacro))
74 else if (!NamespaceName.empty())
76 text += NamespaceName;
77 if (NamespaceTok->is(TT_NamespaceMacro))
84 bool hasEndComment(
const FormatToken *RBraceTok) {
85 return RBraceTok->Next && RBraceTok->Next->is(tok::comment);
88 bool validEndComment(
const FormatToken *RBraceTok, StringRef NamespaceName,
89 const FormatToken *NamespaceTok) {
90 assert(hasEndComment(RBraceTok));
91 const FormatToken *Comment = RBraceTok->Next;
95 static llvm::Regex *
const NamespaceCommentPattern =
96 new llvm::Regex(
"^/[/*] *(end (of )?)? *(anonymous|unnamed)? *" 97 "namespace( +([a-zA-Z0-9:_]+))?\\.? *(\\*/)?$",
98 llvm::Regex::IgnoreCase);
99 static llvm::Regex *
const NamespaceMacroCommentPattern =
100 new llvm::Regex(
"^/[/*] *(end (of )?)? *(anonymous|unnamed)? *" 101 "([a-zA-Z0-9_]+)\\(([a-zA-Z0-9:_]*)\\)\\.? *(\\*/)?$",
102 llvm::Regex::IgnoreCase);
104 SmallVector<StringRef, 8> Groups;
105 if (NamespaceTok->is(TT_NamespaceMacro) &&
106 NamespaceMacroCommentPattern->match(Comment->TokenText, &Groups)) {
107 StringRef NamespaceTokenText = Groups.size() > 4 ? Groups[4] :
"";
109 if (NamespaceTokenText != NamespaceTok->TokenText)
111 }
else if (NamespaceTok->isNot(tok::kw_namespace) ||
112 !NamespaceCommentPattern->match(Comment->TokenText, &Groups)) {
116 StringRef NamespaceNameInComment = Groups.size() > 5 ? Groups[5] :
"";
118 if (NamespaceName.empty() && !NamespaceNameInComment.empty())
120 StringRef AnonymousInComment = Groups.size() > 3 ? Groups[3] :
"";
122 if (!NamespaceName.empty() && !AnonymousInComment.empty())
124 return NamespaceNameInComment == NamespaceName;
127 void addEndComment(
const FormatToken *RBraceTok, StringRef EndCommentText,
128 const SourceManager &SourceMgr,
129 tooling::Replacements *Fixes) {
130 auto EndLoc = RBraceTok->Tok.getEndLoc();
132 auto Err = Fixes->add(tooling::Replacement(SourceMgr, Range, EndCommentText));
134 llvm::errs() <<
"Error while adding namespace end comment: " 139 void updateEndComment(
const FormatToken *RBraceTok, StringRef EndCommentText,
140 const SourceManager &SourceMgr,
141 tooling::Replacements *Fixes) {
142 assert(hasEndComment(RBraceTok));
143 const FormatToken *Comment = RBraceTok->Next;
145 Comment->Tok.getEndLoc());
146 auto Err = Fixes->add(tooling::Replacement(SourceMgr, Range, EndCommentText));
148 llvm::errs() <<
"Error while updating namespace end comment: " 162 assert(StartLineIndex < AnnotatedLines.size());
163 const FormatToken *NamespaceTok = AnnotatedLines[StartLineIndex]->First;
164 if (NamespaceTok->is(tok::l_brace)) {
167 if (StartLineIndex > 0)
168 NamespaceTok = AnnotatedLines[StartLineIndex - 1]->First;
170 return NamespaceTok->getNamespaceToken();
177 return NamespaceTok ? NamespaceTok->
TokenText : StringRef();
190 std::string AllNamespaceNames =
"";
192 StringRef NamespaceTokenText;
193 unsigned int CompactedNamespacesCount = 0;
194 for (
size_t I = 0, E = AnnotatedLines.size(); I != E; ++I) {
207 if (RBraceTok->
Next && RBraceTok->
Next->
is(tok::semi)) {
208 EndCommentPrevTok = RBraceTok->
Next;
212 std::string NamespaceName = computeName(NamespaceTok);
213 if (
Style.CompactNamespaces) {
214 if (CompactedNamespacesCount == 0)
215 NamespaceTokenText = NamespaceTok->
TokenText;
217 NamespaceTokenText ==
219 StartLineIndex - CompactedNamespacesCount - 1 ==
220 AnnotatedLines[I + 1]->MatchingOpeningBlockLineIndex &&
221 !AnnotatedLines[I + 1]->
First->Finalized) {
222 if (hasEndComment(EndCommentPrevTok)) {
224 updateEndComment(EndCommentPrevTok, std::string(), SourceMgr, &Fixes);
226 CompactedNamespacesCount++;
227 AllNamespaceNames =
"::" + NamespaceName + AllNamespaceNames;
230 NamespaceName += AllNamespaceNames;
231 CompactedNamespacesCount = 0;
232 AllNamespaceNames = std::string();
238 if (EndCommentNextTok && EndCommentNextTok->
is(tok::comment))
239 EndCommentNextTok = EndCommentNextTok->
Next;
240 if (!EndCommentNextTok && I + 1 < E)
241 EndCommentNextTok = AnnotatedLines[I + 1]->First;
242 bool AddNewline = EndCommentNextTok &&
245 const std::string EndCommentText =
246 computeEndCommentText(NamespaceName, AddNewline, NamespaceTok);
247 if (!hasEndComment(EndCommentPrevTok)) {
248 bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1;
250 addEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
251 }
else if (!validEndComment(EndCommentPrevTok, NamespaceName,
253 updateEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
const AnnotatedLine * Line
static CharSourceRange getCharRange(SourceRange R)
Dataflow Directional Tag Classes.
This class handles loading and caching of source files into memory.