class foo
{};
- * ``bool AfterControlStatement`` Wrap control statements (``if``/``for``/``while``/``switch``/..).
+ * ``BraceWrappingAfterControlStatementStyle AfterControlStatement``
+ Wrap control statements (``if``/``for``/``while``/``switch``/..).
- .. code-block:: c++
+ Possible values:
- true:
- if (foo())
- {
- } else
- {}
- for (int i = 0; i < 10; ++i)
- {}
+ * ``BWACS_Never`` (in configuration: ``Never``)
+ Never wrap braces after a control statement.
- false:
- if (foo()) {
- } else {
- }
- for (int i = 0; i < 10; ++i) {
- }
+ .. code-block:: c++
+
+ if (foo()) {
+ } else {
+ }
+ for (int i = 0; i < 10; ++i) {
+ }
+
+ * ``BWACS_MultiLine`` (in configuration: ``MultiLine``)
+ Only wrap braces after a multi-line control statement.
+
+ .. code-block:: c++
+
+ if (foo && bar &&
+ baz)
+ {
+ quux();
+ }
+ while (foo || bar) {
+ }
+
+ * ``BWACS_Always`` (in configuration: ``Always``)
+ Always wrap braces after a control statement.
+
+ .. code-block:: c++
+
+ if (foo())
+ {
+ } else
+ {}
+ for (int i = 0; i < 10; ++i)
+ {}
* ``bool AfterEnum`` Wrap enum definitions.
/// The brace breaking style to use.
BraceBreakingStyle BreakBeforeBraces;
+ // Different ways to wrap braces after control statements.
+ enum BraceWrappingAfterControlStatementStyle {
+ /// Never wrap braces after a control statement.
+ /// \code
+ /// if (foo()) {
+ /// } else {
+ /// }
+ /// for (int i = 0; i < 10; ++i) {
+ /// }
+ /// \endcode
+ BWACS_Never,
+ /// Only wrap braces after a multi-line control statement.
+ /// \code
+ /// if (foo && bar &&
+ /// baz)
+ /// {
+ /// quux();
+ /// }
+ /// while (foo || bar) {
+ /// }
+ /// \endcode
+ BWACS_MultiLine,
+ /// Always wrap braces after a control statement.
+ /// \code
+ /// if (foo())
+ /// {
+ /// } else
+ /// {}
+ /// for (int i = 0; i < 10; ++i)
+ /// {}
+ /// \endcode
+ BWACS_Always
+ };
+
/// Precise control over the wrapping of braces.
/// \code
/// # Should be declared this way:
/// \endcode
bool AfterClass;
/// Wrap control statements (``if``/``for``/``while``/``switch``/..).
- /// \code
- /// true:
- /// if (foo())
- /// {
- /// } else
- /// {}
- /// for (int i = 0; i < 10; ++i)
- /// {}
- ///
- /// false:
- /// if (foo()) {
- /// } else {
- /// }
- /// for (int i = 0; i < 10; ++i) {
- /// }
- /// \endcode
- bool AfterControlStatement;
+ BraceWrappingAfterControlStatementStyle AfterControlStatement;
/// Wrap enum definitions.
/// \code
/// true:
}
};
+template <>
+struct ScalarEnumerationTraits<
+ FormatStyle::BraceWrappingAfterControlStatementStyle> {
+ static void
+ enumeration(IO &IO,
+ FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
+ IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
+ IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
+ IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
+ IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
+ IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
+ }
+};
+
template <>
struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
static void
if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
return Style;
FormatStyle Expanded = Style;
- Expanded.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, false,
- false, true, true, true};
+ Expanded.BraceWrapping = {false, false, FormatStyle::BWACS_Never,
+ false, false, false,
+ false, false, false,
+ false, false, false,
+ false, true, true,
+ true};
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
case FormatStyle::BS_Allman:
Expanded.BraceWrapping.AfterCaseLabel = true;
Expanded.BraceWrapping.AfterClass = true;
- Expanded.BraceWrapping.AfterControlStatement = true;
+ Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
Expanded.BraceWrapping.AfterEnum = true;
Expanded.BraceWrapping.AfterFunction = true;
Expanded.BraceWrapping.AfterNamespace = true;
case FormatStyle::BS_Whitesmiths:
Expanded.BraceWrapping.AfterCaseLabel = true;
Expanded.BraceWrapping.AfterClass = true;
- Expanded.BraceWrapping.AfterControlStatement = true;
+ Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
Expanded.BraceWrapping.AfterEnum = true;
Expanded.BraceWrapping.AfterFunction = true;
Expanded.BraceWrapping.AfterNamespace = true;
Expanded.BraceWrapping.BeforeElse = true;
break;
case FormatStyle::BS_GNU:
- Expanded.BraceWrapping = {true, true, true, true, true, true, true, true,
- true, true, true, true, true, true, true, true};
+ Expanded.BraceWrapping = {true, true, FormatStyle::BWACS_Always,
+ true, true, true,
+ true, true, true,
+ true, true, true,
+ true, true, true,
+ true};
break;
case FormatStyle::BS_WebKit:
Expanded.BraceWrapping.AfterFunction = true;
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
- LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, false,
- false, true, true, true};
+ LLVMStyle.BraceWrapping = {false, false, FormatStyle::BWACS_Never,
+ false, false, false,
+ false, false, false,
+ false, false, false,
+ false, true, true,
+ true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
Style.UseTab = FormatStyle::UT_Never;
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterClass = true;
- Style.BraceWrapping.AfterControlStatement = true;
+ Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
Style.BraceWrapping.AfterEnum = true;
Style.BraceWrapping.AfterFunction = true;
Style.BraceWrapping.AfterNamespace = true;
}
// Try to merge a control statement block with left brace wrapped
if (I[1]->First->is(tok::l_brace) &&
- TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
- return Style.BraceWrapping.AfterControlStatement
+ (TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
+ tok::kw_switch, tok::kw_try, tok::kw_do) ||
+ (TheLine->First->is(tok::r_brace) && TheLine->First->Next &&
+ TheLine->First->Next->isOneOf(tok::kw_else, tok::kw_catch))) &&
+ Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_MultiLine) {
+ // If possible, merge the next line's wrapped left brace with the current
+ // line. Otherwise, leave it on the next line, as this is a multi-line
+ // control statement.
+ return (Style.ColumnLimit == 0 ||
+ TheLine->Last->TotalLength <= Style.ColumnLimit)
+ ? 1
+ : 0;
+ } else if (I[1]->First->is(tok::l_brace) &&
+ TheLine->First->isOneOf(tok::kw_if, tok::kw_while,
+ tok::kw_for)) {
+ return (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always)
? tryMergeSimpleBlock(I, E, Limit)
: 0;
}
SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
if (Limit == 0)
return 0;
- if (Style.BraceWrapping.AfterControlStatement &&
+ if (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always &&
I[1]->First->is(tok::l_brace) &&
Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never)
return 0;
return 0;
if (!Style.AllowShortIfStatementsOnASingleLine &&
Line.startsWith(tok::kw_if) &&
- Style.BraceWrapping.AfterControlStatement && I + 2 != E &&
- !I[2]->First->is(tok::r_brace))
+ Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always &&
+ I + 2 != E && !I[2]->First->is(tok::r_brace))
return 0;
if (!Style.AllowShortLoopsOnASingleLine &&
Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) &&
return 0;
if (!Style.AllowShortLoopsOnASingleLine &&
Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) &&
- Style.BraceWrapping.AfterControlStatement && I + 2 != E &&
- !I[2]->First->is(tok::r_brace))
+ Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always &&
+ I + 2 != E && !I[2]->First->is(tok::r_brace))
return 0;
// FIXME: Consider an option to allow short exception handling clauses on
// a single line.
if (Tok->Next && Tok->Next->is(tok::kw_else))
return 0;
+ // Don't merge a trailing multi-line control statement block like:
+ // } else if (foo &&
+ // bar)
+ // { <-- current Line
+ // baz();
+ // }
+ if (Line.First == Line.Last &&
+ Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_MultiLine)
+ return 0;
+
return 2;
}
} else if (I[1]->First->is(tok::l_brace)) {
case tok::objc_autoreleasepool:
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
- if (Style.BraceWrapping.AfterControlStatement)
+ if (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always)
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false);
}
// Skip synchronization object
parseParens();
if (FormatTok->Tok.is(tok::l_brace)) {
- if (Style.BraceWrapping.AfterControlStatement)
+ if (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always)
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false);
}
Style.BraceWrapping.IndentBraces);
parseBlock(/*MustBeDeclaration=*/false);
if (FormatTok->Tok.is(tok::kw_break)) {
- if (Style.BraceWrapping.AfterControlStatement)
+ if (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always)
addUnwrappedLine();
parseStructuralElement();
}
AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_WithoutElse;
AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = true;
- AllowSimpleBracedStatements.BraceWrapping.AfterControlStatement = true;
+ AllowSimpleBracedStatements.BraceWrapping.AfterControlStatement =
+ FormatStyle::BWACS_Always;
verifyFormat("if (true) {}", AllowSimpleBracedStatements);
verifyFormat("if constexpr (true) {}", AllowSimpleBracedStatements);
Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterCaseLabel = true;
- Style.BraceWrapping.AfterControlStatement = true;
+ Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
EXPECT_EQ("switch (n)\n"
"{\n"
" case 0:\n"
Style.AllowShortCaseLabelsOnASingleLine = true;
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterCaseLabel = true;
- Style.BraceWrapping.AfterControlStatement = true;
+ Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
EXPECT_EQ("switch (n)\n"
"{\n"
" case 0:\n"
"}");
}
+TEST_F(FormatTest, MultiLineControlStatements) {
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakBeforeBraces = FormatStyle::BraceBreakingStyle::BS_Custom;
+ Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_MultiLine;
+ Style.ColumnLimit = 20;
+ // Short lines should keep opening brace on same line.
+ EXPECT_EQ("if (foo) {\n"
+ " bar();\n"
+ "}",
+ format("if(foo){bar();}", Style));
+ EXPECT_EQ("if (foo) {\n"
+ " bar();\n"
+ "} else {\n"
+ " baz();\n"
+ "}",
+ format("if(foo){bar();}else{baz();}", Style));
+ EXPECT_EQ("if (foo && bar) {\n"
+ " baz();\n"
+ "}",
+ format("if(foo&&bar){baz();}", Style));
+ EXPECT_EQ("if (foo) {\n"
+ " bar();\n"
+ "} else if (baz) {\n"
+ " quux();\n"
+ "}",
+ format("if(foo){bar();}else if(baz){quux();}", Style));
+ EXPECT_EQ(
+ "if (foo) {\n"
+ " bar();\n"
+ "} else if (baz) {\n"
+ " quux();\n"
+ "} else {\n"
+ " foobar();\n"
+ "}",
+ format("if(foo){bar();}else if(baz){quux();}else{foobar();}", Style));
+ EXPECT_EQ("for (;;) {\n"
+ " foo();\n"
+ "}",
+ format("for(;;){foo();}"));
+ EXPECT_EQ("while (1) {\n"
+ " foo();\n"
+ "}",
+ format("while(1){foo();}", Style));
+ EXPECT_EQ("switch (foo) {\n"
+ "case bar:\n"
+ " return;\n"
+ "}",
+ format("switch(foo){case bar:return;}", Style));
+ EXPECT_EQ("try {\n"
+ " foo();\n"
+ "} catch (...) {\n"
+ " bar();\n"
+ "}",
+ format("try{foo();}catch(...){bar();}", Style));
+ EXPECT_EQ("do {\n"
+ " foo();\n"
+ "} while (bar &&\n"
+ " baz);",
+ format("do{foo();}while(bar&&baz);", Style));
+ // Long lines should put opening brace on new line.
+ EXPECT_EQ("if (foo && bar &&\n"
+ " baz)\n"
+ "{\n"
+ " quux();\n"
+ "}",
+ format("if(foo&&bar&&baz){quux();}", Style));
+ EXPECT_EQ("if (foo && bar &&\n"
+ " baz)\n"
+ "{\n"
+ " quux();\n"
+ "}",
+ format("if (foo && bar &&\n"
+ " baz) {\n"
+ " quux();\n"
+ "}",
+ Style));
+ EXPECT_EQ("if (foo) {\n"
+ " bar();\n"
+ "} else if (baz ||\n"
+ " quux)\n"
+ "{\n"
+ " foobar();\n"
+ "}",
+ format("if(foo){bar();}else if(baz||quux){foobar();}", Style));
+ EXPECT_EQ(
+ "if (foo) {\n"
+ " bar();\n"
+ "} else if (baz ||\n"
+ " quux)\n"
+ "{\n"
+ " foobar();\n"
+ "} else {\n"
+ " barbaz();\n"
+ "}",
+ format("if(foo){bar();}else if(baz||quux){foobar();}else{barbaz();}",
+ Style));
+ EXPECT_EQ("for (int i = 0;\n"
+ " i < 10; ++i)\n"
+ "{\n"
+ " foo();\n"
+ "}",
+ format("for(int i=0;i<10;++i){foo();}", Style));
+ EXPECT_EQ("while (foo || bar ||\n"
+ " baz)\n"
+ "{\n"
+ " quux();\n"
+ "}",
+ format("while(foo||bar||baz){quux();}", Style));
+ EXPECT_EQ("switch (\n"
+ " foo = barbaz)\n"
+ "{\n"
+ "case quux:\n"
+ " return;\n"
+ "}",
+ format("switch(foo=barbaz){case quux:return;}", Style));
+ EXPECT_EQ("try {\n"
+ " foo();\n"
+ "} catch (\n"
+ " Exception &bar)\n"
+ "{\n"
+ " baz();\n"
+ "}",
+ format("try{foo();}catch(Exception&bar){baz();}", Style));
+}
+
//===----------------------------------------------------------------------===//
// Tests for classes, namespaces, etc.
//===----------------------------------------------------------------------===//
"};"));
FormatStyle Style = getLLVMStyle();
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
- Style.BraceWrapping.AfterControlStatement = true;
+ Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
Style.BraceWrapping.AfterFunction = true;
EXPECT_EQ("void f()\n"
"try\n"
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterCaseLabel);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass);
- CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterControlStatement);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterEnum);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterFunction);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterNamespace);
CHECK_PARSE("BreakBeforeBraces: Custom", BreakBeforeBraces,
FormatStyle::BS_Custom);
+ Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Never;
+ CHECK_PARSE("BraceWrapping:\n"
+ " AfterControlStatement: MultiLine",
+ BraceWrapping.AfterControlStatement,
+ FormatStyle::BWACS_MultiLine);
+ CHECK_PARSE("BraceWrapping:\n"
+ " AfterControlStatement: Always",
+ BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Always);
+ CHECK_PARSE("BraceWrapping:\n"
+ " AfterControlStatement: Never",
+ BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Never);
+ // For backward compatibility:
+ CHECK_PARSE("BraceWrapping:\n"
+ " AfterControlStatement: true",
+ BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Always);
+ CHECK_PARSE("BraceWrapping:\n"
+ " AfterControlStatement: false",
+ BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Never);
+
Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All;
CHECK_PARSE("AlwaysBreakAfterReturnType: None", AlwaysBreakAfterReturnType,
FormatStyle::RTBS_None);
" f();\n"
"}\n");
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
- Style.BraceWrapping.AfterControlStatement = true;
+ Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
verifyFormat("@autoreleasepool\n"
"{\n"
" f();\n"
" f();\n"
"}\n");
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
- Style.BraceWrapping.AfterControlStatement = true;
+ Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
verifyFormat("@synchronized(self)\n"
"{\n"
" f();\n"