Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -238,6 +238,19 @@ /// \endcode bool AlignAfterOpenBracket; + /// \brief Different ways to align after 'return'. + enum ReturnAlignStyle { + /// Never align after return. + RA_Never, + /// Align after return except for builder-style calls. + RA_ExceptBuilder, + /// Always align after return + RA_Always + }; + + /// \brief How to align expressions following 'return'. + ReturnAlignStyle AlignAfterReturn; + /// \brief If \c true, aligns trailing comments. bool AlignTrailingComments; @@ -405,6 +418,7 @@ bool operator==(const FormatStyle &R) const { return AccessModifierOffset == R.AccessModifierOffset && AlignAfterOpenBracket == R.AlignAfterOpenBracket && + AlignAfterReturn == R.AlignAfterReturn && AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft && AlignTrailingComments == R.AlignTrailingComments && AllowAllParametersOfDeclarationOnNextLine == Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -736,13 +736,19 @@ ParenState NewParenState = State.Stack.back(); NewParenState.ContainsLineBreak = false; - // Indent from 'LastSpace' unless these are fake parentheses encapsulating - // a builder type call after 'return' or, if the alignment after opening - // brackets is disabled. - if (!Current.isTrailingComment() && - (!Previous || Previous->isNot(tok::kw_return) || *I > 0) && - (Style.AlignAfterOpenBracket || *I != prec::Comma || - Current.NestingLevel == 0)) + // Indent from 'LastSpace' unless alignment after 'return' is disabled or + // alignment after opening brackets is disabled. + bool ShouldAlign = !Current.isTrailingComment(); + if (Previous && Previous->is(tok::kw_return)) { + if (Style.AlignAfterReturn == FormatStyle::RA_Never) + ShouldAlign = false; + if (Style.AlignAfterReturn == FormatStyle::RA_ExceptBuilder) + ShouldAlign &= *I > 0; + } + if (!Style.AlignAfterOpenBracket && *I == prec::Comma && + Current.NestingLevel > 0) + ShouldAlign = false; + if (ShouldAlign) NewParenState.Indent = std::max(std::max(State.Column, NewParenState.Indent), State.Stack.back().LastSpace); Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -57,6 +57,16 @@ } }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FormatStyle::ReturnAlignStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::RA_Never); + IO.enumCase(Value, "false", FormatStyle::RA_Never); + IO.enumCase(Value, "Always", FormatStyle::RA_Always); + IO.enumCase(Value, "true", FormatStyle::RA_Always); + IO.enumCase(Value, "ExceptBuilder", FormatStyle::RA_ExceptBuilder); + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) { IO.enumCase(Value, "Never", FormatStyle::UT_Never); @@ -171,6 +181,7 @@ IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket); + IO.mapOptional("AlignAfterReturn", Style.AlignAfterReturn); IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft); IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", @@ -326,6 +337,7 @@ LLVMStyle.AccessModifierOffset = -2; LLVMStyle.AlignEscapedNewlinesLeft = false; LLVMStyle.AlignAfterOpenBracket = true; + LLVMStyle.AlignAfterReturn = FormatStyle::RA_ExceptBuilder; LLVMStyle.AlignTrailingComments = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; @@ -414,6 +426,7 @@ if (Language == FormatStyle::LK_Java) { GoogleStyle.AlignAfterOpenBracket = false; + GoogleStyle.AlignAfterReturn = FormatStyle::RA_Never; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; GoogleStyle.ColumnLimit = 100; Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -7547,6 +7547,35 @@ getLLVMStyleWithColumns(8)); } +TEST_F(FormatTest, ConfigurableAlignmentAfterReturn) { + FormatStyle Style = getLLVMStyleWithColumns(40); + Style.AlignAfterReturn = FormatStyle::RA_Always; + verifyFormat("return SomeLongObject\n" + " .someVeryLongFunction()\n" + " .someLongFunction();", + Style); + + Style.AlignAfterReturn = FormatStyle::RA_ExceptBuilder; + verifyFormat("return SomeLongObject\n" + " .someVeryLongFunction()\n" + " .someLongFunction();", + Style); + verifyFormat("return SomeLongObject +\n" + " SomethingVeryLongVarName +\n" + " SomethingElse;", + Style); + + Style.AlignAfterReturn = FormatStyle::RA_Never; + verifyFormat("return SomeLongObject\n" + " .someVeryLongFunction()\n" + " .someLongFunction();", + Style); + verifyFormat("return SomeLongObject +\n" + " SomethingVeryLongVarName +\n" + " SomethingElse;", + Style); +} + TEST_F(FormatTest, ConfigurableUseOfTab) { FormatStyle Tab = getLLVMStyleWithColumns(42); Tab.IndentWidth = 8; @@ -8649,6 +8678,19 @@ CHECK_PARSE("BreakBeforeBinaryOperators: true", BreakBeforeBinaryOperators, FormatStyle::BOS_All); + Style.AlignAfterReturn = FormatStyle::RA_ExceptBuilder; + CHECK_PARSE("AlignAfterReturn: Never", AlignAfterReturn, + FormatStyle::RA_Never); + CHECK_PARSE("AlignAfterReturn: ExceptBuilder", AlignAfterReturn, + FormatStyle::RA_ExceptBuilder); + CHECK_PARSE("AlignAfterReturn: Always", AlignAfterReturn, + FormatStyle::RA_Always); + // For backward compatibility: + CHECK_PARSE("AlignAfterReturn: false", AlignAfterReturn, + FormatStyle::RA_Never); + CHECK_PARSE("AlignAfterReturn: true", AlignAfterReturn, + FormatStyle::RA_Always); + Style.UseTab = FormatStyle::UT_ForIndentation; CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never); CHECK_PARSE("UseTab: ForIndentation", UseTab, FormatStyle::UT_ForIndentation); Index: unittests/Format/FormatTestJava.cpp =================================================================== --- unittests/Format/FormatTestJava.cpp +++ unittests/Format/FormatTestJava.cpp @@ -281,5 +281,16 @@ verifyFormat("public void delete(Object o);"); } +TEST_F(FormatTestJava, NeverAlignReturns) { + verifyFormat("return aaaaaaaaaaaaaaaaaaa\n" + " && bbbbbbbbbbbbbbbbbbb\n" + " && ccccccccccccccccccc", + getStyleWithColumns(40)); + verifyFormat("return (result == null)\n" + " ? aaaaaaaaaaaaaaaaa\n" + " : bbbbbbbbbbbbbbbbb", + getStyleWithColumns(40)); +} + } // end namespace tooling } // end namespace clang