Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -235,6 +235,10 @@ /// Otherwise puts them into the right-most column. bool AlignEscapedNewlinesLeft; + /// \brief If \c true, horizontally aligns arguments in the argument list of a + /// function declaration. + bool AlignFunctionDeclarationArguments; + /// \brief The number of columns to use for indentation. unsigned IndentWidth; @@ -395,6 +399,8 @@ bool operator==(const FormatStyle &R) const { return AccessModifierOffset == R.AccessModifierOffset && AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft && + AlignFunctionDeclarationArguments == + R.AlignFunctionDeclarationArguments && AlignTrailingComments == R.AlignTrailingComments && AllowAllParametersOfDeclarationOnNextLine == R.AllowAllParametersOfDeclarationOnNextLine && Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -301,6 +301,9 @@ } if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr && + !(!Style.AlignFunctionDeclarationArguments && Previous.is(tok::l_paren) && + Previous.getPreviousNonComment() && + Previous.getPreviousNonComment()->Type == TT_FunctionDeclarationName) && (Current.Type != TT_LineComment || Previous.BlockKind == BK_BracedInit)) State.Stack.back().Indent = State.Column + Spaces; if (State.Stack.back().AvoidBinPacking && startsNextParameter(Current, Style)) @@ -735,11 +738,20 @@ ParenState NewParenState = State.Stack.back(); NewParenState.ContainsLineBreak = false; - // Indent from 'LastSpace' unless this the fake parentheses encapsulating a - // builder type call after 'return'. If such a call is line-wrapped, we - // commonly just want to indent from the start of the line. - if (!Current.isTrailingComment() && - (!Previous || Previous->isNot(tok::kw_return) || *I > 0)) + // Indent from 'LastSpace' unless this is the fake parentheses encapsulating + // a builder type call after 'return' or, if function declaration alignment + // is disabled, a function declaration argument list. If such a call is + // line-wrapped, we commonly just want to indent from the start of the line. + bool PreviousIsBuilderReturn = + Previous && Previous->is(tok::kw_return) && *I == 0; + bool PreviousIsFunctionDeclParen = + Previous && Previous->is(tok::l_paren) && + Previous->getPreviousNonComment() && + Previous->getPreviousNonComment()->Type == TT_FunctionDeclarationName && + *I == prec::Comma; + if (!Current.isTrailingComment() && !PreviousIsBuilderReturn && + (Style.AlignFunctionDeclarationArguments || + !PreviousIsFunctionDeclParen)) 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 @@ -171,6 +171,8 @@ IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft); + IO.mapOptional("AlignFunctionDeclarationArguments", + Style.AlignFunctionDeclarationArguments); IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", Style.AllowAllParametersOfDeclarationOnNextLine); @@ -324,6 +326,7 @@ LLVMStyle.Language = FormatStyle::LK_Cpp; LLVMStyle.AccessModifierOffset = -2; LLVMStyle.AlignEscapedNewlinesLeft = false; + LLVMStyle.AlignFunctionDeclarationArguments = true; LLVMStyle.AlignTrailingComments = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; @@ -411,6 +414,7 @@ GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; if (Language == FormatStyle::LK_Java) { + GoogleStyle.AlignFunctionDeclarationArguments = false; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; GoogleStyle.ColumnLimit = 100; @@ -458,6 +462,7 @@ FormatStyle getWebKitStyle() { FormatStyle Style = getLLVMStyle(); Style.AccessModifierOffset = -4; + Style.AlignFunctionDeclarationArguments = false; Style.AlignTrailingComments = false; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -1452,8 +1452,10 @@ return 1; if (Right.is(Keywords.kw_implements)) return 2; - if (Left.is(tok::comma) && Left.NestingLevel == 0) + if (Left.is(tok::comma)) return 3; + if (Left.is(tok::l_paren) && InFunctionDecl) + return 1; } if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next && Index: unittests/Format/FormatTestJava.cpp =================================================================== --- unittests/Format/FormatTestJava.cpp +++ unittests/Format/FormatTestJava.cpp @@ -261,5 +261,16 @@ getStyleWithColumns(50)); } +TEST_F(FormatTestJava, MethodDeclarations) { + verifyFormat("void methodName(Object arg1,\n" + " Object arg2, Object arg3) {\n" + "}", + getStyleWithColumns(40)); + verifyFormat("void methodName(\n" + " Object arg1, Object arg2) {\n" + "}", + getStyleWithColumns(40)); +} + } // end namespace tooling } // end namespace clang