clang-format: Use nested block special case for all languages.

Previously this was only used for JavaScript.

Before:
  functionCall({
                 int i;
                 int j;
               },
               aaaa, bbbb, cccc);

After:
  functionCall({
    int i;
    int j;
  }, aaaa, bbbb, cccc);

llvm-svn: 222531
This commit is contained in:
Daniel Jasper 2014-11-21 13:38:53 +00:00
parent 45bac8d4e8
commit 4b444495ed
5 changed files with 80 additions and 52 deletions

View File

@ -117,9 +117,8 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
// Don't create a 'hanging' indent if there are multiple blocks in a single
// statement.
if (Style.Language == FormatStyle::LK_JavaScript &&
Previous.is(tok::l_brace) && State.Stack.size() > 1 &&
State.Stack[State.Stack.size() - 2].JSFunctionInlined &&
if (Previous.is(tok::l_brace) && State.Stack.size() > 1 &&
State.Stack[State.Stack.size() - 2].NestedBlockInlined &&
State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks)
return false;
@ -453,11 +452,10 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
// Any break on this level means that the parent level has been broken
// and we need to avoid bin packing there.
bool JavaScriptFormat = Style.Language == FormatStyle::LK_JavaScript &&
Current.is(tok::r_brace) &&
State.Stack.size() > 1 &&
State.Stack[State.Stack.size() - 2].JSFunctionInlined;
if (!JavaScriptFormat) {
bool NestedBlockSpecialCase =
Current.is(tok::r_brace) && State.Stack.size() > 1 &&
State.Stack[State.Stack.size() - 2].NestedBlockInlined;
if (!NestedBlockSpecialCase) {
for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
State.Stack[i].BreakBeforeParameter = true;
}
@ -520,7 +518,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
: State.Stack.back().Indent;
if (Current.isOneOf(tok::r_brace, tok::r_square)) {
if (State.Stack.size() > 1 &&
State.Stack[State.Stack.size() - 2].JSFunctionInlined)
State.Stack[State.Stack.size() - 2].NestedBlockInlined)
return State.FirstIndent;
if (Current.closesBlockTypeList(Style) ||
(Current.MatchingParen &&
@ -666,22 +664,21 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
// foo();
// bar();
// }, a, b, c);
if (Style.Language == FormatStyle::LK_JavaScript) {
if (Current.isNot(tok::comment) && Previous && Previous->is(tok::l_brace) &&
State.Stack.size() > 1) {
if (State.Stack[State.Stack.size() - 2].JSFunctionInlined && Newline) {
for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
State.Stack[i].NoLineBreak = true;
}
if (Current.isNot(tok::comment) && Previous && Previous->is(tok::l_brace) &&
State.Stack.size() > 1) {
if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline) {
for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
State.Stack[i].NoLineBreak = true;
}
State.Stack[State.Stack.size() - 2].JSFunctionInlined = false;
}
if (Current.is(Keywords.kw_function))
State.Stack.back().JSFunctionInlined =
!Newline && Previous && Previous->Type != TT_DictLiteral &&
// If the unnamed function is the only parameter to another function,
// we can likely inline it and come up with a good format.
(Previous->isNot(tok::l_paren) || Previous->ParameterCount > 1);
State.Stack[State.Stack.size() - 2].NestedBlockInlined = false;
}
if (Previous && (Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) ||
Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr)) &&
!Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
State.Stack.back().NestedBlockInlined =
!Newline &&
(Previous->isNot(tok::l_paren) || Previous->ParameterCount > 1) && !Newline;
}
moveStatePastFakeLParens(State, Newline);

View File

@ -155,7 +155,7 @@ struct ParenState {
NestedNameSpecifierContinuation(0), CallContinuation(0), VariablePos(0),
ContainsLineBreak(false), ContainsUnwrappedBuilder(0),
AlignColons(true), ObjCSelectorNameFound(false),
HasMultipleNestedBlocks(false), JSFunctionInlined(false) {}
HasMultipleNestedBlocks(false), NestedBlockInlined(false) {}
/// \brief The position to which a specific parenthesis level needs to be
/// indented.
@ -256,9 +256,9 @@ struct ParenState {
/// the same token.
bool HasMultipleNestedBlocks;
// \brief The previous JavaScript 'function' keyword is not wrapped to a new
// line.
bool JSFunctionInlined;
// \brief The start of a nested block (e.g. lambda introducer in C++ or
// "function" in JavaScript) is not wrapped to a new line.
bool NestedBlockInlined;
bool operator<(const ParenState &Other) const {
if (Indent != Other.Indent)
@ -293,8 +293,8 @@ struct ParenState {
return ContainsLineBreak < Other.ContainsLineBreak;
if (ContainsUnwrappedBuilder != Other.ContainsUnwrappedBuilder)
return ContainsUnwrappedBuilder < Other.ContainsUnwrappedBuilder;
if (JSFunctionInlined != Other.JSFunctionInlined)
return JSFunctionInlined < Other.JSFunctionInlined;
if (NestedBlockInlined != Other.NestedBlockInlined)
return NestedBlockInlined < Other.NestedBlockInlined;
return false;
}
};

View File

@ -1285,7 +1285,7 @@ private:
int AdditionalIndent =
State.FirstIndent - State.Line->Level * Style.IndentWidth;
if (State.Stack.size() < 2 ||
!State.Stack[State.Stack.size() - 2].JSFunctionInlined) {
!State.Stack[State.Stack.size() - 2].NestedBlockInlined) {
AdditionalIndent = State.Stack.back().Indent -
Previous.Children[0]->Level * Style.IndentWidth;
}

View File

@ -2900,11 +2900,19 @@ TEST_F(FormatTest, LayoutBlockInsideParens) {
"});",
format(" functionCall ( {int i;int j;} );"));
EXPECT_EQ("functionCall({\n"
" int i;\n"
" int j;\n"
" },\n"
" aaaa, bbbb, cccc);",
" int i;\n"
" int j;\n"
"}, aaaa, bbbb, cccc);",
format(" functionCall ( {int i;int j;}, aaaa, bbbb, cccc);"));
EXPECT_EQ("functionCall(\n"
" {\n"
" int i;\n"
" int j;\n"
" },\n"
" aaaa, bbbb, // comment\n"
" cccc);",
format(" functionCall ( {int i;int j;}, aaaa, bbbb, // comment\n"
"cccc);"));
EXPECT_EQ("functionCall(aaaa, bbbb, { int i; });",
format(" functionCall (aaaa, bbbb, {int i;});"));
EXPECT_EQ("functionCall(aaaa, bbbb, {\n"
@ -2915,7 +2923,8 @@ TEST_F(FormatTest, LayoutBlockInsideParens) {
EXPECT_EQ("functionCall(aaaa, bbbb, { int i; });",
format(" functionCall (aaaa, bbbb, {int i;});"));
verifyFormat(
"Aaa({\n"
"Aaa(\n" // FIXME: There shouldn't be a linebreak here.
" {\n"
" int i; // break\n"
" },\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
@ -2997,10 +3006,9 @@ TEST_F(FormatTest, LayoutNestedBlocks) {
FormatStyle Style = getGoogleStyle();
Style.ColumnLimit = 45;
verifyFormat("Debug(aaaaa, {\n"
" if (aaaaaaaaaaaaaaaaaaaaaaaa)\n"
" return;\n"
" },\n"
" a);", Style);
" if (aaaaaaaaaaaaaaaaaaaaaaaa) return;\n"
"}, a);",
Style);
}
TEST_F(FormatTest, IndividualStatementsOfNestedBlocks) {
@ -7687,11 +7695,10 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
Tab);
verifyFormat("{\n"
"\tQ({\n"
"\t\t int a;\n"
"\t\t someFunction(aaaaaaaaaa,\n"
"\t\t bbbbbbbbb);\n"
"\t },\n"
"\t p);\n"
"\t\tint a;\n"
"\t\tsomeFunction(aaaaaaaa,\n"
"\t\t bbbbbbb);\n"
"\t}, p);\n"
"}",
Tab);
EXPECT_EQ("{\n"
@ -9278,14 +9285,15 @@ TEST_F(FormatTest, FormatsLambdas) {
"};");
// Multiple lambdas in the same parentheses change indentation rules.
verifyFormat("SomeFunction([]() {\n"
" int i = 42;\n"
" return i;\n"
" },\n"
" []() {\n"
" int j = 43;\n"
" return j;\n"
" });");
verifyFormat("SomeFunction(\n"
" []() {\n"
" int i = 42;\n"
" return i;\n"
" },\n"
" []() {\n"
" int j = 43;\n"
" return j;\n"
" });");
// More complex introducers.
verifyFormat("return [i, args...] {};");

View File

@ -319,6 +319,29 @@ TEST_F(FormatTestJava, NeverAlignAfterReturn) {
getStyleWithColumns(40));
}
TEST_F(FormatTestJava, FormatsInnerBlocks) {
verifyFormat("someObject.someFunction(new Runnable() {\n"
" @Override\n"
" public void run() {\n"
" System.out.println(42);\n"
" }\n"
"}, someOtherParameter);");
verifyFormat("someObject.someFunction(\n"
" new Runnable() {\n"
" @Override\n"
" public void run() {\n"
" System.out.println(42);\n"
" }\n"
" },\n"
" new Runnable() {\n"
" @Override\n"
" public void run() {\n"
" System.out.println(43);\n"
" }\n"
" },\n"
" someOtherParameter);");
}
TEST_F(FormatTestJava, FormatsLambdas) {
verifyFormat("(aaaaaaaaaa, bbbbbbbbbb) -> aaaaaaaaaa + bbbbbbbbbb;");
verifyFormat("(aaaaaaaaaa, bbbbbbbbbb)\n"