Skip to content

Commit 25d45a4

Browse files
committed
[clang-format] allow short function body on a single line
clang-format doesn't put short function body on a single line even if user asks to put short blocks on a single line and do not put a whole function on a single line. Add tryMergeSimpleBlocks() if we find user want to put short function body on a single line. Signed-off-by: Lidong Yan <[email protected]>
1 parent 3e42146 commit 25d45a4

File tree

7 files changed

+114
-4
lines changed

7 files changed

+114
-4
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5405,6 +5405,25 @@ the configuration (without a prefix: ``Auto``).
54055405

54065406

54075407

5408+
.. _PutShortFunctionBodiesOnASingleLine:
5409+
5410+
**PutShortFunctionBodiesOnASingleLine** (``Boolean``) :versionbadge:`clang-format 20` :ref:`<PutShortFunctionBodiesOnASingleLine>`
5411+
Dependent on the value, function body can be put on a single line.
5412+
Automatically enabled when
5413+
`AllowShortFunctionsOnASingleLine` is set to `None` and
5414+
`AllowShortBlocksOnASingleLine` is set to `Always`.
5415+
5416+
.. code-block:: c++
5417+
5418+
true:
5419+
int f()
5420+
{ return 0; }
5421+
5422+
false:
5423+
int f() {
5424+
return 0;
5425+
}
5426+
54085427
.. _QualifierAlignment:
54095428

54105429
**QualifierAlignment** (``QualifierAlignmentStyle``) :versionbadge:`clang-format 14` :ref:`<QualifierAlignment>`

clang/include/clang/Format/Format.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3829,6 +3829,23 @@ struct FormatStyle {
38293829
/// \version 13
38303830
int PPIndentWidth;
38313831

3832+
/// Dependent on the value, function body can be put on a single line.
3833+
/// Automatically enabled when
3834+
/// `AllowShortFunctionsOnASingleLine` is set to `None` and
3835+
/// `AllowShortBlocksOnASingleLine` is set to `Always`.
3836+
/// \code
3837+
/// true:
3838+
/// int f()
3839+
/// { return 0; }
3840+
///
3841+
/// false:
3842+
/// int f() {
3843+
/// return 0;
3844+
/// }
3845+
/// \endcode
3846+
/// \version 20
3847+
bool PutShortFunctionBodiesOnASingleLine;
3848+
38323849
/// Different specifiers and qualifiers alignment styles.
38333850
enum QualifierAlignmentStyle : int8_t {
38343851
/// Don't change specifiers/qualifiers to either Left or Right alignment
@@ -5461,6 +5478,8 @@ struct FormatStyle {
54615478
PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
54625479
PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
54635480
PointerAlignment == R.PointerAlignment &&
5481+
PutShortFunctionBodiesOnASingleLine ==
5482+
R.PutShortFunctionBodiesOnASingleLine &&
54645483
QualifierAlignment == R.QualifierAlignment &&
54655484
QualifierOrder == R.QualifierOrder &&
54665485
RawStringFormats == R.RawStringFormats &&

clang/lib/Format/ContinuationIndenter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,13 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
390390
return true;
391391
}
392392

393+
// `PutShortFunctionBodiesOnASingleLine = true` will wrap left brace into
394+
// a new line, do not break before the left brace.
395+
if (Current.is(TT_FunctionLBrace) && !Style.BraceWrapping.AfterFunction &&
396+
Style.PutShortFunctionBodiesOnASingleLine) {
397+
return false;
398+
}
399+
393400
return !State.NoLineBreak && !CurrentState.NoLineBreak;
394401
}
395402

clang/lib/Format/Format.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,8 @@ template <> struct MappingTraits<FormatStyle> {
11441144
Style.PenaltyReturnTypeOnItsOwnLine);
11451145
IO.mapOptional("PointerAlignment", Style.PointerAlignment);
11461146
IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);
1147+
IO.mapOptional("PutShortFunctionBodiesOnASingleLine",
1148+
Style.PutShortFunctionBodiesOnASingleLine);
11471149
IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);
11481150
// Default Order for Left/Right based Qualifier alignment.
11491151
if (Style.QualifierAlignment == FormatStyle::QAS_Right)
@@ -1643,6 +1645,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
16431645
LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
16441646
LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
16451647
LLVMStyle.PPIndentWidth = -1;
1648+
LLVMStyle.PutShortFunctionBodiesOnASingleLine = false;
16461649
LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
16471650
LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
16481651
LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
@@ -3828,6 +3831,10 @@ reformat(const FormatStyle &Style, StringRef Code,
38283831
default:
38293832
break;
38303833
}
3834+
if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None &&
3835+
Expanded.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always) {
3836+
Expanded.PutShortFunctionBodiesOnASingleLine = true;
3837+
}
38313838

38323839
if (Expanded.DisableFormat)
38333840
return {tooling::Replacements(), 0};

clang/lib/Format/UnwrappedLineFormatter.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,13 @@ class LineJoiner {
242242
if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)
243243
return 0;
244244

245-
unsigned Limit =
245+
unsigned LimitStripIndent =
246246
Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent;
247247
// If we already exceed the column limit, we set 'Limit' to 0. The different
248248
// tryMerge..() functions can then decide whether to still do merging.
249-
Limit = TheLine->Last->TotalLength > Limit
250-
? 0
251-
: Limit - TheLine->Last->TotalLength;
249+
unsigned Limit = TheLine->Last->TotalLength > LimitStripIndent
250+
? 0
251+
: LimitStripIndent - TheLine->Last->TotalLength;
252252

253253
if (TheLine->Last->is(TT_FunctionLBrace) &&
254254
TheLine->First == TheLine->Last &&
@@ -257,6 +257,12 @@ class LineJoiner {
257257
return tryMergeSimpleBlock(I, E, Limit);
258258
}
259259

260+
if (TheLine->Last->is(TT_FunctionLBrace) &&
261+
TheLine->First == TheLine->Last &&
262+
Style.PutShortFunctionBodiesOnASingleLine) {
263+
return tryMergeSimpleBlock(I, E, Limit);
264+
}
265+
260266
const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] : nullptr;
261267
// Handle empty record blocks where the brace has already been wrapped.
262268
if (PreviousLine && TheLine->Last->is(tok::l_brace) &&
@@ -532,6 +538,24 @@ class LineJoiner {
532538
}
533539
return MergedLines;
534540
}
541+
542+
// UnwrappedLineParser would move the left brace to a new line when
543+
// PutShortFunctionBodiesOnASingleLine is enabled. However, if the
544+
// function body cannot fit on a single line, and
545+
// Style.BraceWrapping.AfterFunction is false, we should merge the
546+
// function name and the left brace back onto the same line.
547+
if (NextLine.First->is(TT_FunctionLBrace) &&
548+
Style.PutShortFunctionBodiesOnASingleLine &&
549+
!Style.BraceWrapping.AfterFunction) {
550+
unsigned MergedLines = 0;
551+
unsigned NextLineLimit =
552+
NextLine.Last->TotalLength > LimitStripIndent
553+
? 0
554+
: LimitStripIndent - NextLine.Last->TotalLength;
555+
MergedLines = tryMergeSimpleBlock(I + 1, E, NextLineLimit);
556+
return MergedLines > 0 ? 0 : 1;
557+
}
558+
535559
auto IsElseLine = [&TheLine]() -> bool {
536560
const FormatToken *First = TheLine->First;
537561
if (First->is(tok::kw_else))

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,6 +1921,10 @@ void UnwrappedLineParser::parseStructuralElement(
19211921
}
19221922
} else if (Style.BraceWrapping.AfterFunction) {
19231923
addUnwrappedLine();
1924+
} else if (Style.PutShortFunctionBodiesOnASingleLine) {
1925+
// Wrap the left brace here; we'll try to merge it back
1926+
// later if needed.
1927+
addUnwrappedLine();
19241928
}
19251929
if (!Previous || Previous->isNot(TT_TypeDeclarationParen))
19261930
FormatTok->setFinalizedType(TT_FunctionLBrace);

clang/unittests/Format/FormatTest.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14941,11 +14941,24 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) {
1494114941
FormatStyle DoNotMerge = getLLVMStyle();
1494214942
DoNotMerge.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
1494314943

14944+
FormatStyle MergeBodyOnly = getLLVMStyle();
14945+
MergeBodyOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
14946+
MergeBodyOnly.PutShortFunctionBodiesOnASingleLine = true;
14947+
14948+
FormatStyle MergeBodyIfPossible = getLLVMStyleWithColumns(20);
14949+
MergeBodyIfPossible.PutShortFunctionBodiesOnASingleLine = true;
14950+
1494414951
verifyFormat("void f() { return 42; }");
1494514952
verifyFormat("void f() {\n"
1494614953
" return 42;\n"
1494714954
"}",
1494814955
DoNotMerge);
14956+
verifyFormat("void f()\n"
14957+
"{ return 42; }",
14958+
MergeBodyOnly);
14959+
verifyFormat("void long_function_name()\n"
14960+
"{ return 42; }",
14961+
MergeBodyIfPossible);
1494914962
verifyFormat("void f() {\n"
1495014963
" // Comment\n"
1495114964
"}");
@@ -14966,6 +14979,23 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) {
1496614979
" int a;\n"
1496714980
"} // comment",
1496814981
DoNotMerge);
14982+
verifyFormat("void f()\n"
14983+
"{} // comment",
14984+
MergeBodyOnly);
14985+
verifyFormat("void f()\n"
14986+
"{ int a; } // comment",
14987+
MergeBodyOnly);
14988+
verifyFormat("void long_function_name()\n"
14989+
"{} // comment",
14990+
MergeBodyIfPossible);
14991+
verifyFormat("void f() {\n"
14992+
" int a;\n"
14993+
"} // comment",
14994+
MergeBodyIfPossible);
14995+
MergeBodyIfPossible.ColumnLimit = 21;
14996+
verifyFormat("void f()\n"
14997+
"{ int a; } // comment",
14998+
MergeBodyIfPossible);
1496914999
verifyFormat("void f() {\n"
1497015000
"} // comment",
1497115001
getLLVMStyleWithColumns(15));

0 commit comments

Comments
 (0)