owenpan created this revision.
owenpan added reviewers: djasper, klimek, krasimir, MyDeveloperDay, curdeius, 
HazardyKnusperkeks.
owenpan added a project: clang-format.
owenpan requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

See PR50549 <https://bugs.llvm.org/show_bug.cgi?id=50549>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D105099

Files:
  clang/docs/ClangFormatStyleOptions.rst
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/lib/Format/TokenAnnotator.cpp
  clang/unittests/Format/FormatTest.cpp

Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -5953,6 +5953,28 @@
 
   FormatStyle OnePerLine = getLLVMStyle();
   OnePerLine.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
+
+  OnePerLine.ConstructorInitializerAlwaysOnePerLine = true;
+  verifyFormat("MyClass::MyClass()\n"
+               "    : a(a),\n"
+               "      b(b),\n"
+               "      c(c) {}",
+               OnePerLine);
+  verifyFormat("MyClass::MyClass()\n"
+               "    : a(a), // comment\n"
+               "      b(b),\n"
+               "      c(c) {}",
+               OnePerLine);
+  verifyFormat("MyClass::MyClass(int a)\n"
+               "    : b(a),      // comment\n"
+               "      c(a + 1) { // lined up\n"
+               "}",
+               OnePerLine);
+  verifyFormat("Constructor()\n"
+               "    : a(b, b, b) {}",
+               OnePerLine);
+  OnePerLine.ConstructorInitializerAlwaysOnePerLine = false;
+
   OnePerLine.AllowAllParametersOfDeclarationOnNextLine = false;
   verifyFormat("SomeClass::Constructor()\n"
                "    : aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
@@ -6319,6 +6341,28 @@
 
   FormatStyle OnePerLine = Style;
   OnePerLine.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
+
+  OnePerLine.ConstructorInitializerAlwaysOnePerLine = true;
+  verifyFormat("MyClass::MyClass() :\n"
+               "    a(a),\n"
+               "    b(b),\n"
+               "    c(c) {}",
+               OnePerLine);
+  verifyFormat("MyClass::MyClass() :\n"
+               "    a(a), // comment\n"
+               "    b(b),\n"
+               "    c(c) {}",
+               OnePerLine);
+  verifyFormat("MyClass::MyClass(int a) :\n"
+               "    b(a),      // comment\n"
+               "    c(a + 1) { // lined up\n"
+               "}",
+               OnePerLine);
+  verifyFormat("Constructor() :\n"
+               "    a(b, b, b) {}",
+               OnePerLine);
+  OnePerLine.ConstructorInitializerAlwaysOnePerLine = false;
+
   OnePerLine.AllowAllConstructorInitializersOnNextLine = false;
   verifyFormat("SomeClass::Constructor() :\n"
                "    aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
@@ -18122,6 +18166,7 @@
   CHECK_PARSE_BOOL(BreakBeforeTernaryOperators);
   CHECK_PARSE_BOOL(BreakStringLiterals);
   CHECK_PARSE_BOOL(CompactNamespaces);
+  CHECK_PARSE_BOOL(ConstructorInitializerAlwaysOnePerLine);
   CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine);
   CHECK_PARSE_BOOL(DeriveLineEnding);
   CHECK_PARSE_BOOL(DerivePointerAlignment);
@@ -19102,6 +19147,37 @@
 
   Style.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
   Style.ConstructorInitializerIndentWidth = 4;
+
+  Style.ConstructorInitializerAlwaysOnePerLine = true;
+  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+  Style.BraceWrapping.AfterFunction = true;
+  Style.BraceWrapping.SplitEmptyFunction = false;
+  verifyFormat("MyClass::MyClass()\n"
+               "    : a(a)\n"
+               "    , b(b)\n"
+               "    , c(c)\n"
+               "{}",
+               Style);
+  verifyFormat("MyClass::MyClass()\n"
+               "    : a(a) // comment\n"
+               "    , b(b)\n"
+               "    , c(c)\n"
+               "{}",
+               Style);
+  verifyFormat("MyClass::MyClass(int a)\n"
+               "    : b(a)     // comment\n"
+               "    , c(a + 1) // lined up\n"
+               "{}",
+               Style);
+  verifyFormat("Constructor()\n"
+               "    : a(b, b, b)\n"
+               "{}",
+               Style);
+  Style.ConstructorInitializerAlwaysOnePerLine = false;
+  Style.BreakBeforeBraces = FormatStyle::BS_Attach;
+  Style.BraceWrapping.AfterFunction = false;
+  Style.BraceWrapping.SplitEmptyFunction = true;
+
   verifyFormat("SomeClass::Constructor() : aaaaaaaa(aaaaaaaa) {}", Style);
   verifyFormat(
       "SomeClass::Constructor() : aaaaa(aaaaa), aaaaa(aaaaa), aaaaa(aaaaa)\n",
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3739,13 +3739,19 @@
       return Style.BreakBeforeConceptDeclarations;
     return (Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes);
   }
-  if (Right.is(TT_CtorInitializerComma) &&
-      Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
-      !Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
-    return true;
-  if (Right.is(TT_CtorInitializerColon) &&
+  if (Style.ConstructorInitializerAlwaysOnePerLine) {
+    if (Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon &&
+        (Left.is(TT_CtorInitializerComma) || Right.is(TT_CtorInitializerColon)))
+      return true;
+
+    if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&
+        Left.isOneOf(TT_CtorInitializerColon, TT_CtorInitializerComma))
+      return true;
+  }
+  if (Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon) &&
       Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
-      !Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
+      (Style.ConstructorInitializerAlwaysOnePerLine ||
+       !Style.ConstructorInitializerAllOnOneLineOrOnePerLine))
     return true;
   // Break only if we have multiple inheritance.
   if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -633,6 +633,8 @@
     IO.mapOptional("ColumnLimit", Style.ColumnLimit);
     IO.mapOptional("CommentPragmas", Style.CommentPragmas);
     IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
+    IO.mapOptional("ConstructorInitializerAlwaysOnePerLine",
+                   Style.ConstructorInitializerAlwaysOnePerLine);
     IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
                    Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
     IO.mapOptional("ConstructorInitializerIndentWidth",
@@ -1034,6 +1036,7 @@
   LLVMStyle.ColumnLimit = 80;
   LLVMStyle.CommentPragmas = "^ IWYU pragma:";
   LLVMStyle.CompactNamespaces = false;
+  LLVMStyle.ConstructorInitializerAlwaysOnePerLine = false;
   LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
   LLVMStyle.ConstructorInitializerIndentWidth = 4;
   LLVMStyle.ContinuationIndentWidth = 4;
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -507,9 +507,9 @@
 
   /// \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.
+  /// line, if ``ConstructorInitializerAllOnOneLineOrOnePerLine`` is true.
   /// Note that this parameter has no effect if
-  /// ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is false.
+  /// ``ConstructorInitializerAllOnOneLineOrOnePerLine`` is false.
   /// \code
   ///   true:
   ///   MyClass::MyClass() :
@@ -1894,9 +1894,24 @@
   /// \endcode
   bool CompactNamespaces;
 
+  /// Always put each constructor initializer on its own line.
+  /// \code
+  ///   true:
+  ///   MyClass::MyClass() :
+  ///       member0(0),
+  ///       member1(2) {}
+  ///
+  ///   false:
+  ///   MyClass::MyClass() :
+  ///       member0(0), member1(2) {}
+  /// \endcode
+  bool ConstructorInitializerAlwaysOnePerLine;
+
   // clang-format off
-  /// If the constructor initializers don't fit on a line, put each
-  /// initializer on its own line.
+  /// If the constructor initializers don't fit on a line, put each initializer
+  /// on its own line.
+  /// Note that this parameter has no effect if
+  /// ``ConstructorInitializerAlwaysOnePerLine`` is true.
   /// \code
   ///   true:
   ///   SomeClass::Constructor()
@@ -3424,6 +3439,8 @@
            BreakStringLiterals == R.BreakStringLiterals &&
            ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas &&
            BreakInheritanceList == R.BreakInheritanceList &&
+           ConstructorInitializerAlwaysOnePerLine ==
+               R.ConstructorInitializerAlwaysOnePerLine &&
            ConstructorInitializerAllOnOneLineOrOnePerLine ==
                R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
            ConstructorInitializerIndentWidth ==
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -648,9 +648,9 @@
 **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.
+  line, if ``ConstructorInitializerAllOnOneLineOrOnePerLine`` is true.
   Note that this parameter has no effect if
-  ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is false.
+  ``ConstructorInitializerAllOnOneLineOrOnePerLine`` is false.
 
   .. code-block:: c++
 
@@ -2141,8 +2141,10 @@
     }}}
 
 **ConstructorInitializerAllOnOneLineOrOnePerLine** (``bool``)
-  If the constructor initializers don't fit on a line, put each
-  initializer on its own line.
+  If the constructor initializers don't fit on a line, put each initializer
+  on its own line.
+  Note that this parameter has no effect if
+  ``ConstructorInitializerAlwaysOnePerLine`` is true.
 
   .. code-block:: c++
 
@@ -2159,6 +2161,20 @@
       return 0;
     }
 
+**ConstructorInitializerAlwaysOnePerLine** (``bool``)
+  Always put each constructor initializer on its own line.
+
+  .. code-block:: c++
+
+    true:
+    MyClass::MyClass() :
+        member0(0),
+        member1(2) {}
+
+    false:
+    MyClass::MyClass() :
+        member0(0), member1(2) {}
+
 **ConstructorInitializerIndentWidth** (``unsigned``)
   The number of characters to use for indentation of constructor
   initializer lists as well as inheritance lists.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to