Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -414,6 +414,12 @@ /// type. bool IndentWrappedFunctionNames; + /// \brief If true, indent nested blocks to the start of the nested function call + bool IndentNestedBlocks; + + /// \brief If true, allow newlines before block parameters when ColumnLimit is 0. + bool AllowNewlineBeforeBlockParameter; + /// \brief If true, empty lines at the start of blocks are kept. bool KeepEmptyLinesAtTheStartOfBlocks; @@ -656,6 +662,8 @@ IndentCaseLabels == R.IndentCaseLabels && IndentWidth == R.IndentWidth && Language == R.Language && IndentWrappedFunctionNames == R.IndentWrappedFunctionNames && + IndentNestedBlocks == R.IndentNestedBlocks && + AllowNewlineBeforeBlockParameter == R.AllowNewlineBeforeBlockParameter && KeepEmptyLinesAtTheStartOfBlocks == R.KeepEmptyLinesAtTheStartOfBlocks && MacroBlockBegin == R.MacroBlockBegin && Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -179,7 +179,7 @@ Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0)) return true; if (Current.is(TT_SelectorName) && State.Stack.back().ObjCSelectorNameFound && - State.Stack.back().BreakBeforeParameter) + State.Stack.back().BreakBeforeParameter && Style.IndentNestedBlocks) return true; unsigned NewLineColumn = getNewLineColumn(State); @@ -234,6 +234,9 @@ State.Stack.back().FirstLessLess == 0) return true; + if (Current.is(TT_SelectorName) && State.Stack.back().ObjCSelectorNameFound && + State.Stack.back().BreakBeforeParameter && !Style.IndentNestedBlocks) + return true; if (Current.NestingLevel == 0 && !Current.isTrailingComment()) { // Always break after "template <...>" and leading annotations. This is only // for cases where the entire line does not fit on a single line as a @@ -546,7 +549,7 @@ Style.Language != FormatStyle::LK_Cpp && Current.is(tok::r_brace) && State.Stack.size() > 1 && State.Stack[State.Stack.size() - 2].NestedBlockInlined; - if (!NestedBlockSpecialCase) + if (!NestedBlockSpecialCase && Style.AllowNewlineBeforeBlockParameter) for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) State.Stack[i].BreakBeforeParameter = true; @@ -916,8 +919,13 @@ unsigned LastSpace = State.Stack.back().LastSpace; bool AvoidBinPacking; bool BreakBeforeParameter = false; - unsigned NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall, - State.Stack.back().NestedBlockIndent); + unsigned NestedBlockIndent; + if (Style.IndentNestedBlocks) { + NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall, + State.Stack.back().NestedBlockIndent); + } else { + NestedBlockIndent = State.Stack.back().NestedBlockIndent; + } if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) { if (Current.opensBlockOrBlockTypeList(Style)) { NewIndent = State.Stack.back().NestedBlockIndent + Style.IndentWidth; @@ -967,7 +975,7 @@ if (getLengthToMatchingParen(Current) + State.Column > getColumnLimit(State)) BreakBeforeParameter = true; - } else { + } else if (Style.AllowNewlineBeforeBlockParameter) { // For ColumnLimit = 0, we have to figure out whether there is or has to // be a line break within this call. for (const FormatToken *Tok = &Current; Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -304,6 +304,10 @@ IO.mapOptional("IndentWidth", Style.IndentWidth); IO.mapOptional("IndentWrappedFunctionNames", Style.IndentWrappedFunctionNames); + IO.mapOptional("IndentNestedBlocks", + Style.IndentNestedBlocks); + IO.mapOptional("AllowNewlineBeforeBlockParameter", + Style.AllowNewlineBeforeBlockParameter); IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks", Style.KeepEmptyLinesAtTheStartOfBlocks); IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin); @@ -519,6 +523,8 @@ {".*", 1}}; LLVMStyle.IndentCaseLabels = false; LLVMStyle.IndentWrappedFunctionNames = false; + LLVMStyle.IndentNestedBlocks = true; + LLVMStyle.AllowNewlineBeforeBlockParameter = true; LLVMStyle.IndentWidth = 2; LLVMStyle.TabWidth = 8; LLVMStyle.MaxEmptyLinesToKeep = 1; Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -7136,6 +7136,22 @@ " outRange8:(NSRange)out_range8\n" " outRange9:(NSRange)out_range9;"); + FormatStyle NoIndentStyle = getLLVMStyle(); + NoIndentStyle.IndentNestedBlocks = false; + verifyFormat("- (NSUInteger)indexOfObject:(id)anObject\n" + " inRange:(NSRange)range\n" + " outRange:(NSRange)out_range\n" + " outRange1:(NSRange)out_range1\n" + " outRange2:(NSRange)out_range2\n" + " outRange3:(NSRange)out_range3\n" + " outRange4:(NSRange)out_range4\n" + " outRange5:(NSRange)out_range5\n" + " outRange6:(NSRange)out_range6\n" + " outRange7:(NSRange)out_range7\n" + " outRange8:(NSRange)out_range8\n" + " outRange9:(NSRange)out_range9;", + NoIndentStyle); + // When the function name has to be wrapped. FormatStyle Style = getLLVMStyle(); Style.IndentWrappedFunctionNames = false; @@ -10849,6 +10865,20 @@ " [self onOperationDone];\n" "}];", FourIndent); + + FormatStyle NoNestedBlocks = getLLVMStyle(); + NoNestedBlocks.IndentNestedBlocks = false; + verifyFormat("[self block:^(void) {\n" + " doStuff();\n" + "} completionHandler:^(void) {\n" + " doStuff();\n" + " [self block:^(void) {\n" + " doStuff();\n" + " } completionHandler:^(void) {\n" + " doStuff();\n" + " }];\n" + "}];", + NoNestedBlocks); } TEST_F(FormatTest, FormatsBlocksWithZeroColumnWidth) { @@ -10916,6 +10946,24 @@ " int i;\n" "};", format("void (^largeBlock)(void) = ^{ int i; };", ZeroColumn)); + + FormatStyle DisallowNewline = getLLVMStyle(); + DisallowNewline.AllowNewlineBeforeBlockParameter = false; + DisallowNewline.ColumnLimit = 0; + verifyFormat("[[SessionService sharedService] loadWindowWithCompletionBlock:^(SessionWindow *window) {\n" + " if (window) {\n" + " [self windowDidLoad:window];\n" + " } else {\n" + " [self errorLoadingWindow];\n" + " }\n" + "}];", + DisallowNewline); + verifyFormat("[controller test:^{\n" + " doStuff();\n" + "} withTimeout:5 completionHandler:^{\n" + " doStuff();\n" + "}];", + DisallowNewline); } TEST_F(FormatTest, SupportsCRLF) {