Skip to content

Commit

Permalink
[clang-format] Extend SpaceBeforeParens for requires
Browse files Browse the repository at this point in the history
We can now configure the space between requires and the following paren,
seperate for clauses and expressions.

Differential Revision: https://reviews.llvm.org/D113369
  • Loading branch information
HazardyKnusperkeks committed Feb 15, 2022
1 parent bcd1e46 commit b786a4a
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 3 deletions.
21 changes: 21 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Expand Up @@ -4004,6 +4004,27 @@ the configuration (without a prefix: ``Auto``).
void operator++ (int a); vs. void operator++(int a);
object.operator++ (10); object.operator++(10);

* ``bool AfterRequiresInClause`` If ``true``, put space between requires keyword in a requires clause and
opening parentheses, if there is one.

.. code-block:: c++

true: false:
template<typename T> vs. template<typename T>
requires (A<T> && B<T>) requires(A<T> && B<T>)
... ...

* ``bool AfterRequiresInExpression`` If ``true``, put space between requires keyword in a requires expression
and opening parentheses.

.. code-block:: c++

true: false:
template<typename T> vs. template<typename T>
concept C = requires (T t) { concept C = requires(T t) {
... ...
} }

* ``bool BeforeNonEmptyParentheses`` If ``true``, put a space before opening parentheses only if the
parentheses are not empty.

Expand Down
24 changes: 23 additions & 1 deletion clang/include/clang/Format/Format.h
Expand Up @@ -3594,6 +3594,25 @@ struct FormatStyle {
/// object.operator++ (10); object.operator++(10);
/// \endcode
bool AfterOverloadedOperator;
/// If ``true``, put space between requires keyword in a requires clause and
/// opening parentheses, if there is one.
/// \code
/// true: false:
/// template<typename T> vs. template<typename T>
/// requires (A<T> && B<T>) requires(A<T> && B<T>)
/// ... ...
/// \endcode
bool AfterRequiresInClause;
/// If ``true``, put space between requires keyword in a requires expression
/// and opening parentheses.
/// \code
/// true: false:
/// template<typename T> vs. template<typename T>
/// concept C = requires (T t) { concept C = requires(T t) {
/// ... ...
/// } }
/// \endcode
bool AfterRequiresInExpression;
/// If ``true``, put a space before opening parentheses only if the
/// parentheses are not empty.
/// \code
Expand All @@ -3607,7 +3626,8 @@ struct FormatStyle {
: AfterControlStatements(false), AfterForeachMacros(false),
AfterFunctionDeclarationName(false),
AfterFunctionDefinitionName(false), AfterIfMacros(false),
AfterOverloadedOperator(false), BeforeNonEmptyParentheses(false) {}
AfterOverloadedOperator(false), AfterRequiresInClause(false),
AfterRequiresInExpression(false), BeforeNonEmptyParentheses(false) {}

bool operator==(const SpaceBeforeParensCustom &Other) const {
return AfterControlStatements == Other.AfterControlStatements &&
Expand All @@ -3617,6 +3637,8 @@ struct FormatStyle {
AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName &&
AfterIfMacros == Other.AfterIfMacros &&
AfterOverloadedOperator == Other.AfterOverloadedOperator &&
AfterRequiresInClause == Other.AfterRequiresInClause &&
AfterRequiresInExpression == Other.AfterRequiresInExpression &&
BeforeNonEmptyParentheses == Other.BeforeNonEmptyParentheses;
}
};
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Format/Format.cpp
Expand Up @@ -898,6 +898,9 @@ template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
Spacing.AfterFunctionDeclarationName);
IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
IO.mapOptional("AfterRequiresInExpression",
Spacing.AfterRequiresInExpression);
IO.mapOptional("BeforeNonEmptyParentheses",
Spacing.BeforeNonEmptyParentheses);
}
Expand Down Expand Up @@ -1259,6 +1262,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceBeforeCtorInitializerColon = true;
LLVMStyle.SpaceBeforeInheritanceColon = true;
LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
LLVMStyle.SpaceBeforeParensOptions = {};
LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Format/TokenAnnotator.cpp
Expand Up @@ -3247,8 +3247,12 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Right.is(tok::l_paren)) {
if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen))
return spaceRequiredBeforeParens(Right);
if (Left.is(tok::kw_requires))
return spaceRequiredBeforeParens(Right);
if (Left.isOneOf(TT_RequiresClause, TT_RequiresClauseInARequiresExpression))
return Style.SpaceBeforeParensOptions.AfterRequiresInClause ||
spaceRequiredBeforeParens(Right);
if (Left.is(TT_RequiresExpression))
return Style.SpaceBeforeParensOptions.AfterRequiresInExpression ||
spaceRequiredBeforeParens(Right);
if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
(Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
return true;
Expand Down
78 changes: 78 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Expand Up @@ -15012,6 +15012,84 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
verifyFormat("X A::operator++();", SpaceAfterOverloadedOperator);
verifyFormat("some_object.operator++();", SpaceAfterOverloadedOperator);
verifyFormat("auto func() -> int;", SpaceAfterOverloadedOperator);

auto SpaceAfterRequires = getLLVMStyle();
SpaceAfterRequires.SpaceBeforeParens = FormatStyle::SBPO_Custom;
EXPECT_FALSE(
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause);
EXPECT_FALSE(
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInExpression);
verifyFormat("void f(auto x)\n"
" requires requires(int i) { x + i; }\n"
"{}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
" requires(requires(int i) { x + i; })\n"
"{}",
SpaceAfterRequires);
verifyFormat("if (requires(int i) { x + i; })\n"
" return;",
SpaceAfterRequires);
verifyFormat("bool b = requires(int i) { x + i; };", SpaceAfterRequires);
verifyFormat("template <typename T>\n"
" requires(Foo<T>)\n"
"class Bar;",
SpaceAfterRequires);

SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause = true;
verifyFormat("void f(auto x)\n"
" requires requires(int i) { x + i; }\n"
"{}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
" requires (requires(int i) { x + i; })\n"
"{}",
SpaceAfterRequires);
verifyFormat("if (requires(int i) { x + i; })\n"
" return;",
SpaceAfterRequires);
verifyFormat("bool b = requires(int i) { x + i; };", SpaceAfterRequires);
verifyFormat("template <typename T>\n"
" requires (Foo<T>)\n"
"class Bar;",
SpaceAfterRequires);

SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause = false;
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInExpression = true;
verifyFormat("void f(auto x)\n"
" requires requires (int i) { x + i; }\n"
"{}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
" requires(requires (int i) { x + i; })\n"
"{}",
SpaceAfterRequires);
verifyFormat("if (requires (int i) { x + i; })\n"
" return;",
SpaceAfterRequires);
verifyFormat("bool b = requires (int i) { x + i; };", SpaceAfterRequires);
verifyFormat("template <typename T>\n"
" requires(Foo<T>)\n"
"class Bar;",
SpaceAfterRequires);

SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause = true;
verifyFormat("void f(auto x)\n"
" requires requires (int i) { x + i; }\n"
"{}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
" requires (requires (int i) { x + i; })\n"
"{}",
SpaceAfterRequires);
verifyFormat("if (requires (int i) { x + i; })\n"
" return;",
SpaceAfterRequires);
verifyFormat("bool b = requires (int i) { x + i; };", SpaceAfterRequires);
verifyFormat("template <typename T>\n"
" requires (Foo<T>)\n"
"class Bar;",
SpaceAfterRequires);
}

TEST_F(FormatTest, SpaceAfterLogicalNot) {
Expand Down

0 comments on commit b786a4a

Please sign in to comment.