Index: lib/Format/NamespaceEndCommentsFixer.cpp =================================================================== --- lib/Format/NamespaceEndCommentsFixer.cpp +++ lib/Format/NamespaceEndCommentsFixer.cpp @@ -139,20 +139,36 @@ 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; } Index: unittests/Format/NamespaceEndCommentsFixerTest.cpp =================================================================== --- unittests/Format/NamespaceEndCommentsFixerTest.cpp +++ unittests/Format/NamespaceEndCommentsFixerTest.cpp @@ -184,6 +184,34 @@ "}\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) { @@ -220,6 +248,24 @@ " 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) { @@ -227,6 +273,8 @@ 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) { @@ -238,6 +286,14 @@ "}", // 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) { @@ -276,6 +332,18 @@ 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) { @@ -309,10 +377,17 @@ 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) { @@ -346,8 +421,16 @@ 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,