Skip to content

Commit

Permalink
[clang-format] Add BreakFunctionDefinitionParameters option (#84988)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ameerj authored Apr 2, 2024
1 parent a9af66a commit 13be0d4
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 0 deletions.
15 changes: 15 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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>`
Expand Down
16 changes: 16 additions & 0 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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 &&
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,9 @@ struct FormatToken {
/// 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
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,7 @@ class AnnotatingParser {
(!Previous->isAttribute() &&
!Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) {
Line.MightBeFunctionDecl = true;
Tok->MightBeFunctionDeclParen = true;
}
}
break;
Expand Down Expand Up @@ -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) {
Expand Down
37 changes: 37 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 13be0d4

Please sign in to comment.