Index: clang/lib/Format/FormatToken.h =================================================================== --- clang/lib/Format/FormatToken.h +++ clang/lib/Format/FormatToken.h @@ -102,7 +102,9 @@ TYPE(MacroBlockBegin) \ TYPE(MacroBlockEnd) \ TYPE(ModulePartitionColon) \ + TYPE(NamespaceLBrace) \ TYPE(NamespaceMacro) \ + TYPE(NamespaceRBrace) \ TYPE(NonNullAssertion) \ TYPE(NullCoalescingEqual) \ TYPE(NullCoalescingOperator) \ Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -805,6 +805,9 @@ return IfLBrace; } + if (FormatTok->is(tok::r_brace) && Tok->is(TT_NamespaceLBrace)) + FormatTok->setFinalizedType(TT_NamespaceRBrace); + const bool IsFunctionRBrace = FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace); @@ -2958,6 +2961,9 @@ } } if (FormatTok->is(tok::l_brace)) { + FormatToken *LBrace = FormatTok; + LBrace->setFinalizedType(TT_NamespaceLBrace); + if (ShouldBreakBeforeBrace(Style, InitialToken)) addUnwrappedLine(); Index: clang/lib/Format/WhitespaceManager.cpp =================================================================== --- clang/lib/Format/WhitespaceManager.cpp +++ clang/lib/Format/WhitespaceManager.cpp @@ -1081,11 +1081,10 @@ if (i + 1 != e && Changes[i + 1].ContinuesPPDirective) ChangeMaxColumn -= 2; - // If this comment follows an } in column 0, it probably documents the - // closing of a namespace and we don't want to align it. - bool FollowsRBraceInColumn0 = i > 0 && Changes[i].NewlinesBefore == 0 && - Changes[i - 1].Tok->is(tok::r_brace) && - Changes[i - 1].StartOfTokenColumn == 0; + + // We don't want to align namespace end comments. + bool DontAlignThisComment = i > 0 && Changes[i].NewlinesBefore == 0 && + Changes[i - 1].Tok->is(TT_NamespaceRBrace); bool WasAlignedWithStartOfNextLine = false; if (Changes[i].NewlinesBefore >= 1) { // A comment on its own line. unsigned CommentColumn = SourceMgr.getSpellingColumnNumber( @@ -1105,7 +1104,7 @@ } } if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Never || - FollowsRBraceInColumn0) { + DontAlignThisComment) { alignTrailingComments(StartOfSequence, i, MinColumn); MinColumn = ChangeMinColumn; MaxColumn = ChangeMinColumn; Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -20314,7 +20314,7 @@ " int x;\n" " };\n" " } // namespace b\n" - " } // namespace a", + " } // namespace a", WhitesmithsBraceStyle); verifyFormat("void f()\n" Index: clang/unittests/Format/FormatTestComments.cpp =================================================================== --- clang/unittests/Format/FormatTestComments.cpp +++ clang/unittests/Format/FormatTestComments.cpp @@ -3087,6 +3087,118 @@ Style)); } +TEST_F(FormatTestComments, DontAlignNamespaceComments) { + FormatStyle Style = getLLVMStyle(); + Style.NamespaceIndentation = FormatStyle::NI_All; + Style.NamespaceMacros.push_back("TESTSUITE"); + Style.ShortNamespaceLines = 0; + + StringRef Input = "namespace A {\n" + " TESTSUITE(B) {\n" + " namespace C {\n" + " namespace D {} // namespace D\n" + " std::string Foo = Bar; // Comment\n" + " std::string BazString = Baz; // C2\n" + " } // namespace C\n" + " }\n" + "} // NaMeSpAcE A"; + + EXPECT_TRUE(Style.FixNamespaceComments); + EXPECT_EQ(Style.AlignTrailingComments.Kind, FormatStyle::TCAS_Always); + verifyFormat("namespace A {\n" + " TESTSUITE(B) {\n" + " namespace C {\n" + " namespace D {} // namespace D\n" + " std::string Foo = Bar; // Comment\n" + " std::string BazString = Baz; // C2\n" + " } // namespace C\n" + " } // TESTSUITE(B)\n" + "} // NaMeSpAcE A", + Input, Style); + + Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; + verifyFormat("namespace A {\n" + " TESTSUITE(B) {\n" + " namespace C {\n" + " namespace D {} // namespace D\n" + " std::string Foo = Bar; // Comment\n" + " std::string BazString = Baz; // C2\n" + " } // namespace C\n" + " } // TESTSUITE(B)\n" + "} // NaMeSpAcE A", + Input, Style); + + Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Leave; + verifyFormat("namespace A {\n" + " TESTSUITE(B) {\n" + " namespace C {\n" + " namespace D {} // namespace D\n" + " std::string Foo = Bar; // Comment\n" + " std::string BazString = Baz; // C2\n" + " } // namespace C\n" + " } // TESTSUITE(B)\n" + "} // NaMeSpAcE A", + Input, Style); + + Style.FixNamespaceComments = false; + Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Always; + verifyFormat("namespace A {\n" + " TESTSUITE(B) {\n" + " namespace C {\n" + " namespace D {} // namespace D\n" + " std::string Foo = Bar; // Comment\n" + " std::string BazString = Baz; // C2\n" + " } // namespace C\n" + " }\n" + "} // NaMeSpAcE A", + Input, Style); + + Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; + verifyFormat("namespace A {\n" + " TESTSUITE(B) {\n" + " namespace C {\n" + " namespace D {} // namespace D\n" + " std::string Foo = Bar; // Comment\n" + " std::string BazString = Baz; // C2\n" + " } // namespace C\n" + " }\n" + "} // NaMeSpAcE A", + Input, Style); + + Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Leave; + verifyFormat("namespace A {\n" + " TESTSUITE(B) {\n" + " namespace C {\n" + " namespace D {} // namespace D\n" + " std::string Foo = Bar; // Comment\n" + " std::string BazString = Baz; // C2\n" + " } // namespace C\n" + " }\n" + "} // NaMeSpAcE A", + Input, Style); + + Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Always; + Style.FixNamespaceComments = true; + Input = "namespace A {\n" + " int Foo;\n" + " int Bar;\n" + "}\n" + "// Comment"; + +#if 0 + // FIXME: The following comment is aligned with the namespace comment. + verifyFormat("namespace A {\n" + " int Foo;\n" + " int Bar;\n" + "} // namespace A\n" + " // Comment", + Input, Style); +#endif + + Style.FixNamespaceComments = false; + verifyFormat(Input, Style); +} + TEST_F(FormatTestComments, AlignsBlockCommentDecorations) { EXPECT_EQ("/*\n" " */",