Skip to content

[clang-format] Add BreakFunctionDefinitionParameters option #84988

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3150,6 +3150,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 @@ -2208,6 +2208,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 @@ -4867,6 +4881,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 @@ -945,6 +945,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 @@ -1450,6 +1452,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 @@ -569,6 +569,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 @@ -1502,6 +1502,7 @@ class AnnotatingParser {
(!Previous->isAttribute() &&
!Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) {
Line.MightBeFunctionDecl = true;
Tok->MightBeFunctionDeclParen = true;
}
}
break;
Expand Down Expand Up @@ -5317,6 +5318,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 @@ -7951,6 +7951,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