Skip to content

Commit 13be0d4

Browse files
authored
[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
1 parent a9af66a commit 13be0d4

File tree

6 files changed

+81
-0
lines changed

6 files changed

+81
-0
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,6 +3295,21 @@ the configuration (without a prefix: ``Auto``).
32953295

32963296

32973297

3298+
.. _BreakFunctionDefinitionParameters:
3299+
3300+
**BreakFunctionDefinitionParameters** (``Boolean``) :versionbadge:`clang-format 19` :ref:`<BreakFunctionDefinitionParameters>`
3301+
If ``true``, clang-format will always break before function definition
3302+
parameters.
3303+
3304+
.. code-block:: c++
3305+
3306+
true:
3307+
void functionDefinition(
3308+
int A, int B) {}
3309+
3310+
false:
3311+
void functionDefinition(int A, int B) {}
3312+
32983313
.. _BreakInheritanceList:
32993314

33003315
**BreakInheritanceList** (``BreakInheritanceListStyle``) :versionbadge:`clang-format 7` :ref:`<BreakInheritanceList>`

clang/include/clang/Format/Format.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,6 +2223,20 @@ struct FormatStyle {
22232223
/// \version 5
22242224
BreakConstructorInitializersStyle BreakConstructorInitializers;
22252225

2226+
/// If ``true``, clang-format will always break before function definition
2227+
/// parameters.
2228+
/// \code
2229+
/// true:
2230+
/// void functionDefinition(
2231+
/// int A, int B) {}
2232+
///
2233+
/// false:
2234+
/// void functionDefinition(int A, int B) {}
2235+
///
2236+
/// \endcode
2237+
/// \version 19
2238+
bool BreakFunctionDefinitionParameters;
2239+
22262240
/// Break after each annotation on a field in Java files.
22272241
/// \code{.java}
22282242
/// true: false:
@@ -4938,6 +4952,8 @@ struct FormatStyle {
49384952
BreakBeforeInlineASMColon == R.BreakBeforeInlineASMColon &&
49394953
BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators &&
49404954
BreakConstructorInitializers == R.BreakConstructorInitializers &&
4955+
BreakFunctionDefinitionParameters ==
4956+
R.BreakFunctionDefinitionParameters &&
49414957
BreakInheritanceList == R.BreakInheritanceList &&
49424958
BreakStringLiterals == R.BreakStringLiterals &&
49434959
BreakTemplateDeclarations == R.BreakTemplateDeclarations &&

clang/lib/Format/Format.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,8 @@ template <> struct MappingTraits<FormatStyle> {
955955
Style.BreakBeforeTernaryOperators);
956956
IO.mapOptional("BreakConstructorInitializers",
957957
Style.BreakConstructorInitializers);
958+
IO.mapOptional("BreakFunctionDefinitionParameters",
959+
Style.BreakFunctionDefinitionParameters);
958960
IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
959961
IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
960962
IO.mapOptional("BreakTemplateDeclarations",
@@ -1465,6 +1467,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
14651467
LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
14661468
LLVMStyle.BreakBeforeTernaryOperators = true;
14671469
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
1470+
LLVMStyle.BreakFunctionDefinitionParameters = false;
14681471
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
14691472
LLVMStyle.BreakStringLiterals = true;
14701473
LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;

clang/lib/Format/FormatToken.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,9 @@ struct FormatToken {
574574
/// Is optional and can be removed.
575575
bool Optional = false;
576576

577+
/// Might be function declaration open/closing paren.
578+
bool MightBeFunctionDeclParen = false;
579+
577580
/// Number of optional braces to be inserted after this token:
578581
/// -1: a single left brace
579582
/// 0: no braces

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,7 @@ class AnnotatingParser {
15501550
(!Previous->isAttribute() &&
15511551
!Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) {
15521552
Line.MightBeFunctionDecl = true;
1553+
Tok->MightBeFunctionDeclParen = true;
15531554
}
15541555
}
15551556
break;
@@ -5392,6 +5393,12 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
53925393
if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0)
53935394
return true;
53945395

5396+
if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl &&
5397+
Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen &&
5398+
Left.ParameterCount > 0) {
5399+
return true;
5400+
}
5401+
53955402
if (Style.isCSharp()) {
53965403
if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) &&
53975404
Style.BraceWrapping.AfterFunction) {

clang/unittests/Format/FormatTest.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7976,6 +7976,43 @@ TEST_F(FormatTest, AllowAllArgumentsOnNextLineDontAlign) {
79767976
Input, Style);
79777977
}
79787978

7979+
TEST_F(FormatTest, BreakFunctionDefinitionParameters) {
7980+
FormatStyle Style = getLLVMStyle();
7981+
EXPECT_FALSE(Style.BreakFunctionDefinitionParameters);
7982+
StringRef Input = "void functionDecl(paramA, paramB, paramC);\n"
7983+
"void emptyFunctionDefinition() {}\n"
7984+
"void functionDefinition(int A, int B, int C) {}\n"
7985+
"Class::Class(int A, int B) : m_A(A), m_B(B) {}\n";
7986+
verifyFormat(StringRef("void functionDecl(paramA, paramB, paramC);\n"
7987+
"void emptyFunctionDefinition() {}\n"
7988+
"void functionDefinition(int A, int B, int C) {}\n"
7989+
"Class::Class(int A, int B) : m_A(A), m_B(B) {}\n"),
7990+
Input, Style);
7991+
Style.BreakFunctionDefinitionParameters = true;
7992+
verifyFormat(StringRef("void functionDecl(paramA, paramB, paramC);\n"
7993+
"void emptyFunctionDefinition() {}\n"
7994+
"void functionDefinition(\n"
7995+
" int A, int B, int C) {}\n"
7996+
"Class::Class(\n"
7997+
" int A, int B)\n"
7998+
" : m_A(A), m_B(B) {}\n"),
7999+
Input, Style);
8000+
// Test the style where all parameters are on their own lines
8001+
Style.AllowAllParametersOfDeclarationOnNextLine = false;
8002+
Style.BinPackParameters = false;
8003+
verifyFormat(StringRef("void functionDecl(paramA, paramB, paramC);\n"
8004+
"void emptyFunctionDefinition() {}\n"
8005+
"void functionDefinition(\n"
8006+
" int A,\n"
8007+
" int B,\n"
8008+
" int C) {}\n"
8009+
"Class::Class(\n"
8010+
" int A,\n"
8011+
" int B)\n"
8012+
" : m_A(A), m_B(B) {}\n"),
8013+
Input, Style);
8014+
}
8015+
79798016
TEST_F(FormatTest, BreakBeforeInlineASMColon) {
79808017
FormatStyle Style = getLLVMStyle();
79818018
Style.BreakBeforeInlineASMColon = FormatStyle::BBIAS_Never;

0 commit comments

Comments
 (0)