r196901 - Support GNU style rule to put a space before opening parenthesis.

Alexander Kornienko alexfh at google.com
Tue Dec 10 02:18:34 PST 2013


Author: alexfh
Date: Tue Dec 10 04:18:34 2013
New Revision: 196901

URL: http://llvm.org/viewvc/llvm-project?rev=196901&view=rev
Log:
Support GNU style rule to put a space before opening parenthesis.

Summary:
The rule from the GNU style states:
"We find it easier to read a program when it has spaces before the open-parentheses and after the commas."

http://www.gnu.org/prep/standards/standards.html#index-spaces-before-open_002dparen

This patch makes clang-format adds an option to put spaces before almost all open parentheses, except the cases, where different behavior is dictated by the style rules or language syntax:
  * preprocessor:
    ** function-like macro definitions can't have a space between the macro name and the parenthesis;
    ** `#if defined(...)` can have a space, but it seems, that it's more frequently used without a space in GCC, for example;
  * never add spaces after unary operators;
  * adding spaces between two opening parentheses is controlled with the `SpacesInParentheses` option;
  * never add spaces between `[` and `(` (there's no option yet).

Reviewers: djasper

Reviewed By: djasper

CC: cfe-commits, klimek

Differential Revision: http://llvm-reviews.chandlerc.com/D2326

Modified:
    cfe/trunk/docs/ClangFormatStyleOptions.rst
    cfe/trunk/include/clang/Format/Format.h
    cfe/trunk/lib/Format/Format.cpp
    cfe/trunk/lib/Format/TokenAnnotator.cpp
    cfe/trunk/unittests/Format/FormatTest.cpp

Modified: cfe/trunk/docs/ClangFormatStyleOptions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ClangFormatStyleOptions.rst?rev=196901&r1=196900&r2=196901&view=diff
==============================================================================
--- cfe/trunk/docs/ClangFormatStyleOptions.rst (original)
+++ cfe/trunk/docs/ClangFormatStyleOptions.rst Tue Dec 10 04:18:34 2013
@@ -106,6 +106,10 @@ the configuration (without a prefix: ``A
   Allow putting all parameters of a function declaration onto
   the next line even if ``BinPackParameters`` is ``false``.
 
+**AllowShortFunctionsOnASingleLine** (``bool``)
+  If ``true``, ``int f() { return 0; }`` can be put on a single
+  line.
+
 **AllowShortIfStatementsOnASingleLine** (``bool``)
   If ``true``, ``if (a) return;`` can be put on a single
   line.
@@ -144,6 +148,9 @@ the configuration (without a prefix: ``A
     Always break before braces.
 
 
+**BreakBeforeTernaryOperators** (``bool``)
+  If ``true``, ternary operators will be placed after line breaks.
+
 **BreakConstructorInitializersBeforeComma** (``bool``)
   Always break constructor initializers before commas and align
   the commas with the colon.
@@ -153,7 +160,7 @@ the configuration (without a prefix: ``A
 
   A column limit of ``0`` means that there is no column limit. In this case,
   clang-format will respect the input's line breaking decisions within
-  statements.
+  statements unless they contradict other rules.
 
 **ConstructorInitializerAllOnOneLineOrOnePerLine** (``bool``)
   If the constructor initializers don't fit on a line, put each
@@ -163,6 +170,9 @@ the configuration (without a prefix: ``A
   The number of characters to use for indentation of constructor
   initializer lists.
 
+**ContinuationIndentWidth** (``unsigned``)
+  Indent width for line continuations.
+
 **Cpp11BracedListStyle** (``bool``)
   If ``true``, format braced lists as best suited for C++11 braced
   lists.
@@ -206,6 +216,19 @@ the configuration (without a prefix: ``A
 **IndentWidth** (``unsigned``)
   The number of columns to use for indentation.
 
+**Language** (``LanguageKind``)
+  Language, this format style is targeted at.
+
+  Possible values:
+
+  * ``LK_None`` (in configuration: ``None``)
+    Do not use.
+  * ``LK_Cpp`` (in configuration: ``Cpp``)
+    Should be used for C, C++, ObjectiveC, ObjectiveC++.
+  * ``LK_JavaScript`` (in configuration: ``JavaScript``)
+    Should be used for JavaScript.
+
+
 **MaxEmptyLinesToKeep** (``unsigned``)
   The maximum number of consecutive empty lines to keep.
 
@@ -226,6 +249,9 @@ the configuration (without a prefix: ``A
   Add a space in front of an Objective-C protocol list, i.e. use
   ``Foo <Protocol>`` instead of ``Foo<Protocol>``.
 
+**PenaltyBreakBeforeFirstCallParameter** (``unsigned``)
+  The penalty for breaking a function call after "call(".
+
 **PenaltyBreakComment** (``unsigned``)
   The penalty for each line break introduced inside a comment.
 
@@ -245,25 +271,41 @@ the configuration (without a prefix: ``A
 **PointerBindsToType** (``bool``)
   Set whether & and * bind to the type as opposed to the variable.
 
-**SpaceAfterControlStatementKeyword** (``bool``)
-  If ``true``, spaces will be inserted between 'for'/'if'/'while'/...
-  and '('.
-
 **SpaceBeforeAssignmentOperators** (``bool``)
   If ``false``, spaces will be removed before assignment operators.
 
+**SpaceBeforeParens** (``SpaceBeforeParensOptions``)
+  Defines in which cases to put a space before opening parentheses.
+
+  Possible values:
+
+  * ``SBPO_Never`` (in configuration: ``Never``)
+    Never put a space before opening parentheses.
+  * ``SBPO_ControlStatements`` (in configuration: ``ControlStatements``)
+    Put a space before opening parentheses only after control statement
+    keywords (``for/if/while...``).
+  * ``SBPO_Always`` (in configuration: ``Always``)
+    Always put a space before opening parentheses, except when it's
+    prohibited by the syntax rules (in function-like macro definitions) or
+    when determined by other style rules (after unary operators, opening
+    parentheses, etc.)
+
+
 **SpaceInEmptyParentheses** (``bool``)
   If ``false``, spaces may be inserted into '()'.
 
 **SpacesBeforeTrailingComments** (``unsigned``)
   The number of spaces to before trailing line comments.
 
+**SpacesInAngles** (``bool``)
+  If ``true``, spaces will be inserted after '<' and before '>' in
+  template argument lists
+
 **SpacesInCStyleCastParentheses** (``bool``)
   If ``false``, spaces may be inserted into C style casts.
 
 **SpacesInParentheses** (``bool``)
-  If ``true``, spaces will be inserted after every '(' and before
-  every ')'.
+  If ``true``, spaces will be inserted after '(' and before ')'.
 
 **Standard** (``LanguageStandard``)
   Format compatible with this standard, e.g. use

Modified: cfe/trunk/include/clang/Format/Format.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=196901&r1=196900&r2=196901&view=diff
==============================================================================
--- cfe/trunk/include/clang/Format/Format.h (original)
+++ cfe/trunk/include/clang/Format/Format.h Tue Dec 10 04:18:34 2013
@@ -256,9 +256,22 @@ struct FormatStyle {
   /// \brief If \c false, spaces may be inserted into C style casts.
   bool SpacesInCStyleCastParentheses;
 
-  /// \brief If \c true, spaces will be inserted between 'for'/'if'/'while'/...
-  /// and '('.
-  bool SpaceAfterControlStatementKeyword;
+  /// \brief Different ways to put a space before opening parentheses.
+  enum SpaceBeforeParensOptions {
+    /// Never put a space before opening parentheses.
+    SBPO_Never,
+    /// Put a space before opening parentheses only after control statement
+    /// keywords (<tt>for/if/while...</tt>).
+    SBPO_ControlStatements,
+    /// Always put a space before opening parentheses, except when it's
+    /// prohibited by the syntax rules (in function-like macro definitions) or
+    /// when determined by other style rules (after unary operators, opening
+    /// parentheses, etc.)
+    SBPO_Always
+  };
+
+  /// \brief Defines in which cases to put a space before opening parentheses.
+  SpaceBeforeParensOptions SpaceBeforeParens;
 
   /// \brief If \c false, spaces will be removed before assignment operators.
   bool SpaceBeforeAssignmentOperators;
@@ -315,8 +328,7 @@ struct FormatStyle {
            SpacesInAngles == R.SpacesInAngles &&
            SpaceInEmptyParentheses == R.SpaceInEmptyParentheses &&
            SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses &&
-           SpaceAfterControlStatementKeyword ==
-               R.SpaceAfterControlStatementKeyword &&
+           SpaceBeforeParens == R.SpaceBeforeParens &&
            SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators &&
            ContinuationIndentWidth == R.ContinuationIndentWidth;
   }

Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=196901&r1=196900&r2=196901&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Tue Dec 10 04:18:34 2013
@@ -90,6 +90,24 @@ struct ScalarEnumerationTraits<
   }
 };
 
+template <>
+struct ScalarEnumerationTraits<
+    clang::format::FormatStyle::SpaceBeforeParensOptions> {
+  static void
+  enumeration(IO &IO,
+              clang::format::FormatStyle::SpaceBeforeParensOptions &Value) {
+    IO.enumCase(Value, "Never", clang::format::FormatStyle::SBPO_Never);
+    IO.enumCase(Value, "ControlStatements",
+                clang::format::FormatStyle::SBPO_ControlStatements);
+    IO.enumCase(Value, "Always", clang::format::FormatStyle::SBPO_Always);
+
+    // For backward compatibility.
+    IO.enumCase(Value, "false", clang::format::FormatStyle::SBPO_Never);
+    IO.enumCase(Value, "true",
+                clang::format::FormatStyle::SBPO_ControlStatements);
+  }
+};
+
 template <> struct MappingTraits<clang::format::FormatStyle> {
   static void mapping(llvm::yaml::IO &IO, clang::format::FormatStyle &Style) {
     if (IO.outputting()) {
@@ -179,11 +197,16 @@ template <> struct MappingTraits<clang::
     IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
     IO.mapOptional("SpacesInCStyleCastParentheses",
                    Style.SpacesInCStyleCastParentheses);
-    IO.mapOptional("SpaceAfterControlStatementKeyword",
-                   Style.SpaceAfterControlStatementKeyword);
     IO.mapOptional("SpaceBeforeAssignmentOperators",
                    Style.SpaceBeforeAssignmentOperators);
     IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
+
+    // For backward compatibility.
+    if (!IO.outputting()) {
+      IO.mapOptional("SpaceAfterControlStatementKeyword",
+                     Style.SpaceBeforeParens);
+    }
+    IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
   }
 };
 
@@ -266,7 +289,7 @@ FormatStyle getLLVMStyle() {
   LLVMStyle.SpacesInParentheses = false;
   LLVMStyle.SpaceInEmptyParentheses = false;
   LLVMStyle.SpacesInCStyleCastParentheses = false;
-  LLVMStyle.SpaceAfterControlStatementKeyword = true;
+  LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
   LLVMStyle.SpaceBeforeAssignmentOperators = true;
   LLVMStyle.ContinuationIndentWidth = 4;
   LLVMStyle.SpacesInAngles = false;
@@ -315,7 +338,7 @@ FormatStyle getGoogleStyle() {
   GoogleStyle.SpacesInParentheses = false;
   GoogleStyle.SpaceInEmptyParentheses = false;
   GoogleStyle.SpacesInCStyleCastParentheses = false;
-  GoogleStyle.SpaceAfterControlStatementKeyword = true;
+  GoogleStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
   GoogleStyle.SpaceBeforeAssignmentOperators = true;
   GoogleStyle.ContinuationIndentWidth = 4;
   GoogleStyle.SpacesInAngles = false;

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=196901&r1=196900&r2=196901&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Dec 10 04:18:34 2013
@@ -1293,9 +1293,12 @@ bool TokenAnnotator::spaceRequiredBetwee
     return Line.Type == LT_ObjCDecl ||
            Left.isOneOf(tok::kw_return, tok::kw_new, tok::kw_delete,
                         tok::semi) ||
-           (Style.SpaceAfterControlStatementKeyword &&
+           (Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
             Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,
-                         tok::kw_catch));
+                         tok::kw_catch)) ||
+           (Style.SpaceBeforeParens == FormatStyle::SBPO_Always &&
+            Left.isOneOf(tok::identifier, tok::kw___attribute) &&
+            Line.Type != LT_PreprocessorDirective);
   }
   if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
     return false;

Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=196901&r1=196900&r2=196901&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Tue Dec 10 04:18:34 2013
@@ -2082,7 +2082,8 @@ TEST_F(FormatTest, HashInMacroDefinition
 }
 
 TEST_F(FormatTest, RespectWhitespaceInMacroDefinitions) {
-  verifyFormat("#define A (1)");
+  EXPECT_EQ("#define A (x)", format("#define A (x)"));
+  EXPECT_EQ("#define A(x)", format("#define A(x)"));
 }
 
 TEST_F(FormatTest, EmptyLinesInMacroDefinitions) {
@@ -6660,9 +6661,9 @@ TEST_F(FormatTest, CalculatesOriginalCol
                    getLLVMStyle()));
 }
 
-TEST_F(FormatTest, ConfigurableSpaceAfterControlStatementKeyword) {
+TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
   FormatStyle NoSpace = getLLVMStyle();
-  NoSpace.SpaceAfterControlStatementKeyword = false;
+  NoSpace.SpaceBeforeParens = FormatStyle::SBPO_Never;
 
   verifyFormat("while(true)\n"
                "  continue;", NoSpace);
@@ -6679,6 +6680,42 @@ TEST_F(FormatTest, ConfigurableSpaceAfte
                "default:\n"
                "  break;\n"
                "}", NoSpace);
+
+  FormatStyle Space = getLLVMStyle();
+  Space.SpaceBeforeParens = FormatStyle::SBPO_Always;
+
+  verifyFormat("int f ();", Space);
+  verifyFormat("void f (int a, T b) {\n"
+               "  while (true)\n"
+               "    continue;\n"
+               "}",
+               Space);
+  verifyFormat("if (true)\n"
+               "  f ();\n"
+               "else if (true)\n"
+               "  f ();",
+               Space);
+  verifyFormat("do {\n"
+               "  do_something ();\n"
+               "} while (something ());",
+               Space);
+  verifyFormat("switch (x) {\n"
+               "default:\n"
+               "  break;\n"
+               "}",
+               Space);
+  verifyFormat("A::A () : a (1) {}", Space);
+  verifyFormat("void f () __attribute__ ((asdf));", Space);
+  verifyFormat("*(&a + 1);\n"
+               "&((&a)[1]);\n"
+               "a[(b + c) * d];\n"
+               "(((a + 1) * 2) + 3) * 4;",
+               Space);
+  verifyFormat("#define A(x) x", Space);
+  verifyFormat("#define A (x) x", Space);
+  verifyFormat("#if defined(x)\n"
+               "#endif",
+               Space);
 }
 
 TEST_F(FormatTest, ConfigurableSpacesInParentheses) {
@@ -6988,7 +7025,6 @@ TEST_F(FormatTest, ParsesConfiguration)
   CHECK_PARSE_BOOL(SpacesInAngles);
   CHECK_PARSE_BOOL(SpaceInEmptyParentheses);
   CHECK_PARSE_BOOL(SpacesInCStyleCastParentheses);
-  CHECK_PARSE_BOOL(SpaceAfterControlStatementKeyword);
   CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators);
 
   CHECK_PARSE("AccessModifierOffset: -1234", AccessModifierOffset, -1234);
@@ -7020,6 +7056,19 @@ TEST_F(FormatTest, ParsesConfiguration)
   CHECK_PARSE("UseTab: ForIndentation", UseTab, FormatStyle::UT_ForIndentation);
   CHECK_PARSE("UseTab: Always", UseTab, FormatStyle::UT_Always);
 
+  Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
+  CHECK_PARSE("SpaceBeforeParens: Never", SpaceBeforeParens,
+              FormatStyle::SBPO_Never);
+  CHECK_PARSE("SpaceBeforeParens: Always", SpaceBeforeParens,
+              FormatStyle::SBPO_Always);
+  CHECK_PARSE("SpaceBeforeParens: ControlStatements", SpaceBeforeParens,
+              FormatStyle::SBPO_ControlStatements);
+  // For backward compatibility:
+  CHECK_PARSE("SpaceAfterControlStatementKeyword: false", SpaceBeforeParens,
+              FormatStyle::SBPO_Never);
+  CHECK_PARSE("SpaceAfterControlStatementKeyword: true", SpaceBeforeParens,
+              FormatStyle::SBPO_ControlStatements);
+
   Style.ColumnLimit = 123;
   FormatStyle BaseStyle = getLLVMStyle();
   CHECK_PARSE("BasedOnStyle: LLVM", ColumnLimit, BaseStyle.ColumnLimit);





More information about the cfe-commits mailing list