diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1368,6 +1368,24 @@ +.. _AlwaysBreakBeforeFunctionParameters: + +**AlwaysBreakBeforeFunctionParameters** (``Boolean``) :versionbadge:`clang-format 16.0` + If ``true``, always break before function parameters. + + This flag is meant to align function parameters starting on the line following + a function declaration or definition. Thus, it will only take effect if a function + declares a parameter (or multiple parameters). Example uses ``AlwaysBreakAfterReturnType`` + set to ``All``. + + .. code-block:: c++ + + true: false: + int vs. int + add_two_numbers( add_two_numbers(int a, + int a, int b); + int b); + .. _AlwaysBreakBeforeMultilineStrings: **AlwaysBreakBeforeMultilineStrings** (``Boolean``) :versionbadge:`clang-format 3.4` :ref:`ΒΆ ` diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -822,6 +822,14 @@ /// \version 3.4 bool AlwaysBreakBeforeMultilineStrings; + /// \brief Always break before function parameters in a declaration, e.g.: + /// \code + /// someFunction( + /// int argument1, + /// int argument2); + /// \endcode + bool AlwaysBreakBeforeFunctionParameters; + /// Different ways to break after the template declaration. enum BreakTemplateDeclarationsStyle : int8_t { /// Do not force break before declaration. 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 @@ -353,6 +353,11 @@ auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack); return LambdaBodyLength > getColumnLimit(State); } + // Check if we want to break before function parameters in declarations + if (startsNextParameter(Current, Style) && + Style.AlwaysBreakBeforeFunctionParameters && + State.Line->MustBeDeclaration) + return true; if (Current.MustBreakBefore || (Current.is(TT_InlineASMColon) && (Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always || @@ -1049,7 +1054,9 @@ // If we are breaking after '(', '{', '<', or this is the break after a ':' // to start a member initializater list in a constructor, this should not // be considered bin packing unless the relevant AllowAll option is false or - // this is a dict/object literal. + // this is a dict/object literal. Break if + // AlwaysBreakBeforeFunctionParameters is true and it's a function + // declaration. bool PreviousIsBreakingCtorInitializerColon = PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) && Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon; @@ -1064,7 +1071,9 @@ !State.Line->MustBeDeclaration) || (!AllowAllConstructorInitializersOnNextLine && PreviousIsBreakingCtorInitializerColon) || - Previous.is(TT_DictLiteral)) { + Previous.is(TT_DictLiteral) || + (Style.AlwaysBreakBeforeFunctionParameters && + State.Line->MustBeDeclaration)) { CurrentState.BreakBeforeParameter = true; } diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -870,6 +870,8 @@ Style.AlwaysBreakAfterReturnType); IO.mapOptional("AlwaysBreakBeforeMultilineStrings", Style.AlwaysBreakBeforeMultilineStrings); + IO.mapOptional("AlwaysBreakBeforeFunctionParameters", + Style.AlwaysBreakBeforeFunctionParameters); IO.mapOptional("AlwaysBreakTemplateDeclarations", Style.AlwaysBreakTemplateDeclarations); IO.mapOptional("AttributeMacros", Style.AttributeMacros); @@ -1504,6 +1506,7 @@ FormatStyle::SIS_WithoutElse; GoogleStyle.AllowShortLoopsOnASingleLine = true; GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; + GoogleStyle.AlwaysBreakBeforeFunctionParameters = false; GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; GoogleStyle.DerivePointerAlignment = true; GoogleStyle.IncludeStyle.IncludeCategories = {{"^", 2, 0, false}, @@ -1576,6 +1579,7 @@ GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; + GoogleStyle.AlwaysBreakBeforeFunctionParameters = false; GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; GoogleStyle.ColumnLimit = 100; GoogleStyle.SpaceAfterCStyleCast = true; @@ -1587,6 +1591,7 @@ // TODO: still under discussion whether to switch to SLS_All. GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; + GoogleStyle.AlwaysBreakBeforeFunctionParameters = false; GoogleStyle.BreakBeforeTernaryOperators = false; // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is // commonly followed by overlong URLs. @@ -1612,6 +1617,7 @@ GoogleStyle.BreakStringLiterals = false; } else if (Language == FormatStyle::LK_ObjC) { GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; + GoogleStyle.AlwaysBreakBeforeFunctionParameters = false; GoogleStyle.ColumnLimit = 100; // "Regroup" doesn't work well for ObjC yet (main header heuristic, // relationship between ObjC standard library headers and other heades, diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4724,6 +4724,18 @@ return true; } + // If AlwaysBreakBeforeFunctionParameters is true, we want to break before + // the next parameter, if there is one. + if (Left.is(tok::l_paren) && Style.AlwaysBreakBeforeFunctionParameters && + !Right.is(tok::r_paren)) { + if (Left.Previous) { + const FormatToken &TwoPrevious = *Left.Previous; + if (TwoPrevious.is(TT_FunctionDeclarationName)) { + return true; + } + } + } + // If the last token before a '}', ']', or ')' is a comma or a trailing // comment, the intention is to insert a line break after it in order to make // shuffling around entries easier. Import statements, especially in