[clang-format] Add BreakFunctionDefinitionParameters option (#84988)

This adds an option to break function definition parameters, putting
them on the next line after the function's opening paren.

This was a missing step towards allowing styles which require all
function definition parameters be on their own lines.

Closes #62963
This commit is contained in:
Ameer J
2024-04-02 15:00:51 -04:00
committed by GitHub
parent a9af66a90e
commit 13be0d4a34
6 changed files with 81 additions and 0 deletions

View File

@@ -3295,6 +3295,21 @@ the configuration (without a prefix: ``Auto``).
.. _BreakFunctionDefinitionParameters:
**BreakFunctionDefinitionParameters** (``Boolean``) :versionbadge:`clang-format 19` :ref:`¶ <BreakFunctionDefinitionParameters>`
If ``true``, clang-format will always break before function definition
parameters.
.. code-block:: c++
true:
void functionDefinition(
int A, int B) {}
false:
void functionDefinition(int A, int B) {}
.. _BreakInheritanceList:
**BreakInheritanceList** (``BreakInheritanceListStyle``) :versionbadge:`clang-format 7` :ref:`¶ <BreakInheritanceList>`

View File

@@ -2223,6 +2223,20 @@ struct FormatStyle {
/// \version 5
BreakConstructorInitializersStyle BreakConstructorInitializers;
/// If ``true``, clang-format will always break before function definition
/// parameters.
/// \code
/// true:
/// void functionDefinition(
/// int A, int B) {}
///
/// false:
/// void functionDefinition(int A, int B) {}
///
/// \endcode
/// \version 19
bool BreakFunctionDefinitionParameters;
/// Break after each annotation on a field in Java files.
/// \code{.java}
/// true: false:
@@ -4938,6 +4952,8 @@ struct FormatStyle {
BreakBeforeInlineASMColon == R.BreakBeforeInlineASMColon &&
BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators &&
BreakConstructorInitializers == R.BreakConstructorInitializers &&
BreakFunctionDefinitionParameters ==
R.BreakFunctionDefinitionParameters &&
BreakInheritanceList == R.BreakInheritanceList &&
BreakStringLiterals == R.BreakStringLiterals &&
BreakTemplateDeclarations == R.BreakTemplateDeclarations &&

View File

@@ -955,6 +955,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.BreakBeforeTernaryOperators);
IO.mapOptional("BreakConstructorInitializers",
Style.BreakConstructorInitializers);
IO.mapOptional("BreakFunctionDefinitionParameters",
Style.BreakFunctionDefinitionParameters);
IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
IO.mapOptional("BreakTemplateDeclarations",
@@ -1465,6 +1467,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakFunctionDefinitionParameters = false;
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
LLVMStyle.BreakStringLiterals = true;
LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;

View File

@@ -574,6 +574,9 @@ public:
/// Is optional and can be removed.
bool Optional = false;
/// Might be function declaration open/closing paren.
bool MightBeFunctionDeclParen = false;
/// Number of optional braces to be inserted after this token:
/// -1: a single left brace
/// 0: no braces

View File

@@ -1550,6 +1550,7 @@ private:
(!Previous->isAttribute() &&
!Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) {
Line.MightBeFunctionDecl = true;
Tok->MightBeFunctionDeclParen = true;
}
}
break;
@@ -5392,6 +5393,12 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0)
return true;
if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl &&
Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen &&
Left.ParameterCount > 0) {
return true;
}
if (Style.isCSharp()) {
if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) &&
Style.BraceWrapping.AfterFunction) {

View File

@@ -7976,6 +7976,43 @@ TEST_F(FormatTest, AllowAllArgumentsOnNextLineDontAlign) {
Input, Style);
}
TEST_F(FormatTest, BreakFunctionDefinitionParameters) {
FormatStyle Style = getLLVMStyle();
EXPECT_FALSE(Style.BreakFunctionDefinitionParameters);
StringRef Input = "void functionDecl(paramA, paramB, paramC);\n"
"void emptyFunctionDefinition() {}\n"
"void functionDefinition(int A, int B, int C) {}\n"
"Class::Class(int A, int B) : m_A(A), m_B(B) {}\n";
verifyFormat(StringRef("void functionDecl(paramA, paramB, paramC);\n"
"void emptyFunctionDefinition() {}\n"
"void functionDefinition(int A, int B, int C) {}\n"
"Class::Class(int A, int B) : m_A(A), m_B(B) {}\n"),
Input, Style);
Style.BreakFunctionDefinitionParameters = true;
verifyFormat(StringRef("void functionDecl(paramA, paramB, paramC);\n"
"void emptyFunctionDefinition() {}\n"
"void functionDefinition(\n"
" int A, int B, int C) {}\n"
"Class::Class(\n"
" int A, int B)\n"
" : m_A(A), m_B(B) {}\n"),
Input, Style);
// Test the style where all parameters are on their own lines
Style.AllowAllParametersOfDeclarationOnNextLine = false;
Style.BinPackParameters = false;
verifyFormat(StringRef("void functionDecl(paramA, paramB, paramC);\n"
"void emptyFunctionDefinition() {}\n"
"void functionDefinition(\n"
" int A,\n"
" int B,\n"
" int C) {}\n"
"Class::Class(\n"
" int A,\n"
" int B)\n"
" : m_A(A), m_B(B) {}\n"),
Input, Style);
}
TEST_F(FormatTest, BreakBeforeInlineASMColon) {
FormatStyle Style = getLLVMStyle();
Style.BreakBeforeInlineASMColon = FormatStyle::BBIAS_Never;