Skip to content

Commit 08a940d

Browse files
committed
[clang-format]: Add NonEmptyParentheses spacing option
This patch aims to add support for the following rules from the JUCE coding standards: - Always put a space before an open parenthesis that contains text - e.g. foo (123); - Never put a space before an empty pair of open/close parenthesis - e.g. foo(); Patch by Reuben Thomas Differential Revision: https://reviews.llvm.org/D55170 llvm-svn: 357344
1 parent c4ac74f commit 08a940d

File tree

5 files changed

+81
-4
lines changed

5 files changed

+81
-4
lines changed

clang/include/clang/Format/Format.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,6 +1690,17 @@ struct FormatStyle {
16901690
/// }
16911691
/// \endcode
16921692
SBPO_ControlStatements,
1693+
/// Put a space before opening parentheses only if the parentheses are not
1694+
/// empty i.e. '()'
1695+
/// \code
1696+
/// void() {
1697+
/// if (true) {
1698+
/// f();
1699+
/// g (x, y, z);
1700+
/// }
1701+
/// }
1702+
/// \endcode
1703+
SBPO_NonEmptyParentheses,
16931704
/// Always put a space before opening parentheses, except when it's
16941705
/// prohibited by the syntax rules (in function-like macro definitions) or
16951706
/// when determined by other style rules (after unary operators, opening

clang/lib/Format/Format.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
285285
IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
286286
IO.enumCase(Value, "ControlStatements",
287287
FormatStyle::SBPO_ControlStatements);
288+
IO.enumCase(Value, "NonEmptyParentheses",
289+
FormatStyle::SBPO_NonEmptyParentheses);
288290
IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
289291

290292
// For backward compatibility.

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,6 +2453,12 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
24532453
return 3;
24542454
}
24552455

2456+
bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const {
2457+
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always ||
2458+
(Style.SpaceBeforeParens == FormatStyle::SBPO_NonEmptyParentheses &&
2459+
Right.ParameterCount > 0);
2460+
}
2461+
24562462
bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
24572463
const FormatToken &Left,
24582464
const FormatToken &Right) {
@@ -2599,9 +2605,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
25992605
(Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch,
26002606
tok::kw_new, tok::kw_delete) &&
26012607
(!Left.Previous || Left.Previous->isNot(tok::period))))) ||
2602-
(Style.SpaceBeforeParens == FormatStyle::SBPO_Always &&
2608+
(spaceRequiredBeforeParens(Right) &&
26032609
(Left.is(tok::identifier) || Left.isFunctionLikeKeyword() ||
2604-
Left.is(tok::r_paren) ||
2610+
Left.is(tok::r_paren) || Left.isSimpleTypeSpecifier() ||
26052611
(Left.is(tok::r_square) && Left.MatchingParen &&
26062612
Left.MatchingParen->is(TT_LambdaLSquare))) &&
26072613
Line.Type != LT_PreprocessorDirective);
@@ -2795,7 +2801,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
27952801
Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
27962802
return true;
27972803
if (Right.is(TT_OverloadedOperatorLParen))
2798-
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
2804+
return spaceRequiredBeforeParens(Right);
27992805
if (Left.is(tok::comma))
28002806
return true;
28012807
if (Right.is(tok::comma))
@@ -2879,7 +2885,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
28792885
return true;
28802886
if (Left.is(TT_TemplateCloser) && Right.is(tok::l_paren) &&
28812887
Right.isNot(TT_FunctionTypeLParen))
2882-
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
2888+
return spaceRequiredBeforeParens(Right);
28832889
if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&
28842890
Left.MatchingParen && Left.MatchingParen->is(TT_OverloadedOperatorLParen))
28852891
return false;

clang/lib/Format/TokenAnnotator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ class TokenAnnotator {
164164
unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
165165
bool InFunctionDecl);
166166

167+
bool spaceRequiredBeforeParens(const FormatToken &Right) const;
168+
167169
bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
168170
const FormatToken &Right);
169171

clang/unittests/Format/FormatTest.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9627,6 +9627,60 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
96279627
verifyFormat("T A::operator() ();", Space);
96289628
verifyFormat("X A::operator++ (T);", Space);
96299629
verifyFormat("auto lambda = [] () { return 0; };", Space);
9630+
verifyFormat("int x = int (y);", Space);
9631+
9632+
FormatStyle SomeSpace = getLLVMStyle();
9633+
SomeSpace.SpaceBeforeParens = FormatStyle::SBPO_NonEmptyParentheses;
9634+
9635+
verifyFormat("[]() -> float {}", SomeSpace);
9636+
verifyFormat("[] (auto foo) {}", SomeSpace);
9637+
verifyFormat("[foo]() -> int {}", SomeSpace);
9638+
verifyFormat("int f();", SomeSpace);
9639+
verifyFormat("void f (int a, T b) {\n"
9640+
" while (true)\n"
9641+
" continue;\n"
9642+
"}",
9643+
SomeSpace);
9644+
verifyFormat("if (true)\n"
9645+
" f();\n"
9646+
"else if (true)\n"
9647+
" f();",
9648+
SomeSpace);
9649+
verifyFormat("do {\n"
9650+
" do_something();\n"
9651+
"} while (something());",
9652+
SomeSpace);
9653+
verifyFormat("switch (x) {\n"
9654+
"default:\n"
9655+
" break;\n"
9656+
"}",
9657+
SomeSpace);
9658+
verifyFormat("A::A() : a (1) {}", SomeSpace);
9659+
verifyFormat("void f() __attribute__ ((asdf));", SomeSpace);
9660+
verifyFormat("*(&a + 1);\n"
9661+
"&((&a)[1]);\n"
9662+
"a[(b + c) * d];\n"
9663+
"(((a + 1) * 2) + 3) * 4;",
9664+
SomeSpace);
9665+
verifyFormat("#define A(x) x", SomeSpace);
9666+
verifyFormat("#define A (x) x", SomeSpace);
9667+
verifyFormat("#if defined(x)\n"
9668+
"#endif",
9669+
SomeSpace);
9670+
verifyFormat("auto i = std::make_unique<int> (5);", SomeSpace);
9671+
verifyFormat("size_t x = sizeof (x);", SomeSpace);
9672+
verifyFormat("auto f (int x) -> decltype (x);", SomeSpace);
9673+
verifyFormat("int f (T x) noexcept (x.create());", SomeSpace);
9674+
verifyFormat("alignas (128) char a[128];", SomeSpace);
9675+
verifyFormat("size_t x = alignof (MyType);", SomeSpace);
9676+
verifyFormat("static_assert (sizeof (char) == 1, \"Impossible!\");",
9677+
SomeSpace);
9678+
verifyFormat("int f() throw (Deprecated);", SomeSpace);
9679+
verifyFormat("typedef void (*cb) (int);", SomeSpace);
9680+
verifyFormat("T A::operator()();", SomeSpace);
9681+
verifyFormat("X A::operator++ (T);", SomeSpace);
9682+
verifyFormat("int x = int (y);", SomeSpace);
9683+
verifyFormat("auto lambda = []() { return 0; };", SomeSpace);
96309684
}
96319685

96329686
TEST_F(FormatTest, ConfigurableSpacesInParentheses) {
@@ -11413,6 +11467,8 @@ TEST_F(FormatTest, ParsesConfiguration) {
1141311467
FormatStyle::SBPO_Always);
1141411468
CHECK_PARSE("SpaceBeforeParens: ControlStatements", SpaceBeforeParens,
1141511469
FormatStyle::SBPO_ControlStatements);
11470+
CHECK_PARSE("SpaceBeforeParens: NonEmptyParentheses", SpaceBeforeParens,
11471+
FormatStyle::SBPO_NonEmptyParentheses);
1141611472
// For backward compatibility:
1141711473
CHECK_PARSE("SpaceAfterControlStatementKeyword: false", SpaceBeforeParens,
1141811474
FormatStyle::SBPO_Never);

0 commit comments

Comments
 (0)