From: Manuel Klimek Date: Mon, 14 Jan 2013 16:41:43 +0000 (+0000) Subject: Fixes formatting of nested brace initializers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2c7739e3cbf1357c0ef8d894045a300331053565;p=clang Fixes formatting of nested brace initializers. We now format this correctly: Status::Rep Status::global_reps[3] = { { kGlobalRef, OK_CODE, NULL, NULL, NULL }, { kGlobalRef, CANCELLED_CODE, NULL, NULL, NULL }, { kGlobalRef, UNKNOWN_CODE, NULL, NULL, NULL } }; - fixed a bug where BreakBeforeClosingBrace would be set on the wrong state - added penalties for breaking between = and {, and between { and any other non-{ token git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172433 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index a221e4cce7..aa5d924986 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -449,10 +449,10 @@ private: (ParenLevel != 0 || getPrecedence(Previous) == prec::Assignment)) State.Stack[ParenLevel].LastSpace = State.Column; } - moveStateToNextToken(State); if (Newline && Previous.is(tok::l_brace)) { State.Stack.back().BreakBeforeClosingBrace = true; } + moveStateToNextToken(State); } /// \brief Mark the next token as consumed in \p State and modify its stacks @@ -503,6 +503,11 @@ private: const AnnotatedToken &Left = Tok; const AnnotatedToken &Right = Tok.Children[0]; + if (Left.is(tok::l_brace) && Right.isNot(tok::l_brace)) + return 50; + if (Left.is(tok::equal) && Right.is(tok::l_brace)) + return 150; + // In for-loops, prefer breaking at ',' and ';'. if (RootToken.is(tok::kw_for) && (Left.isNot(tok::comma) && Left.isNot(tok::semi))) @@ -561,7 +566,9 @@ private: if (!NewLine && State.NextToken->MustBreakBefore) return UINT_MAX; - if (NewLine && !State.NextToken->CanBreakBefore) + if (NewLine && !State.NextToken->CanBreakBefore && + !(State.NextToken->is(tok::r_brace) && + State.Stack.back().BreakBeforeClosingBrace)) return UINT_MAX; if (!NewLine && State.NextToken->is(tok::r_brace) && State.Stack.back().BreakBeforeClosingBrace) @@ -1249,17 +1256,21 @@ private: // change the "binding" behavior of a comment. return false; - if (Right.is(tok::r_paren) || Right.is(tok::l_brace) || + // We only break before r_brace if there was a corresponding break before + // the l_brace, which is tracked by BreakBeforeClosingBrace. + if (Right.is(tok::r_brace)) + return false; + + if (Right.is(tok::r_paren) || Right.is(tok::greater)) return false; return (isBinaryOperator(Left) && Left.isNot(tok::lessless)) || Left.is(tok::comma) || Right.is(tok::lessless) || Right.is(tok::arrow) || Right.is(tok::period) || Right.is(tok::colon) || Left.is(tok::semi) || - Left.is(tok::l_brace) || Left.is(tok::question) || - Right.is(tok::r_brace) || Left.Type == TT_ConditionalExpr || - (Left.is(tok::r_paren) && Left.Type != TT_CastRParen && - Right.is(tok::identifier)) || + Left.is(tok::l_brace) || Left.is(tok::question) || Left.Type == + TT_ConditionalExpr || (Left.is(tok::r_paren) && Left.Type != + TT_CastRParen && Right.is(tok::identifier)) || (Left.is(tok::l_paren) && !Right.is(tok::r_paren)); } diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 1ab4a53c40..f8a81b5982 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -459,6 +459,32 @@ TEST_F(FormatTest, StaticInitializers) { " looooooooooooooooooooooooooooooong };"); } +TEST_F(FormatTest, NestedStaticInitializers) { + verifyFormat("static A x = { { {} } };\n"); + verifyFormat( + "static A x = {\n" + " { { init1, init2, init3, init4 }, { init1, init2, init3, init4 } }\n" + "};\n"); + verifyFormat( + "somes Status::global_reps[3] = {\n" + " { kGlobalRef, OK_CODE, NULL, NULL, NULL },\n" + " { kGlobalRef, CANCELLED_CODE, NULL, NULL, NULL },\n" + " { kGlobalRef, UNKNOWN_CODE, NULL, NULL, NULL }\n" + "};"); + verifyFormat( + "CGRect cg_rect = { { rect.fLeft, rect.fTop },\n" + " { rect.fRight - rect.fLeft, rect.fBottom - rect.fTop" + " } };"); + + // FIXME: We might at some point want to handle this similar to parameters + // lists, where we have an option to put each on a single line. + verifyFormat("struct {\n" + " unsigned bit;\n" + " const char *const name;\n" + "} kBitsToOs[] = { { kOsMac, \"Mac\" }, { kOsWin, \"Windows\" },\n" + " { kOsLinux, \"Linux\" }, { kOsCrOS, \"Chrome OS\" } };"); +} + TEST_F(FormatTest, FormatsSmallMacroDefinitionsInSingleLine) { verifyFormat("#define ALooooooooooooooooooooooooooooooooooooooongMacro(" " \\\n"