forked from OSchip/llvm-project
[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
This commit is contained in:
parent
c4ac74fb49
commit
08a940d629
|
@ -1690,6 +1690,17 @@ struct FormatStyle {
|
|||
/// }
|
||||
/// \endcode
|
||||
SBPO_ControlStatements,
|
||||
/// Put a space before opening parentheses only if the parentheses are not
|
||||
/// empty i.e. '()'
|
||||
/// \code
|
||||
/// void() {
|
||||
/// if (true) {
|
||||
/// f();
|
||||
/// g (x, y, z);
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
SBPO_NonEmptyParentheses,
|
||||
/// 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
|
||||
|
|
|
@ -285,6 +285,8 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
|
|||
IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
|
||||
IO.enumCase(Value, "ControlStatements",
|
||||
FormatStyle::SBPO_ControlStatements);
|
||||
IO.enumCase(Value, "NonEmptyParentheses",
|
||||
FormatStyle::SBPO_NonEmptyParentheses);
|
||||
IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
|
||||
|
||||
// For backward compatibility.
|
||||
|
|
|
@ -2453,6 +2453,12 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
|
|||
return 3;
|
||||
}
|
||||
|
||||
bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const {
|
||||
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always ||
|
||||
(Style.SpaceBeforeParens == FormatStyle::SBPO_NonEmptyParentheses &&
|
||||
Right.ParameterCount > 0);
|
||||
}
|
||||
|
||||
bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
|
||||
const FormatToken &Left,
|
||||
const FormatToken &Right) {
|
||||
|
@ -2599,9 +2605,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
|
|||
(Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch,
|
||||
tok::kw_new, tok::kw_delete) &&
|
||||
(!Left.Previous || Left.Previous->isNot(tok::period))))) ||
|
||||
(Style.SpaceBeforeParens == FormatStyle::SBPO_Always &&
|
||||
(spaceRequiredBeforeParens(Right) &&
|
||||
(Left.is(tok::identifier) || Left.isFunctionLikeKeyword() ||
|
||||
Left.is(tok::r_paren) ||
|
||||
Left.is(tok::r_paren) || Left.isSimpleTypeSpecifier() ||
|
||||
(Left.is(tok::r_square) && Left.MatchingParen &&
|
||||
Left.MatchingParen->is(TT_LambdaLSquare))) &&
|
||||
Line.Type != LT_PreprocessorDirective);
|
||||
|
@ -2795,7 +2801,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
|||
Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
|
||||
return true;
|
||||
if (Right.is(TT_OverloadedOperatorLParen))
|
||||
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
|
||||
return spaceRequiredBeforeParens(Right);
|
||||
if (Left.is(tok::comma))
|
||||
return true;
|
||||
if (Right.is(tok::comma))
|
||||
|
@ -2879,7 +2885,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
|||
return true;
|
||||
if (Left.is(TT_TemplateCloser) && Right.is(tok::l_paren) &&
|
||||
Right.isNot(TT_FunctionTypeLParen))
|
||||
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
|
||||
return spaceRequiredBeforeParens(Right);
|
||||
if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&
|
||||
Left.MatchingParen && Left.MatchingParen->is(TT_OverloadedOperatorLParen))
|
||||
return false;
|
||||
|
|
|
@ -164,6 +164,8 @@ private:
|
|||
unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
|
||||
bool InFunctionDecl);
|
||||
|
||||
bool spaceRequiredBeforeParens(const FormatToken &Right) const;
|
||||
|
||||
bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
|
||||
const FormatToken &Right);
|
||||
|
||||
|
|
|
@ -9627,6 +9627,60 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
|
|||
verifyFormat("T A::operator() ();", Space);
|
||||
verifyFormat("X A::operator++ (T);", Space);
|
||||
verifyFormat("auto lambda = [] () { return 0; };", Space);
|
||||
verifyFormat("int x = int (y);", Space);
|
||||
|
||||
FormatStyle SomeSpace = getLLVMStyle();
|
||||
SomeSpace.SpaceBeforeParens = FormatStyle::SBPO_NonEmptyParentheses;
|
||||
|
||||
verifyFormat("[]() -> float {}", SomeSpace);
|
||||
verifyFormat("[] (auto foo) {}", SomeSpace);
|
||||
verifyFormat("[foo]() -> int {}", SomeSpace);
|
||||
verifyFormat("int f();", SomeSpace);
|
||||
verifyFormat("void f (int a, T b) {\n"
|
||||
" while (true)\n"
|
||||
" continue;\n"
|
||||
"}",
|
||||
SomeSpace);
|
||||
verifyFormat("if (true)\n"
|
||||
" f();\n"
|
||||
"else if (true)\n"
|
||||
" f();",
|
||||
SomeSpace);
|
||||
verifyFormat("do {\n"
|
||||
" do_something();\n"
|
||||
"} while (something());",
|
||||
SomeSpace);
|
||||
verifyFormat("switch (x) {\n"
|
||||
"default:\n"
|
||||
" break;\n"
|
||||
"}",
|
||||
SomeSpace);
|
||||
verifyFormat("A::A() : a (1) {}", SomeSpace);
|
||||
verifyFormat("void f() __attribute__ ((asdf));", SomeSpace);
|
||||
verifyFormat("*(&a + 1);\n"
|
||||
"&((&a)[1]);\n"
|
||||
"a[(b + c) * d];\n"
|
||||
"(((a + 1) * 2) + 3) * 4;",
|
||||
SomeSpace);
|
||||
verifyFormat("#define A(x) x", SomeSpace);
|
||||
verifyFormat("#define A (x) x", SomeSpace);
|
||||
verifyFormat("#if defined(x)\n"
|
||||
"#endif",
|
||||
SomeSpace);
|
||||
verifyFormat("auto i = std::make_unique<int> (5);", SomeSpace);
|
||||
verifyFormat("size_t x = sizeof (x);", SomeSpace);
|
||||
verifyFormat("auto f (int x) -> decltype (x);", SomeSpace);
|
||||
verifyFormat("int f (T x) noexcept (x.create());", SomeSpace);
|
||||
verifyFormat("alignas (128) char a[128];", SomeSpace);
|
||||
verifyFormat("size_t x = alignof (MyType);", SomeSpace);
|
||||
verifyFormat("static_assert (sizeof (char) == 1, \"Impossible!\");",
|
||||
SomeSpace);
|
||||
verifyFormat("int f() throw (Deprecated);", SomeSpace);
|
||||
verifyFormat("typedef void (*cb) (int);", SomeSpace);
|
||||
verifyFormat("T A::operator()();", SomeSpace);
|
||||
verifyFormat("X A::operator++ (T);", SomeSpace);
|
||||
verifyFormat("int x = int (y);", SomeSpace);
|
||||
verifyFormat("auto lambda = []() { return 0; };", SomeSpace);
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, ConfigurableSpacesInParentheses) {
|
||||
|
@ -11413,6 +11467,8 @@ TEST_F(FormatTest, ParsesConfiguration) {
|
|||
FormatStyle::SBPO_Always);
|
||||
CHECK_PARSE("SpaceBeforeParens: ControlStatements", SpaceBeforeParens,
|
||||
FormatStyle::SBPO_ControlStatements);
|
||||
CHECK_PARSE("SpaceBeforeParens: NonEmptyParentheses", SpaceBeforeParens,
|
||||
FormatStyle::SBPO_NonEmptyParentheses);
|
||||
// For backward compatibility:
|
||||
CHECK_PARSE("SpaceAfterControlStatementKeyword: false", SpaceBeforeParens,
|
||||
FormatStyle::SBPO_Never);
|
||||
|
|
Loading…
Reference in New Issue