diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -400,7 +400,9 @@ return true; if (Current.is(TT_SelectorName) && !Previous.is(tok::at) && State.Stack.back().ObjCSelectorNameFound && - State.Stack.back().BreakBeforeParameter) + State.Stack.back().BreakBeforeParameter && + (Style.ObjCBreakBeforeNestedBlockParam || + !Current.startsSequence(TT_SelectorName, tok::colon, tok::caret))) return true; unsigned NewLineColumn = getNewLineColumn(State); diff --git a/clang/unittests/Format/FormatTestObjC.cpp b/clang/unittests/Format/FormatTestObjC.cpp --- a/clang/unittests/Format/FormatTestObjC.cpp +++ b/clang/unittests/Format/FormatTestObjC.cpp @@ -18,6 +18,7 @@ #define DEBUG_TYPE "format-test" using clang::tooling::ReplacementTest; +using testing::internal::ScopedTrace; namespace clang { namespace format { @@ -51,18 +52,24 @@ return *Result; } - void verifyFormat(StringRef Code) { + void _verifyFormat(const char *File, int Line, StringRef Code) { + ScopedTrace t(File, Line, ::testing::Message() << Code.str()); EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable"; EXPECT_EQ(Code.str(), format(test::messUp(Code))); } - void verifyIncompleteFormat(StringRef Code) { + void _verifyIncompleteFormat(const char *File, int Line, StringRef Code) { + ScopedTrace t(File, Line, ::testing::Message() << Code.str()); EXPECT_EQ(Code.str(), format(test::messUp(Code), SC_ExpectIncomplete)); } FormatStyle Style; }; +#define verifyIncompleteFormat(...) \ + _verifyIncompleteFormat(__FILE__, __LINE__, __VA_ARGS__) +#define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__) + TEST(FormatTestObjCStyle, DetectsObjCInHeaders) { auto Style = getStyle("LLVM", "a.h", "none", "@interface\n" @@ -1453,6 +1460,39 @@ " callback:^(typeof(self) self, NSNumber *u, NSNumber *v) {\n" " u = v;\n" " }]"); + + verifyFormat("[self block:^(void) {\n" + " doStuff();\n" + "} completionHandler:^(void) {\n" + " doStuff();\n" + " [self block:^(void) {\n" + " doStuff();\n" + " } completionHandler:^(void) {\n" + " doStuff();\n" + " }];\n" + "}];"); + + Style.ColumnLimit = 0; + verifyFormat("[[SessionService sharedService] " + "loadWindowWithCompletionBlock:^(SessionWindow *window) {\n" + " if (window) {\n" + " [self windowDidLoad:window];\n" + " } else {\n" + " [self errorLoadingWindow];\n" + " }\n" + "}];"); + verifyFormat("[controller test:^{\n" + " doStuff();\n" + "} withTimeout:5 completionHandler:^{\n" + " doStuff();\n" + "}];"); + verifyFormat( + "[self setupTextFieldSignals:@[\n" + " self.documentWidthField,\n" + " self.documentHeightField,\n" + "] solver:^(NSTextField *textField) {\n" + " return [self.representedObject solveEquationForTextField:textField];\n" + "}];"); } TEST_F(FormatTestObjC, IfNotUnlikely) {