diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1241,6 +1241,21 @@ +**AlwaysBreakBeforeFunctionParameters** (``Boolean``) :versionbadge:`clang-format 15.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). + + .. code-block:: c++ + + true: false: + int vs. int + add_two_numbers( add_two_numbers(int a, + int a, int b); + int b); + **AlwaysBreakBeforeMultilineStrings** (``Boolean``) :versionbadge:`clang-format 3.4` If ``true``, always break before multiline string literals. 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 @@ -749,6 +749,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 @@ -335,6 +335,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)) return true; if (CurrentState.BreakBeforeClosingBrace && @@ -983,7 +988,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 = Previous.is(TT_CtorInitializerColon) && Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon; @@ -995,7 +1002,9 @@ !State.Line->MustBeDeclaration) || (Style.PackConstructorInitializers != FormatStyle::PCIS_NextLine && PreviousIsBreakingCtorInitializerColon) || - Previous.is(TT_DictLiteral)) + Previous.is(TT_DictLiteral) || + (Style.AlwaysBreakBeforeFunctionParameters && + State.Line->MustBeDeclaration)) CurrentState.BreakBeforeParameter = true; // If we are breaking after a ':' to start a member initializer list, 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 @@ -685,6 +685,8 @@ IO.mapOptional("AlwaysBreakBeforeMultilineStrings", Style.AlwaysBreakBeforeMultilineStrings); + IO.mapOptional("AlwaysBreakBeforeFunctionParameters", + Style.AlwaysBreakBeforeFunctionParameters); IO.mapOptional("AlwaysBreakTemplateDeclarations", Style.AlwaysBreakTemplateDeclarations); IO.mapOptional("AttributeMacros", Style.AttributeMacros); @@ -1367,6 +1369,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}, @@ -1438,6 +1441,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; @@ -1449,6 +1453,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. 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 @@ -4042,6 +4042,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