17 #include "llvm/Support/Debug.h" 18 #include "llvm/Support/Regex.h" 20 #define DEBUG_TYPE "namespace-end-comments-fixer" 28 static const int kShortNamespaceMaxLines = 1;
32 static llvm::Regex kNamespaceCommentPattern =
33 llvm::Regex(
"^/[/*] *(end (of )?)? *(anonymous|unnamed)? *" 34 "namespace( +([a-zA-Z0-9:_]+))?\\.? *(\\*/)?$",
35 llvm::Regex::IgnoreCase);
39 std::string computeName(
const FormatToken *NamespaceTok) {
40 assert(NamespaceTok && NamespaceTok->is(tok::kw_namespace) &&
41 "expecting a namespace token");
42 std::string name =
"";
45 while (Tok && !Tok->is(tok::l_brace)) {
47 Tok = Tok->getNextNonComment();
52 std::string computeEndCommentText(StringRef NamespaceName,
bool AddNewline) {
53 std::string
text =
"// namespace";
54 if (!NamespaceName.empty()) {
56 text += NamespaceName;
63 bool hasEndComment(
const FormatToken *RBraceTok) {
64 return RBraceTok->Next && RBraceTok->Next->is(tok::comment);
67 bool validEndComment(
const FormatToken *RBraceTok, StringRef NamespaceName) {
68 assert(hasEndComment(RBraceTok));
69 const FormatToken *Comment = RBraceTok->Next;
70 SmallVector<StringRef, 7> Groups;
71 if (kNamespaceCommentPattern.match(Comment->TokenText, &Groups)) {
72 StringRef NamespaceNameInComment = Groups.size() > 5 ? Groups[5] :
"";
74 if (NamespaceName.empty() && !NamespaceNameInComment.empty())
76 StringRef AnonymousInComment = Groups.size() > 3 ? Groups[3] :
"";
78 if (!NamespaceName.empty() && !AnonymousInComment.empty())
80 return NamespaceNameInComment == NamespaceName;
85 void addEndComment(
const FormatToken *RBraceTok, StringRef EndCommentText,
86 const SourceManager &SourceMgr,
87 tooling::Replacements *Fixes) {
88 auto EndLoc = RBraceTok->Tok.getEndLoc();
92 llvm::errs() <<
"Error while adding namespace end comment: " 97 void updateEndComment(
const FormatToken *RBraceTok, StringRef EndCommentText,
98 const SourceManager &SourceMgr,
99 tooling::Replacements *Fixes) {
100 assert(hasEndComment(RBraceTok));
101 const FormatToken *Comment = RBraceTok->Next;
103 Comment->Tok.getEndLoc());
106 llvm::errs() <<
"Error while updating namespace end comment: " 112 getNamespaceToken(
const AnnotatedLine *line,
113 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
114 if (!line->Affected || line->InPPDirective || !line->startsWith(tok::r_brace))
116 size_t StartLineIndex = line->MatchingOpeningBlockLineIndex;
119 assert(StartLineIndex < AnnotatedLines.size());
120 const FormatToken *NamespaceTok = AnnotatedLines[StartLineIndex]->First;
121 if (NamespaceTok->is(tok::l_brace)) {
124 if (StartLineIndex > 0)
125 NamespaceTok = AnnotatedLines[StartLineIndex - 1]->First;
128 if (NamespaceTok->is(tok::kw_inline))
129 NamespaceTok = NamespaceTok->getNextNonComment();
130 if (!NamespaceTok || NamespaceTok->isNot(tok::kw_namespace))
145 AnnotatedLines.end());
147 std::string AllNamespaceNames =
"";
149 unsigned int CompactedNamespacesCount = 0;
150 for (
size_t I = 0, E = AnnotatedLines.size(); I != E; ++I) {
153 getNamespaceToken(EndLine, AnnotatedLines);
163 if (RBraceTok->
Next && RBraceTok->
Next->
is(tok::semi)) {
164 EndCommentPrevTok = RBraceTok->
Next;
168 std::string NamespaceName = computeName(NamespaceTok);
171 getNamespaceToken(AnnotatedLines[I + 1], AnnotatedLines) &&
172 StartLineIndex - CompactedNamespacesCount - 1 ==
173 AnnotatedLines[I + 1]->MatchingOpeningBlockLineIndex &&
174 !AnnotatedLines[I + 1]->First->Finalized) {
175 if (hasEndComment(EndCommentPrevTok)) {
177 updateEndComment(EndCommentPrevTok, std::string(), SourceMgr, &Fixes);
179 CompactedNamespacesCount++;
180 AllNamespaceNames =
"::" + NamespaceName + AllNamespaceNames;
183 NamespaceName += AllNamespaceNames;
184 CompactedNamespacesCount = 0;
185 AllNamespaceNames = std::string();
191 if (EndCommentNextTok && EndCommentNextTok->
is(tok::comment))
192 EndCommentNextTok = EndCommentNextTok->
Next;
193 if (!EndCommentNextTok && I + 1 < E)
194 EndCommentNextTok = AnnotatedLines[I + 1]->First;
195 bool AddNewline = EndCommentNextTok &&
198 const std::string EndCommentText =
199 computeEndCommentText(NamespaceName, AddNewline);
200 if (!hasEndComment(EndCommentPrevTok)) {
201 bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1;
203 addEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
204 }
else if (!validEndComment(EndCommentPrevTok, NamespaceName)) {
205 updateEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
static CharSourceRange getCharRange(SourceRange R)
Dataflow Directional Tag Classes.
std::string toString(const til::SExpr *E)
This class handles loading and caching of source files into memory.