]> granicus.if.org Git - clang/commitdiff
Implements brace breaking styles.
authorManuel Klimek <klimek@google.com>
Mon, 13 May 2013 12:51:40 +0000 (12:51 +0000)
committerManuel Klimek <klimek@google.com>
Mon, 13 May 2013 12:51:40 +0000 (12:51 +0000)
We now support "Linux" and "Stroustrup" brace breaking styles, which
gets us one step closer to support formatting WebKit, KDE & Linux code.

Linux brace breaking style:
namespace a
{
class A
{
  void f()
  {
    if (x) {
      f();
    } else {
      g();
    }
  }
}
}

Stroustrup brace breaking style:
namespace a {
class A {
  void f()
  {
    if (x) {
      f();
    } else {
      g();
    }
  }
}
}

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181700 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Format/Format.h
lib/Format/Format.cpp
lib/Format/UnwrappedLineParser.cpp
unittests/Format/FormatTest.cpp

index 79e26d0a0c6aa13be823024992b8b9c4b20df2b2..47b5bb69073ca487a64ae8e57f37be853fdf8205 100644 (file)
@@ -101,6 +101,20 @@ struct FormatStyle {
   /// tab characters.
   bool UseTab;
 
+  /// \brief Different ways to attach braces to their surrounding context.
+  enum BraceBreakingStyle {
+    /// Always attach braces to surrounding context.
+    BS_Attach,
+    /// Like \c Attach, but break before braces on function, namespace and
+    /// class definitions.
+    BS_Linux,
+    /// Like \c Attach, but break before function definitions.
+    BS_Stroustrup
+  };
+
+  /// \brief The brace breaking style to use.
+  BraceBreakingStyle BreakBeforeBraces;
+
   bool operator==(const FormatStyle &R) const {
     return AccessModifierOffset == R.AccessModifierOffset &&
            AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft &&
@@ -122,7 +136,8 @@ struct FormatStyle {
            SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
            Standard == R.Standard &&
            IndentWidth == R.IndentWidth &&
-           UseTab == R.UseTab;
+           UseTab == R.UseTab &&
+           BreakBeforeBraces == R.BreakBeforeBraces;
   }
 
 };
index a62fa379ab1f8f925b6961b920d8a3db4aa456d7..b8c40cf2633c2089117903ed388df60cbe37d7ef 100644 (file)
@@ -36,11 +36,21 @@ namespace llvm {
 namespace yaml {
 template <>
 struct ScalarEnumerationTraits<clang::format::FormatStyle::LanguageStandard> {
-  static void enumeration(IO &io,
-                          clang::format::FormatStyle::LanguageStandard &value) {
-    io.enumCase(value, "C++03", clang::format::FormatStyle::LS_Cpp03);
-    io.enumCase(value, "C++11", clang::format::FormatStyle::LS_Cpp11);
-    io.enumCase(value, "Auto", clang::format::FormatStyle::LS_Auto);
+  static void enumeration(IO &IO,
+                          clang::format::FormatStyle::LanguageStandard &Value) {
+    IO.enumCase(Value, "C++03", clang::format::FormatStyle::LS_Cpp03);
+    IO.enumCase(Value, "C++11", clang::format::FormatStyle::LS_Cpp11);
+    IO.enumCase(Value, "Auto", clang::format::FormatStyle::LS_Auto);
+  }
+};
+
+template<>
+struct ScalarEnumerationTraits<clang::format::FormatStyle::BraceBreakingStyle> {
+  static void
+  enumeration(IO &IO, clang::format::FormatStyle::BraceBreakingStyle &Value) {
+    IO.enumCase(Value, "Attach", clang::format::FormatStyle::BS_Attach);
+    IO.enumCase(Value, "Linux", clang::format::FormatStyle::BS_Linux);
+    IO.enumCase(Value, "Stroustrup", clang::format::FormatStyle::BS_Stroustrup);
   }
 };
 
@@ -87,6 +97,7 @@ template <> struct MappingTraits<clang::format::FormatStyle> {
     IO.mapOptional("Standard", Style.Standard);
     IO.mapOptional("IndentWidth", Style.IndentWidth);
     IO.mapOptional("UseTab", Style.UseTab);
+    IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
   }
 };
 }
@@ -115,6 +126,7 @@ FormatStyle getLLVMStyle() {
   LLVMStyle.Standard = FormatStyle::LS_Cpp03;
   LLVMStyle.IndentWidth = 2;
   LLVMStyle.UseTab = false;
+  LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
   return LLVMStyle;
 }
 
@@ -138,6 +150,7 @@ FormatStyle getGoogleStyle() {
   GoogleStyle.Standard = FormatStyle::LS_Auto;
   GoogleStyle.IndentWidth = 2;
   GoogleStyle.UseTab = false;
+  GoogleStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
   return GoogleStyle;
 }
 
index 722af5d2b7630874a8b67b551cc6f1d1aabb8e3b..a08790d80dcaf623d43325f2c4020bcc114b60f4 100644 (file)
@@ -402,6 +402,10 @@ void UnwrappedLineParser::parseStructuralElement() {
       // structural element.
       // FIXME: Figure out cases where this is not true, and add projections for
       // them (the one we know is missing are lambdas).
+      if (Style.BreakBeforeBraces == FormatStyle::BS_Linux ||
+          Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup)
+        addUnwrappedLine();
+
       parseBlock(/*MustBeDeclaration=*/ false);
       addUnwrappedLine();
       return;
@@ -577,6 +581,9 @@ void UnwrappedLineParser::parseNamespace() {
   if (FormatTok.Tok.is(tok::identifier))
     nextToken();
   if (FormatTok.Tok.is(tok::l_brace)) {
+    if (Style.BreakBeforeBraces == FormatStyle::BS_Linux)
+      addUnwrappedLine();
+
     parseBlock(/*MustBeDeclaration=*/ true, 0);
     // Munch the semicolon after a namespace. This is more common than one would
     // think. Puttin the semicolon into its own line is very ugly.
@@ -751,8 +758,12 @@ void UnwrappedLineParser::parseRecord() {
       }
     }
   }
-  if (FormatTok.Tok.is(tok::l_brace))
+  if (FormatTok.Tok.is(tok::l_brace)) {
+    if (Style.BreakBeforeBraces == FormatStyle::BS_Linux)
+      addUnwrappedLine();
+
     parseBlock(/*MustBeDeclaration=*/ true);
+  }
   // We fall through to parsing a structural element afterwards, so
   // class A {} n, m;
   // will end up in one unwrapped line.
index ce79a1c97b99c407c99669810a18026de4338bb5..9624ac92240a445355268d975068e8409cb39c69 100644 (file)
@@ -4037,6 +4037,42 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
                Tab);
 }
 
+TEST_F(FormatTest, LinuxBraceBreaking) {
+  FormatStyle BreakBeforeBrace = getLLVMStyle();
+  BreakBeforeBrace.BreakBeforeBraces = FormatStyle::BS_Linux;
+  verifyFormat("namespace a\n"
+               "{\n"
+               "class A\n"
+               "{\n"
+               "  void f()\n"
+               "  {\n"
+               "    if (true) {\n"
+               "      a();\n"
+               "      b();\n"
+               "    }\n"
+               "  }\n"
+               "}\n"
+               "}",
+               BreakBeforeBrace);
+}
+
+TEST_F(FormatTest, StroustrupBraceBreaking) {
+  FormatStyle BreakBeforeBrace = getLLVMStyle();
+  BreakBeforeBrace.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
+  verifyFormat("namespace a {\n"
+               "class A {\n"
+               "  void f()\n"
+               "  {\n"
+               "    if (true) {\n"
+               "      a();\n"
+               "      b();\n"
+               "    }\n"
+               "  }\n"
+               "}\n"
+               "}",
+               BreakBeforeBrace);
+}
+
 bool allStylesEqual(ArrayRef<FormatStyle> Styles) {
   for (size_t i = 1; i < Styles.size(); ++i)
     if (!(Styles[0] == Styles[i]))
@@ -4113,6 +4149,14 @@ TEST_F(FormatTest, ParsesConfiguration) {
   CHECK_PARSE("BasedOnStyle: LLVM", ColumnLimit, BaseStyle.ColumnLimit);
   CHECK_PARSE("BasedOnStyle: LLVM\nColumnLimit: 1234", ColumnLimit, 1234u);
 
+  Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
+  CHECK_PARSE("BreakBeforeBraces: Attach", BreakBeforeBraces,
+              FormatStyle::BS_Attach);
+  CHECK_PARSE("BreakBeforeBraces: Linux", BreakBeforeBraces,
+              FormatStyle::BS_Linux);
+  CHECK_PARSE("BreakBeforeBraces: Stroustrup", BreakBeforeBraces,
+              FormatStyle::BS_Stroustrup);
+
 #undef CHECK_PARSE
 #undef CHECK_PARSE_BOOL
 }