[PATCH] clang-format: "break before else" behavior

Jarkko Hietaniemi jhi at iki.fi
Fri May 9 05:20:49 PDT 2014


I wanted cuddled braces for 'if' and 'else' (just like the default style 
gives) *except* that I wanted my 'else' keywords themselves "uncuddled", 
that is, inserting a break before the 'else':

if (a) {
   a();
}
else {
   b();
}

This style makes the 'else' stand out better, instead of being hidden in

   } else {

while still giving the relatively tighter vertical packing of lines.

This looks to be part of the "Stroustrup" style.

However, I'm a little dubious about changing this because so far it 
hasn't been part of the Stroustrup behavior... that is, existing users 
of BS_Stroustrup will have their code look different when they re-format.

But http://www.stroustrup.com/Programming/PPP-style-rev3.pdf very 
clearly "uncuddles" the 'else', while the braces of both 'else' and 'if' 
are "cuddled", as a proper K&R descendant should.

In case changing the behavior of BS_Stroustrup is deemed too big a 
change, I'm also including an alternate version of the change which adds 
a new top-level option for this, AlwaysBreakBeforeElse.

Patches attached.


-------------- next part --------------
Index: tools/clang/include/clang/Format/Format.h
===================================================================
--- tools/clang/include/clang/Format/Format.h	(revision 208145)
+++ tools/clang/include/clang/Format/Format.h	(working copy)
@@ -240,7 +240,7 @@
     /// Like \c Attach, but break before braces on function, namespace and
     /// class definitions.
     BS_Linux,
-    /// Like \c Attach, but break before function definitions.
+    /// Like \c Attach, but break before function definitions, and 'else'.
     BS_Stroustrup,
     /// Always break before braces.
     BS_Allman,
Index: tools/clang/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- tools/clang/lib/Format/UnwrappedLineParser.cpp	(revision 208145)
+++ tools/clang/lib/Format/UnwrappedLineParser.cpp	(working copy)
@@ -1035,6 +1035,8 @@
     --Line->Level;
   }
   if (FormatTok->Tok.is(tok::kw_else)) {
+    if (Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup)
+      addUnwrappedLine();
     nextToken();
     if (FormatTok->Tok.is(tok::l_brace)) {
       CompoundStatementIndenter Indenter(this, Style, Line->Level);
Index: tools/clang/unittests/Format/FormatTest.cpp
===================================================================
--- tools/clang/unittests/Format/FormatTest.cpp	(revision 208145)
+++ tools/clang/unittests/Format/FormatTest.cpp	(working copy)
@@ -7377,6 +7377,17 @@
                "}",
                BreakBeforeBrace);
 
+  verifyFormat("void foo()\n"
+               "{\n"
+               "  if (a) {\n"
+               "    a();\n"
+               "  }\n"
+               "  else {\n"
+               "    b();\n"
+               "  }\n"
+               "}\n",
+               BreakBeforeBrace);
+
   verifyFormat("#ifdef _DEBUG\n"
                "int foo(int i = 0)\n"
                "#else\n"
-------------- next part --------------
Index: tools/clang/include/clang/Format/Format.h
===================================================================
--- tools/clang/include/clang/Format/Format.h	(revision 208145)
+++ tools/clang/include/clang/Format/Format.h	(working copy)
@@ -213,6 +213,9 @@
   /// \brief If \c true, always break before multiline string literals.
   bool AlwaysBreakBeforeMultilineStrings;
 
+  /// \brief If \c true, always break before 'else'.
+  bool AlwaysBreakBeforeElse;
+
   /// \brief Different ways to use tab in formatting.
   enum UseTabStyle {
     /// Never use tab.
@@ -349,6 +352,7 @@
            BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators &&
            BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators &&
            BreakBeforeBraces == R.BreakBeforeBraces &&
+           AlwaysBreakBeforeElse == R.AlwaysBreakBeforeElse &&
            BreakConstructorInitializersBeforeComma ==
                R.BreakConstructorInitializersBeforeComma &&
            ColumnLimit == R.ColumnLimit &&
Index: tools/clang/lib/Format/Format.cpp
===================================================================
--- tools/clang/lib/Format/Format.cpp	(revision 208145)
+++ tools/clang/lib/Format/Format.cpp	(working copy)
@@ -160,6 +160,7 @@
                    Style.AlwaysBreakTemplateDeclarations);
     IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
                    Style.AlwaysBreakBeforeMultilineStrings);
+    IO.mapOptional("AlwaysBreakBeforeElse", Style.AlwaysBreakBeforeElse);
     IO.mapOptional("BreakBeforeBinaryOperators",
                    Style.BreakBeforeBinaryOperators);
     IO.mapOptional("BreakBeforeTernaryOperators",
@@ -265,6 +266,7 @@
   LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
   LLVMStyle.AllowShortLoopsOnASingleLine = false;
   LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
+  LLVMStyle.AlwaysBreakBeforeElse = false;
   LLVMStyle.AlwaysBreakTemplateDeclarations = false;
   LLVMStyle.BinPackParameters = true;
   LLVMStyle.BreakBeforeBinaryOperators = false;
Index: tools/clang/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- tools/clang/lib/Format/UnwrappedLineParser.cpp	(revision 208145)
+++ tools/clang/lib/Format/UnwrappedLineParser.cpp	(working copy)
@@ -1035,6 +1035,8 @@
     --Line->Level;
   }
   if (FormatTok->Tok.is(tok::kw_else)) {
+    if (Style.AlwaysBreakBeforeElse)
+      addUnwrappedLine();
     nextToken();
     if (FormatTok->Tok.is(tok::l_brace)) {
       CompoundStatementIndenter Indenter(this, Style, Line->Level);
Index: tools/clang/unittests/Format/FormatTest.cpp
===================================================================
--- tools/clang/unittests/Format/FormatTest.cpp	(revision 208145)
+++ tools/clang/unittests/Format/FormatTest.cpp	(working copy)
@@ -8769,5 +8769,19 @@
                    "int i;\n"));
 }
 
+TEST_F(FormatTest, AlwaysBreakBeforeElse) {
+  FormatStyle BeforeElse = getLLVMStyle();
+  BeforeElse.AlwaysBreakBeforeElse = true;
+  verifyFormat("void foo() {\n"
+               "  if (a) {\n"
+               "    a();\n"
+               "  }\n"
+               "  else {\n"
+               "    b();\n"
+               "  }\n"
+               "}\n",
+               BeforeElse);
+}
+
 } // end namespace tooling
 } // end namespace clang


More information about the cfe-commits mailing list