summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Hoad <mydeveloperday@gmail.com>2019-03-23 14:37:58 +0000
committerPaul Hoad <mydeveloperday@gmail.com>2019-03-23 14:37:58 +0000
commitc4515d09740be87226d185f7728893d26c5af652 (patch)
tree230defb16fb135ddae412588f337598f170894bd
parentf503b6985438025bd8fee75a547c9aec8b0a0c74 (diff)
Clang-format: add finer-grained options for putting all arguments on one line
Summary: Add two new options, AllowAllArgumentsOnNextLine and AllowAllConstructorInitializersOnNextLine. These mirror the existing AllowAllParametersOfDeclarationOnNextLine and allow me to support an internal style guide where I work. I think this would be generally useful, some have asked for it on stackoverflow: https://stackoverflow.com/questions/30057534/clang-format-binpackarguments-not-working-as-expected https://stackoverflow.com/questions/38635106/clang-format-how-to-prevent-all-function-arguments-on-next-line Reviewers: djasper, krasimir, MyDeveloperDay Reviewed By: MyDeveloperDay Subscribers: jkorous, MyDeveloperDay, aol-nnov, lebedev.ri, uohcsemaj, cfe-commits, klimek Differential Revision: https://reviews.llvm.org/D40988 Patch By: russellmcc (Russell McClellan) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@356834 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/ClangFormatStyleOptions.rst35
-rw-r--r--include/clang/Format/Format.h35
-rw-r--r--lib/Format/ContinuationIndenter.cpp32
-rw-r--r--lib/Format/Format.cpp7
-rw-r--r--unittests/Format/FormatTest.cpp199
5 files changed, 299 insertions, 9 deletions
diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst
index 1a783fd430..0ddc313d27 100644
--- a/docs/ClangFormatStyleOptions.rst
+++ b/docs/ClangFormatStyleOptions.rst
@@ -277,6 +277,41 @@ the configuration (without a prefix: ``Auto``).
int a; // My comment a vs. int a; // My comment a
int b = 2; // comment b int b = 2; // comment about b
+**AllowAllArgumentsOnNextLine** (``bool``)
+ If a function call or braced initializer list doesn't fit on a
+ line, allow putting all arguments onto the next line, even if
+ ``BinPackArguments`` is ``false``.
+
+ .. code-block:: c++
+
+ true:
+ callFunction(
+ a, b, c, d);
+
+ false:
+ callFunction(a,
+ b,
+ c,
+ d);
+
+**AllowAllConstructorInitializersOnNextLine** (``bool``)
+ If a constructor definition with a member initializer list doesn't
+ fit on a single line, allow putting all member initializers onto the next
+ line, if ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is true.
+ Note that this parameter has no effect if
+ ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is false.
+
+ .. code-block:: c++
+
+ true:
+ MyClass::MyClass() :
+ member0(0), member1(2) {}
+
+ false:
+ MyClass::MyClass() :
+ member0(0),
+ member1(2) {}
+
**AllowAllParametersOfDeclarationOnNextLine** (``bool``)
If the function declaration doesn't fit on a line,
allow putting all parameters of a function declaration onto
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 34a511f654..40f962016b 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -154,6 +154,38 @@ struct FormatStyle {
/// \endcode
bool AlignTrailingComments;
+ /// \brief If a function call or braced initializer list doesn't fit on a
+ /// line, allow putting all arguments onto the next line, even if
+ /// ``BinPackArguments`` is ``false``.
+ /// \code
+ /// true:
+ /// callFunction(
+ /// a, b, c, d);
+ ///
+ /// false:
+ /// callFunction(a,
+ /// b,
+ /// c,
+ /// d);
+ /// \endcode
+ bool AllowAllArgumentsOnNextLine;
+
+ /// \brief If a constructor definition with a member initializer list doesn't
+ /// fit on a single line, allow putting all member initializers onto the next
+ /// line, if ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is true.
+ /// Note that this parameter has no effect if
+ /// ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is false.
+ /// \code
+ /// true:
+ /// MyClass::MyClass() :
+ /// member0(0), member1(2) {}
+ ///
+ /// false:
+ /// MyClass::MyClass() :
+ /// member0(0),
+ /// member1(2) {}
+ bool AllowAllConstructorInitializersOnNextLine;
+
/// If the function declaration doesn't fit on a line,
/// allow putting all parameters of a function declaration onto
/// the next line even if ``BinPackParameters`` is ``false``.
@@ -1761,6 +1793,9 @@ struct FormatStyle {
AlignEscapedNewlines == R.AlignEscapedNewlines &&
AlignOperands == R.AlignOperands &&
AlignTrailingComments == R.AlignTrailingComments &&
+ AllowAllArgumentsOnNextLine == R.AllowAllArgumentsOnNextLine &&
+ AllowAllConstructorInitializersOnNextLine ==
+ R.AllowAllConstructorInitializersOnNextLine &&
AllowAllParametersOfDeclarationOnNextLine ==
R.AllowAllParametersOfDeclarationOnNextLine &&
AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine &&
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index a2a13d4d46..b64fdd7c0b 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -881,14 +881,30 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
State.Stack.back().BreakBeforeClosingBrace = true;
if (State.Stack.back().AvoidBinPacking) {
- // If we are breaking after '(', '{', '<', this is not bin packing
- // unless AllowAllParametersOfDeclarationOnNextLine is false or this is a
- // dict/object literal.
- if (!Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
+ // If we are breaking after '(', '{', '<', or this is the break after a ':'
+ // to start a member initializater list in a constructor, this should not
+ // be considered bin packing unless the relevant AllowAll option is false or
+ // this is a dict/object literal.
+ bool PreviousIsBreakingCtorInitializerColon =
+ Previous.is(TT_CtorInitializerColon) &&
+ Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon;
+ if (!(Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
+ PreviousIsBreakingCtorInitializerColon) ||
(!Style.AllowAllParametersOfDeclarationOnNextLine &&
State.Line->MustBeDeclaration) ||
+ (!Style.AllowAllArgumentsOnNextLine &&
+ !State.Line->MustBeDeclaration) ||
+ (!Style.AllowAllConstructorInitializersOnNextLine &&
+ PreviousIsBreakingCtorInitializerColon) ||
Previous.is(TT_DictLiteral))
State.Stack.back().BreakBeforeParameter = true;
+
+ // If we are breaking after a ':' to start a member initializer list,
+ // and we allow all arguments on the next line, we should not break
+ // before the next parameter.
+ if (PreviousIsBreakingCtorInitializerColon &&
+ Style.AllowAllConstructorInitializersOnNextLine)
+ State.Stack.back().BreakBeforeParameter = false;
}
return Penalty;
@@ -1102,9 +1118,13 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
? 0
: 2);
State.Stack.back().NestedBlockIndent = State.Stack.back().Indent;
- if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
+ if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine) {
State.Stack.back().AvoidBinPacking = true;
- State.Stack.back().BreakBeforeParameter = false;
+ State.Stack.back().BreakBeforeParameter =
+ !Style.AllowAllConstructorInitializersOnNextLine;
+ } else {
+ State.Stack.back().BreakBeforeParameter = false;
+ }
}
if (Current.is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon) {
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 5fe118a716..2d1adb58e4 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -335,6 +335,10 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
IO.mapOptional("AlignOperands", Style.AlignOperands);
IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
+ IO.mapOptional("AllowAllArgumentsOnNextLine",
+ Style.AllowAllArgumentsOnNextLine);
+ IO.mapOptional("AllowAllConstructorInitializersOnNextLine",
+ Style.AllowAllConstructorInitializersOnNextLine);
IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
Style.AllowAllParametersOfDeclarationOnNextLine);
IO.mapOptional("AllowShortBlocksOnASingleLine",
@@ -351,6 +355,7 @@ template <> struct MappingTraits<FormatStyle> {
Style.AlwaysBreakAfterDefinitionReturnType);
IO.mapOptional("AlwaysBreakAfterReturnType",
Style.AlwaysBreakAfterReturnType);
+
// If AlwaysBreakAfterDefinitionReturnType was specified but
// AlwaysBreakAfterReturnType was not, initialize the latter from the
// former for backwards compatibility.
@@ -641,6 +646,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignTrailingComments = true;
LLVMStyle.AlignConsecutiveAssignments = false;
LLVMStyle.AlignConsecutiveDeclarations = false;
+ LLVMStyle.AllowAllArgumentsOnNextLine = true;
+ LLVMStyle.AllowAllConstructorInitializersOnNextLine = true;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
LLVMStyle.AllowShortBlocksOnASingleLine = false;
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index eaf818c16c..f9b2fe2e9f 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -3956,6 +3956,191 @@ TEST_F(FormatTest, ConstructorInitializers) {
" aaaa(aaaa) {}"));
}
+TEST_F(FormatTest, AllowAllConstructorInitializersOnNextLine) {
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
+ Style.ColumnLimit = 60;
+ Style.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
+ Style.AllowAllConstructorInitializersOnNextLine = true;
+ Style.BinPackParameters = false;
+
+ for (int i = 0; i < 4; ++i) {
+ // Test all combinations of parameters that should not have an effect.
+ Style.AllowAllParametersOfDeclarationOnNextLine = i & 1;
+ Style.AllowAllArgumentsOnNextLine = i & 2;
+
+ Style.AllowAllConstructorInitializersOnNextLine = true;
+ Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
+ verifyFormat("Constructor()\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+ verifyFormat("Constructor() : a(a), b(b) {}", Style);
+
+ Style.AllowAllConstructorInitializersOnNextLine = false;
+ verifyFormat("Constructor()\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a)\n"
+ " , bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+ verifyFormat("Constructor() : a(a), b(b) {}", Style);
+
+ Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
+ Style.AllowAllConstructorInitializersOnNextLine = true;
+ verifyFormat("Constructor()\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.AllowAllConstructorInitializersOnNextLine = false;
+ verifyFormat("Constructor()\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a),\n"
+ " bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.BreakConstructorInitializers = FormatStyle::BCIS_AfterColon;
+ Style.AllowAllConstructorInitializersOnNextLine = true;
+ verifyFormat("Constructor() :\n"
+ " aaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.AllowAllConstructorInitializersOnNextLine = false;
+ verifyFormat("Constructor() :\n"
+ " aaaaaaaaaaaaaaaaaa(a),\n"
+ " bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+ }
+
+ // Test interactions between AllowAllParametersOfDeclarationOnNextLine and
+ // AllowAllConstructorInitializersOnNextLine in all
+ // BreakConstructorInitializers modes
+ Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
+ Style.AllowAllParametersOfDeclarationOnNextLine = true;
+ Style.AllowAllConstructorInitializersOnNextLine = false;
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbb)\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a)\n"
+ " , bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.AllowAllConstructorInitializersOnNextLine = true;
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " int bbbbbbbbbbbbb,\n"
+ " int cccccccccccccccc)\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.AllowAllParametersOfDeclarationOnNextLine = false;
+ Style.AllowAllConstructorInitializersOnNextLine = false;
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " int bbbbbbbbbbbbb)\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a)\n"
+ " , bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
+
+ Style.AllowAllParametersOfDeclarationOnNextLine = true;
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbb)\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a),\n"
+ " bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.AllowAllConstructorInitializersOnNextLine = true;
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " int bbbbbbbbbbbbb,\n"
+ " int cccccccccccccccc)\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.AllowAllParametersOfDeclarationOnNextLine = false;
+ Style.AllowAllConstructorInitializersOnNextLine = false;
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " int bbbbbbbbbbbbb)\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a),\n"
+ " bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.BreakConstructorInitializers = FormatStyle::BCIS_AfterColon;
+ Style.AllowAllParametersOfDeclarationOnNextLine = true;
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbb) :\n"
+ " aaaaaaaaaaaaaaaaaaaa(a),\n"
+ " bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.AllowAllConstructorInitializersOnNextLine = true;
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " int bbbbbbbbbbbbb,\n"
+ " int cccccccccccccccc) :\n"
+ " aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.AllowAllParametersOfDeclarationOnNextLine = false;
+ Style.AllowAllConstructorInitializersOnNextLine = false;
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " int bbbbbbbbbbbbb) :\n"
+ " aaaaaaaaaaaaaaaaaaaa(a),\n"
+ " bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+}
+
+TEST_F(FormatTest, AllowAllArgumentsOnNextLine) {
+ FormatStyle Style = getLLVMStyle();
+ Style.ColumnLimit = 60;
+ Style.BinPackArguments = false;
+ for (int i = 0; i < 4; ++i) {
+ // Test all combinations of parameters that should not have an effect.
+ Style.AllowAllParametersOfDeclarationOnNextLine = i & 1;
+ Style.AllowAllConstructorInitializersOnNextLine = i & 2;
+
+ Style.AllowAllArgumentsOnNextLine = true;
+ verifyFormat("void foo() {\n"
+ " FunctionCallWithReallyLongName(\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbb);\n"
+ "}",
+ Style);
+ Style.AllowAllArgumentsOnNextLine = false;
+ verifyFormat("void foo() {\n"
+ " FunctionCallWithReallyLongName(\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " bbbbbbbbbbbb);\n"
+ "}",
+ Style);
+
+ Style.AllowAllArgumentsOnNextLine = true;
+ verifyFormat("void foo() {\n"
+ " auto VariableWithReallyLongName = {\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbb};\n"
+ "}",
+ Style);
+ Style.AllowAllArgumentsOnNextLine = false;
+ verifyFormat("void foo() {\n"
+ " auto VariableWithReallyLongName = {\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " bbbbbbbbbbbb};\n"
+ "}",
+ Style);
+ }
+
+ // This parameter should not affect declarations.
+ Style.BinPackParameters = false;
+ Style.AllowAllArgumentsOnNextLine = false;
+ Style.AllowAllParametersOfDeclarationOnNextLine = true;
+ verifyFormat("void FunctionCallWithReallyLongName(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbb);",
+ Style);
+ Style.AllowAllParametersOfDeclarationOnNextLine = false;
+ verifyFormat("void FunctionCallWithReallyLongName(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " int bbbbbbbbbbbb);",
+ Style);
+}
+
TEST_F(FormatTest, BreakConstructorInitializersAfterColon) {
FormatStyle Style = getLLVMStyle();
Style.BreakConstructorInitializers = FormatStyle::BCIS_AfterColon;
@@ -3973,17 +4158,23 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) {
verifyFormat("template <typename T>\n"
"Constructor() : Initializer(FitsOnTheLine) {}",
getStyleWithColumns(Style, 50));
+ Style.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
+ verifyFormat(
+ "SomeClass::Constructor() :\n"
+ " aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}",
+ Style);
+ Style.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
verifyFormat(
"SomeClass::Constructor() :\n"
" aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}",
- Style);
+ Style);
verifyFormat(
"SomeClass::Constructor() :\n"
" aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
" aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}",
- Style);
+ Style);
verifyFormat(
"SomeClass::Constructor() :\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa),\n"
@@ -4029,7 +4220,7 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) {
FormatStyle OnePerLine = Style;
OnePerLine.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
- OnePerLine.AllowAllParametersOfDeclarationOnNextLine = false;
+ OnePerLine.AllowAllConstructorInitializersOnNextLine = false;
verifyFormat("SomeClass::Constructor() :\n"
" aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
" aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
@@ -11025,6 +11216,8 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(AlignTrailingComments);
CHECK_PARSE_BOOL(AlignConsecutiveAssignments);
CHECK_PARSE_BOOL(AlignConsecutiveDeclarations);
+ CHECK_PARSE_BOOL(AllowAllArgumentsOnNextLine);
+ CHECK_PARSE_BOOL(AllowAllConstructorInitializersOnNextLine);
CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine);
CHECK_PARSE_BOOL(AllowShortBlocksOnASingleLine);
CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine);