Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -112,6 +112,10 @@ /// single line. bool AllowShortLoopsOnASingleLine; + /// \brief If \c true, namespace a { class b; } can be put + /// on a single line + bool AllowShortNamespacesOnASingleLine; + /// \brief Different ways to break after the function definition return type. enum DefinitionReturnTypeBreakingStyle { /// Break after return type automatically. Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -212,6 +212,8 @@ Style.AllowShortIfStatementsOnASingleLine); IO.mapOptional("AllowShortLoopsOnASingleLine", Style.AllowShortLoopsOnASingleLine); + IO.mapOptional("AllowShortNamespacesOnASingleLine", + Style.AllowShortNamespacesOnASingleLine); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); IO.mapOptional("AlwaysBreakBeforeMultilineStrings", @@ -354,6 +356,7 @@ LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; LLVMStyle.AllowShortIfStatementsOnASingleLine = false; LLVMStyle.AllowShortLoopsOnASingleLine = false; + LLVMStyle.AllowShortNamespacesOnASingleLine = false; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; LLVMStyle.AlwaysBreakTemplateDeclarations = false; Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -199,6 +199,12 @@ return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0; } if (TheLine->Last->is(tok::l_brace)) { + if (Style.AllowShortNamespacesOnASingleLine && + TheLine->First->is(tok::kw_namespace)) { + if (unsigned result = tryMergeNamespace(I, E, Limit)) { + return result; + } + } return Style.BreakBeforeBraces == FormatStyle::BS_Attach ? tryMergeSimpleBlock(I, E, Limit) : 0; @@ -258,6 +264,35 @@ return 1; } + unsigned tryMergeNamespace( + SmallVectorImpl::const_iterator I, + SmallVectorImpl::const_iterator E, unsigned Limit) { + if (Limit == 0) + return 0; + if (I[1]->InPPDirective != (*I)->InPPDirective || + (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) + return 0; + + Limit = limitConsideringMacros(I + 1, E, Limit); + + if (1 + I[1]->Last->TotalLength > Limit) + return 0; + + // An assumption of the function is that the first line begins with + // keyword namespace (i.e. I[0]->First->is(tok::kw_namespace)) + + // The line which is in the namespace should end with semicolon + if (I[1]->Last->isNot(tok::semi)) + return 0; + + // Last, check that the third line starts with a closing brace. + if (I[2]->First->isNot(tok::r_brace)) + return 0; + + // If so, merge all three lines. + return 2; + } + unsigned tryMergeSimpleControlStatement( SmallVectorImpl::const_iterator I, SmallVectorImpl::const_iterator E, unsigned Limit) { Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -10433,6 +10433,17 @@ verifyNoCrash("#define a\\\n /**/}"); } +TEST_F(FormatTest, ShortNamespacesOption) { + FormatStyle style = getLLVMStyle(); + style.AllowShortNamespacesOnASingleLine = true; + + verifyFormat("namespace foo { class bar; }", style); + verifyFormat("namespace foo {\nclass bar;\nclass baz;\n}", style); + verifyFormat("namespace foo {\nint f() { return 5; }\n}", style); + verifyFormat("namespace foo { template struct bar; }", style); + verifyFormat("namespace foo { constexpr int num = 42; }", style); +} + } // end namespace } // end namespace format } // end namespace clang