if (RBraceTok->Finalized)
continue;
RBraceTok->Finalized = true;
+ const FormatToken *EndCommentPrevTok = RBraceTok;
+ // Namespaces often end with '};'. In that case, attach namespace end
+ // comments to the semicolon tokens.
+ if (RBraceTok->Next && RBraceTok->Next->is(tok::semi)) {
+ EndCommentPrevTok = RBraceTok->Next;
+ }
+ // The next token in the token stream after the place where the end comment
+ // token must be. This is either the next token on the current line or the
+ // first token on the next line.
+ const FormatToken *EndCommentNextTok = EndCommentPrevTok->Next;
+ if (EndCommentNextTok && EndCommentNextTok->is(tok::comment))
+ EndCommentNextTok = EndCommentNextTok->Next;
+ if (!EndCommentNextTok && I + 1 < E)
+ EndCommentNextTok = AnnotatedLines[I + 1]->First;
+ bool AddNewline = EndCommentNextTok &&
+ EndCommentNextTok->NewlinesBefore == 0 &&
+ EndCommentNextTok->isNot(tok::eof);
const std::string NamespaceName = computeName(NamespaceTok);
- bool AddNewline = (I + 1 < E) &&
- AnnotatedLines[I + 1]->First->NewlinesBefore == 0 &&
- AnnotatedLines[I + 1]->First->isNot(tok::eof);
const std::string EndCommentText =
computeEndCommentText(NamespaceName, AddNewline);
- if (!hasEndComment(RBraceTok)) {
+ if (!hasEndComment(EndCommentPrevTok)) {
bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1;
if (!isShort)
- addEndComment(RBraceTok, EndCommentText, SourceMgr, &Fixes);
+ addEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
continue;
}
- if (!validEndComment(RBraceTok, NamespaceName))
- updateEndComment(RBraceTok, EndCommentText, SourceMgr, &Fixes);
+ if (!validEndComment(EndCommentPrevTok, NamespaceName))
+ updateEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
}
return Fixes;
}
"}\n"
"}\n"
"}"));
+
+ // Adds an end comment after a semicolon.
+ EXPECT_EQ("namespace {\n"
+ " int i;\n"
+ " int j;\n"
+ "};// namespace",
+ fixNamespaceEndComments("namespace {\n"
+ " int i;\n"
+ " int j;\n"
+ "};"));
+ EXPECT_EQ("namespace A {\n"
+ " int i;\n"
+ " int j;\n"
+ "};// namespace A",
+ fixNamespaceEndComments("namespace A {\n"
+ " int i;\n"
+ " int j;\n"
+ "};"));
+ EXPECT_EQ("namespace A {\n"
+ " int i;\n"
+ " int j;\n"
+ "};// namespace A\n"
+ "// unrelated",
+ fixNamespaceEndComments("namespace A {\n"
+ " int i;\n"
+ " int j;\n"
+ "};\n"
+ "// unrelated"));
}
TEST_F(NamespaceEndCommentsFixerTest, AddsNewlineIfNeeded) {
" int j;\n"
" int k;\n"
"}"));
+ EXPECT_EQ("namespace {\n"
+ " int i;\n"
+ " int j;\n"
+ "};// namespace\n"
+ "int k;",
+ fixNamespaceEndComments("namespace {\n"
+ " int i;\n"
+ " int j;\n"
+ "};int k;"));
+ EXPECT_EQ("namespace {\n"
+ " int i;\n"
+ " int j;\n"
+ "};// namespace\n"
+ ";",
+ fixNamespaceEndComments("namespace {\n"
+ " int i;\n"
+ " int j;\n"
+ "};;"));
}
TEST_F(NamespaceEndCommentsFixerTest, DoesNotAddEndCommentForShortNamespace) {
EXPECT_EQ("namespace A {}", fixNamespaceEndComments("namespace A {}"));
EXPECT_EQ("namespace A { a }",
fixNamespaceEndComments("namespace A { a }"));
+ EXPECT_EQ("namespace A { a };",
+ fixNamespaceEndComments("namespace A { a };"));
}
TEST_F(NamespaceEndCommentsFixerTest, DoesNotAddCommentAfterUnaffectedRBrace) {
"}",
// The range (16, 3) spans the 'int' above.
/*Ranges=*/{1, tooling::Range(16, 3)}));
+ EXPECT_EQ("namespace A {\n"
+ " int i;\n"
+ "};",
+ fixNamespaceEndComments("namespace A {\n"
+ " int i;\n"
+ "};",
+ // The range (16, 3) spans the 'int' above.
+ /*Ranges=*/{1, tooling::Range(16, 3)}));
}
TEST_F(NamespaceEndCommentsFixerTest, DoesNotAddCommentAfterRBraceInPPDirective) {
fixNamespaceEndComments("namespace A::B {\n"
" int i;\n"
"} // end namespace A::B"));
+ EXPECT_EQ("namespace A {\n"
+ " int i;\n"
+ "}; // end namespace A",
+ fixNamespaceEndComments("namespace A {\n"
+ " int i;\n"
+ "}; // end namespace A"));
+ EXPECT_EQ("namespace {\n"
+ " int i;\n"
+ "}; /* unnamed namespace */",
+ fixNamespaceEndComments("namespace {\n"
+ " int i;\n"
+ "}; /* unnamed namespace */"));
}
TEST_F(NamespaceEndCommentsFixerTest, UpdatesInvalidEndLineComment) {
fixNamespaceEndComments("namespace A {\n"
" int i;\n"
"} // banamespace A"));
-
+ EXPECT_EQ("namespace A {\n"
+ " int i;\n"
+ "}; // namespace A",
+ fixNamespaceEndComments("namespace A {\n"
+ " int i;\n"
+ "}; // banamespace A"));
// Updates invalid line comments even for short namespaces.
EXPECT_EQ("namespace A {} // namespace A",
fixNamespaceEndComments("namespace A {} // namespace"));
+ EXPECT_EQ("namespace A {}; // namespace A",
+ fixNamespaceEndComments("namespace A {}; // namespace"));
}
TEST_F(NamespaceEndCommentsFixerTest, UpdatesInvalidEndBlockComment) {
fixNamespaceEndComments("namespace A {\n"
" int i;\n"
"} /* banamespace A */"));
+ EXPECT_EQ("namespace A {\n"
+ " int i;\n"
+ "}; // namespace A",
+ fixNamespaceEndComments("namespace A {\n"
+ " int i;\n"
+ "}; /* banamespace A */"));
EXPECT_EQ("namespace A {} // namespace A",
fixNamespaceEndComments("namespace A {} /**/"));
+ EXPECT_EQ("namespace A {}; // namespace A",
+ fixNamespaceEndComments("namespace A {}; /**/"));
}
TEST_F(NamespaceEndCommentsFixerTest,