[clang-format] Add SpaceBeforeCpp11BracedList option.
authorHans Wennborg <hans@hanshq.net>
Thu, 14 Jun 2018 08:01:09 +0000 (08:01 +0000)
committerHans Wennborg <hans@hanshq.net>
Thu, 14 Jun 2018 08:01:09 +0000 (08:01 +0000)
WebKit C++ style for object initialization is as follows:

  Foo foo { bar };

Yet using clang-format -style=webkit changes this to:

  Foo foo{ bar };

As there is no existing combination of rules that will ensure a space
before a braced list in this fashion, this patch adds a new
SpaceBeforeCpp11BracedList rule.

Patch by Ross Kirsling!

Differential Revision: https://reviews.llvm.org/D46024

llvm-svn: 334692

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 24ce4fb..976362f 100644 (file)
@@ -1791,6 +1791,18 @@ the configuration (without a prefix: ``Auto``).
      int a = 5;                     vs.     int a=5;
      a += 42                                a+=42;
 
+**SpaceBeforeCpp11BracedList** (``bool``)
+  If ``true``, a space will be inserted before a C++11 braced list
+  used to initialize an object (after the preceding identifier or type).
+
+  .. code-block:: c++
+
+     true:                                  false:
+     Foo foo { bar };               vs.     Foo foo{ bar };
+     Foo {};                                Foo{};
+     vector<int> { 1, 2, 3 };               vector<int>{ 1, 2, 3 };
+     new int[3] { 1, 2, 3 };                new int[3]{ 1, 2, 3 };
+
 **SpaceBeforeCtorInitializerColon** (``bool``)
   If ``false``, spaces will be removed before constructor initializer
   colon.
index 66b7762..efc7cf6 100644 (file)
@@ -1495,6 +1495,17 @@ struct FormatStyle {
   /// \endcode
   bool SpaceBeforeAssignmentOperators;
 
+  /// If ``true``, a space will be inserted before a C++11 braced list
+  /// used to initialize an object (after the preceding identifier or type).
+  /// \code
+  ///    true:                                  false:
+  ///    Foo foo { bar };               vs.     Foo foo{ bar };
+  ///    Foo {};                                Foo{};
+  ///    vector<int> { 1, 2, 3 };               vector<int>{ 1, 2, 3 };
+  ///    new int[3] { 1, 2, 3 };                new int[3]{ 1, 2, 3 };
+  /// \endcode
+  bool SpaceBeforeCpp11BracedList;
+
   /// If ``false``, spaces will be removed before constructor initializer
   /// colon.
   /// \code
@@ -1738,6 +1749,7 @@ struct FormatStyle {
            SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&
            SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword &&
            SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators &&
+           SpaceBeforeCpp11BracedList == R.SpaceBeforeCpp11BracedList &&
            SpaceBeforeCtorInitializerColon ==
                R.SpaceBeforeCtorInitializerColon &&
            SpaceBeforeInheritanceColon == R.SpaceBeforeInheritanceColon &&
index 7e62d15..71fc81a 100644 (file)
@@ -449,6 +449,8 @@ template <> struct MappingTraits<FormatStyle> {
                    Style.SpaceAfterTemplateKeyword);
     IO.mapOptional("SpaceBeforeAssignmentOperators",
                    Style.SpaceBeforeAssignmentOperators);
+    IO.mapOptional("SpaceBeforeCpp11BracedList",
+                   Style.SpaceBeforeCpp11BracedList);
     IO.mapOptional("SpaceBeforeCtorInitializerColon",
                    Style.SpaceBeforeCtorInitializerColon);
     IO.mapOptional("SpaceBeforeInheritanceColon",
@@ -697,6 +699,7 @@ FormatStyle getLLVMStyle() {
   LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
   LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
   LLVMStyle.SpaceBeforeAssignmentOperators = true;
+  LLVMStyle.SpaceBeforeCpp11BracedList = false;
   LLVMStyle.SpacesInAngles = false;
 
   LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
@@ -892,6 +895,7 @@ FormatStyle getWebKitStyle() {
   Style.ObjCBlockIndentWidth = 4;
   Style.ObjCSpaceAfterProperty = true;
   Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.SpaceBeforeCpp11BracedList = true;
   return Style;
 }
 
index ea95769..3280f25 100644 (file)
@@ -2548,6 +2548,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
   if (Style.isCpp()) {
     if (Left.is(tok::kw_operator))
       return Right.is(tok::coloncolon);
+    if (Right.is(tok::l_brace) && Right.BlockKind == BK_BracedInit &&
+        !Left.opensScope() && Style.SpaceBeforeCpp11BracedList)
+      return true;
   } else if (Style.Language == FormatStyle::LK_Proto ||
              Style.Language == FormatStyle::LK_TextProto) {
     if (Right.is(tok::period) &&
index 399503a..f234e28 100644 (file)
@@ -7019,6 +7019,11 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) {
                "  { \"ccccccccccccccccccccc\", 2 }\n"
                "};",
                ExtraSpaces);
+
+  FormatStyle SpaceBeforeBrace = getLLVMStyle();
+  SpaceBeforeBrace.SpaceBeforeCpp11BracedList = true;
+  verifyFormat("vector<int> x {1, 2, 3, 4};", SpaceBeforeBrace);
+  verifyFormat("f({}, {{}, {}}, MyMap[{k, v}]);", SpaceBeforeBrace);
 }
 
 TEST_F(FormatTest, FormatsBracedListsInColumnLayout) {
@@ -10622,6 +10627,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
   CHECK_PARSE_BOOL(SpaceAfterCStyleCast);
   CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword);
   CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators);
+  CHECK_PARSE_BOOL(SpaceBeforeCpp11BracedList);
   CHECK_PARSE_BOOL(SpaceBeforeCtorInitializerColon);
   CHECK_PARSE_BOOL(SpaceBeforeInheritanceColon);
   CHECK_PARSE_BOOL(SpaceBeforeRangeBasedForLoopColon);