Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -1151,6 +1151,30 @@ /// \endcode bool IndentWrappedFunctionNames; + /// \brief The style of indenting long function or method names wrapped + /// onto the next line. + enum IndentWrappedMethodStyle { + /// Automatically determine indenting style. + IWM_Auto, + /// Always indent wrapped methods names. + IWM_Always, + /// Never indent wrapped method names. + IWM_Never, + }; + + /// \brief Controls whether Objective-C method definition or + /// declaration is indented after wrapping onto the next line. + /// \code + /// Always (or Auto, if IndentWrappedFunctionNames is true): + /// - (LoooooooooooooooooooooooooooooooooooooooongReturnType) + /// loooooooooooooooooooooooooooooooongFunctionDeclaration; + /// + /// Never (or Auto, if IndentWrappedFunctionNames is false): + /// - (LoooooooooooooooooooooooooooooooooooooooongReturnType) + /// LoooooooooooooooooooooooooooooooongFunctionDeclaration; + /// \endcode + IndentWrappedMethodStyle IndentWrappedObjCMethodNames; + /// \brief Quotation styles for JavaScript strings. Does not affect template /// strings. enum JavaScriptQuoteStyle { @@ -1741,6 +1765,7 @@ IndentPPDirectives == R.IndentPPDirectives && IndentWidth == R.IndentWidth && Language == R.Language && IndentWrappedFunctionNames == R.IndentWrappedFunctionNames && + IndentWrappedObjCMethodNames == R.IndentWrappedObjCMethodNames && JavaScriptQuotes == R.JavaScriptQuotes && JavaScriptWrapImports == R.JavaScriptWrapImports && KeepEmptyLinesAtTheStartOfBlocks == Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -26,6 +26,19 @@ namespace clang { namespace format { +// Returns true if a TT_SelectorName should be indented when wrapped, +// false otherwise. +static bool shouldIndentWrappedSelectorName(const FormatStyle &Style) { + // TT_SelectorName is used across multiple languages; we only want + // Style.IndentWrappedObjCMethodNames to apply to ObjC. + if (Style.Language == FormatStyle::LK_ObjC) + return Style.IndentWrappedObjCMethodNames == FormatStyle::IWM_Always || + (Style.IndentWrappedObjCMethodNames == FormatStyle::IWM_Auto && + Style.IndentWrappedFunctionNames); + else + return Style.IndentWrappedFunctionNames; +} + // Returns the length of everything up to the first possible line break after // the ), ], } or > matching \c Tok. static unsigned getLengthToMatchingParen(const FormatToken &Tok) { @@ -698,7 +711,7 @@ State.Stack.back().AlignColons = false; } else { State.Stack.back().ColonPos = - (Style.IndentWrappedFunctionNames + (shouldIndentWrappedSelectorName(Style) ? std::max(State.Stack.back().Indent, State.FirstIndent + Style.ContinuationIndentWidth) : State.Stack.back().Indent) + @@ -897,7 +910,7 @@ if (NextNonComment->is(TT_SelectorName)) { if (!State.Stack.back().ObjCSelectorNameFound) { unsigned MinIndent = - (Style.IndentWrappedFunctionNames + (shouldIndentWrappedSelectorName(Style) ? std::max(State.Stack.back().Indent, State.FirstIndent + Style.ContinuationIndentWidth) : State.Stack.back().Indent); @@ -996,10 +1009,9 @@ !Current.NextOperator ? 0 : State.Column; if (Current.is(TT_SelectorName)) { State.Stack.back().ObjCSelectorNameFound = true; - if (Style.IndentWrappedFunctionNames) { + if (shouldIndentWrappedSelectorName(Style)) State.Stack.back().Indent = State.FirstIndent + Style.ContinuationIndentWidth; - } } if (Current.is(TT_CtorInitializerColon) && Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon) { Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -243,6 +243,16 @@ } }; +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, + FormatStyle::IndentWrappedMethodStyle &Value) { + IO.enumCase(Value, "Auto", FormatStyle::IWM_Auto); + IO.enumCase(Value, "Always", FormatStyle::IWM_Always); + IO.enumCase(Value, "Never", FormatStyle::IWM_Never); + } +}; + template <> struct MappingTraits { static void mapping(IO &IO, FormatStyle &Style) { // When reading, read the language first, we need it for getPredefinedStyle. @@ -378,6 +388,8 @@ IO.mapOptional("IndentWidth", Style.IndentWidth); IO.mapOptional("IndentWrappedFunctionNames", Style.IndentWrappedFunctionNames); + IO.mapOptional("IndentWrappedObjCMethodNames", + Style.IndentWrappedObjCMethodNames); IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes); IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports); IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks", @@ -645,6 +657,7 @@ LLVMStyle.IndentCaseLabels = false; LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; LLVMStyle.IndentWrappedFunctionNames = false; + LLVMStyle.IndentWrappedObjCMethodNames = FormatStyle::IWM_Auto; LLVMStyle.IndentWidth = 2; LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; LLVMStyle.JavaScriptWrapImports = true; Index: unittests/Format/FormatTestObjC.cpp =================================================================== --- unittests/Format/FormatTestObjC.cpp +++ unittests/Format/FormatTestObjC.cpp @@ -539,6 +539,36 @@ "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + Style.IndentWrappedObjCMethodNames = FormatStyle::IWM_Always; + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + + Style.IndentWrappedObjCMethodNames = FormatStyle::IWM_Never; + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + // Continuation indent width should win over aligning colons if the function // name is long. Style = getGoogleStyle(FormatStyle::LK_ObjC);