Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -349,6 +349,10 @@ /// not use this in config files, etc. Use at your own risk. bool ExperimentalAutoDetectBinPacking; + /// \brief If ``true``, clang-format adds missing namespace end comments and + /// fixes invalid existing ones. + bool FixNamespaceEndComments; + /// \brief A vector of macros that should be interpreted as foreach loops /// instead of as function calls. /// @@ -679,6 +683,7 @@ DisableFormat == R.DisableFormat && ExperimentalAutoDetectBinPacking == R.ExperimentalAutoDetectBinPacking && + FixNamespaceEndComments == R.FixNamespaceEndComments && ForEachMacros == R.ForEachMacros && IncludeCategories == R.IncludeCategories && IndentCaseLabels == R.IndentCaseLabels && Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -308,6 +308,7 @@ IO.mapOptional("DisableFormat", Style.DisableFormat); IO.mapOptional("ExperimentalAutoDetectBinPacking", Style.ExperimentalAutoDetectBinPacking); + IO.mapOptional("FixNamespaceEndComments", Style.FixNamespaceEndComments); IO.mapOptional("ForEachMacros", Style.ForEachMacros); IO.mapOptional("IncludeCategories", Style.IncludeCategories); IO.mapOptional("IncludeIsMainRegex", Style.IncludeIsMainRegex); @@ -529,6 +530,7 @@ LLVMStyle.Cpp11BracedListStyle = true; LLVMStyle.DerivePointerAlignment = false; LLVMStyle.ExperimentalAutoDetectBinPacking = false; + LLVMStyle.FixNamespaceEndComments = true; LLVMStyle.ForEachMacros.push_back("foreach"); LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); @@ -676,6 +678,7 @@ MozillaStyle.ConstructorInitializerIndentWidth = 2; MozillaStyle.ContinuationIndentWidth = 2; MozillaStyle.Cpp11BracedListStyle = false; + MozillaStyle.FixNamespaceEndComments = false; MozillaStyle.IndentCaseLabels = true; MozillaStyle.ObjCSpaceAfterProperty = true; MozillaStyle.ObjCSpaceBeforeProtocolList = false; @@ -696,6 +699,7 @@ Style.BreakConstructorInitializersBeforeComma = true; Style.Cpp11BracedListStyle = false; Style.ColumnLimit = 0; + Style.FixNamespaceEndComments = false; Style.IndentWidth = 4; Style.NamespaceIndentation = FormatStyle::NI_Inner; Style.ObjCBlockIndentWidth = 4; @@ -713,6 +717,7 @@ Style.BreakBeforeTernaryOperators = true; Style.Cpp11BracedListStyle = false; Style.ColumnLimit = 79; + Style.FixNamespaceEndComments = false; Style.SpaceBeforeParens = FormatStyle::SBPO_Always; Style.Standard = FormatStyle::LS_Cpp03; return Style; @@ -1829,6 +1834,22 @@ return tooling::Replacements(); auto Env = Environment::CreateVirtualEnvironment(Code, FileName, Ranges); + if (Style.Language == FormatStyle::LK_Cpp && + Style.FixNamespaceEndComments) { + NamespaceEndCommentsFixer CommentsFixer(*Env, Expanded); + tooling::Replacements CommentFixes = CommentsFixer.process(); + if (!CommentFixes.empty()) { + auto NewCode = applyAllReplacements(Code, CommentFixes); + if (NewCode) { + auto NewEnv = Environment::CreateVirtualEnvironment( + *NewCode, FileName, + tooling::calculateRangesAfterReplacements(CommentFixes, Ranges)); + Formatter Format(*NewEnv, Expanded, IncompleteFormat); + return CommentFixes.merge(Format.process()); + } + } + } + if (Style.Language == FormatStyle::LK_JavaScript && Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) { JavaScriptRequoter Requoter(*Env, Expanded); Index: lib/Index/CommentToXML.cpp =================================================================== --- lib/Index/CommentToXML.cpp +++ lib/Index/CommentToXML.cpp @@ -593,9 +593,11 @@ unsigned Length = Declaration.size(); bool IncompleteFormat = false; + format::FormatStyle Style = format::getLLVMStyle(); + Style.FixNamespaceEndComments = false; tooling::Replacements Replaces = - reformat(format::getLLVMStyle(), StringDecl, - tooling::Range(Offset, Length), "xmldecl.xd", &IncompleteFormat); + reformat(Style, StringDecl, tooling::Range(Offset, Length), "xmldecl.xd", + &IncompleteFormat); auto FormattedStringDecl = applyAllReplacements(StringDecl, Replaces); if (static_cast(FormattedStringDecl)) { Declaration = *FormattedStringDecl; Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -185,7 +185,7 @@ EXPECT_EQ("namespace N {\n" "\n" "int i;\n" - "}", + "} // namespace N", format("namespace N {\n" "\n" "int i;\n" @@ -270,12 +270,22 @@ "}")); // FIXME: This is slightly inconsistent. + FormatStyle LLVMWithNoNamespaceFix = getLLVMStyle(); + LLVMWithNoNamespaceFix.FixNamespaceEndComments = false; EXPECT_EQ("namespace {\n" "int i;\n" "}", format("namespace {\n" "int i;\n" "\n" + "}", LLVMWithNoNamespaceFix)); + EXPECT_EQ("namespace {\n" + "int i;\n" + "\n" + "} // namespace", + format("namespace {\n" + "int i;\n" + "\n" "}")); EXPECT_EQ("namespace {\n" "int i;\n" @@ -1197,33 +1207,43 @@ } TEST_F(FormatTest, FormatsNamespaces) { + FormatStyle LLVMWithNoNamespaceFix = getLLVMStyle(); + LLVMWithNoNamespaceFix.FixNamespaceEndComments = false; + verifyFormat("namespace some_namespace {\n" "class A {};\n" "void f() { f(); }\n" - "}"); + "}", + LLVMWithNoNamespaceFix); verifyFormat("namespace {\n" "class A {};\n" "void f() { f(); }\n" - "}"); + "}", + LLVMWithNoNamespaceFix); verifyFormat("inline namespace X {\n" "class A {};\n" "void f() { f(); }\n" - "}"); + "}", + LLVMWithNoNamespaceFix); verifyFormat("using namespace some_namespace;\n" "class A {};\n" - "void f() { f(); }"); + "void f() { f(); }", + LLVMWithNoNamespaceFix); // This code is more common than we thought; if we // layout this correctly the semicolon will go into // its own line, which is undesirable. - verifyFormat("namespace {};"); + verifyFormat("namespace {};", + LLVMWithNoNamespaceFix); verifyFormat("namespace {\n" "class A {};\n" - "};"); + "};", + LLVMWithNoNamespaceFix); verifyFormat("namespace {\n" "int SomeVariable = 0; // comment\n" - "} // namespace"); + "} // namespace", + LLVMWithNoNamespaceFix); EXPECT_EQ("#ifndef HEADER_GUARD\n" "#define HEADER_GUARD\n" "namespace my_namespace {\n" @@ -1235,14 +1255,16 @@ " namespace my_namespace {\n" "int i;\n" "} // my_namespace\n" - "#endif // HEADER_GUARD")); + "#endif // HEADER_GUARD", + LLVMWithNoNamespaceFix)); EXPECT_EQ("namespace A::B {\n" "class C {};\n" "}", format("namespace A::B {\n" "class C {};\n" - "}")); + "}", + LLVMWithNoNamespaceFix)); FormatStyle Style = getLLVMStyle(); Style.NamespaceIndentation = FormatStyle::NI_All; @@ -1250,14 +1272,14 @@ " int i;\n" " namespace in {\n" " int i;\n" - " } // namespace\n" - "} // namespace", + " } // namespace in\n" + "} // namespace out", format("namespace out {\n" "int i;\n" "namespace in {\n" "int i;\n" - "} // namespace\n" - "} // namespace", + "} // namespace in\n" + "} // namespace out", Style)); Style.NamespaceIndentation = FormatStyle::NI_Inner; @@ -1265,14 +1287,14 @@ "int i;\n" "namespace in {\n" " int i;\n" - "} // namespace\n" - "} // namespace", + "} // namespace in\n" + "} // namespace out", format("namespace out {\n" "int i;\n" "namespace in {\n" "int i;\n" - "} // namespace\n" - "} // namespace", + "} // namespace in\n" + "} // namespace out", Style)); } @@ -1776,11 +1798,11 @@ EXPECT_EQ("SOME_MACRO\n" "namespace {\n" "void f();\n" - "}", + "} // namespace", format("SOME_MACRO\n" " namespace {\n" "void f( );\n" - "}")); + "} // namespace")); // Only if the identifier contains at least 5 characters. EXPECT_EQ("HTTP f();", format("HTTP\nf();")); EXPECT_EQ("MACRO\nf();", format("MACRO\nf();")); @@ -5498,7 +5520,7 @@ verifyIncompleteFormat("namespace {\n" "class Foo { Foo (\n" "};\n" - "} // comment"); + "} // namespace"); } TEST_F(FormatTest, IncorrectCodeErrorDetection) { @@ -7853,6 +7875,7 @@ TEST_F(FormatTest, MozillaBraceBreaking) { FormatStyle MozillaBraceStyle = getLLVMStyle(); MozillaBraceStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; + MozillaBraceStyle.FixNamespaceEndComments = false; verifyFormat("namespace a {\n" "class A\n" "{\n" @@ -8269,6 +8292,7 @@ TEST_F(FormatTest, WebKitBraceBreaking) { FormatStyle WebKitBraceStyle = getLLVMStyle(); WebKitBraceStyle.BreakBeforeBraces = FormatStyle::BS_WebKit; + WebKitBraceStyle.FixNamespaceEndComments = false; verifyFormat("namespace a {\n" "class A {\n" " void f()\n"