cbeck88 created this revision. cbeck88 added a reviewer: djasper. cbeck88 added a subscriber: cfe-commits. cbeck88 set the repository for this revision to rL LLVM. Herald added a subscriber: klimek.
Rationale: I sometimes use a different clang tool, iwyu ("include what you use"), to clean up header file inclusions in my C++ projects. Iwyu seeks to correct the includes of a header or cpp unit so that definitions which are needed are included, and definitions which only need to be forward declared are forward declared. It often generates code like this at the top of your file: namespace foo { class bar; } namespace baz { struct quaz; } ... Unfortunately, clang-format dislikes braces which are arranged this way and always wants to break after them, and after the forward declaration, no matter what configuration options are used (as far as I can tell). I wrote this small patch so that short namespaces like these can be set on a single line regardless of chosen brace-style if a boolean option "AllowShortNamespacesOnASingleLine" is enabled. Repository: rL LLVM http://reviews.llvm.org/D11851 Files: include/clang/Format/Format.h lib/Format/Format.cpp lib/Format/UnwrappedLineFormatter.cpp unittests/Format/FormatTest.cpp
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 <T> struct bar; }", style); + verifyFormat("namespace foo { constexpr int num = 42; }", style); +} + } // end namespace } // end namespace format } // end namespace clang 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<AnnotatedLine *>::const_iterator I, + SmallVectorImpl<AnnotatedLine *>::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<AnnotatedLine *>::const_iterator I, SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) { 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: 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, <tt> namespace a { class b; } </tt> 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.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits