Skip to content

Commit 6facafe

Browse files
rayroudcHazardyKnusperkeks
authored andcommitted
[clang-format] Refactor SpaceBeforeParens to add options
The coding style of some projects requires to have more control on space before opening parentheses. The goal is to add the support of clang-format to more projects. For example adding a space only for function definitions or declarations. This revision adds SpaceBeforeParensOptions to configure each option independently from one another. Differentiel Revision: https://reviews.llvm.org/D110833
1 parent 6633605 commit 6facafe

File tree

6 files changed

+453
-50
lines changed

6 files changed

+453
-50
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3618,7 +3618,7 @@ the configuration (without a prefix: ``Auto``).
36183618
true: false:
36193619
class Foo : Bar {} vs. class Foo: Bar {}
36203620

3621-
**SpaceBeforeParens** (``SpaceBeforeParensOptions``) :versionbadge:`clang-format 3.5`
3621+
**SpaceBeforeParens** (``SpaceBeforeParensStyle``) :versionbadge:`clang-format 3.5`
36223622
Defines in which cases to put a space before opening parentheses.
36233623

36243624
Possible values:
@@ -3688,6 +3688,78 @@ the configuration (without a prefix: ``Auto``).
36883688
}
36893689
}
36903690

3691+
* ``SBPO_Custom`` (in configuration: ``Custom``)
3692+
Configure each individual space before parentheses in
3693+
`SpaceBeforeParensOptions`.
3694+
3695+
3696+
3697+
**SpaceBeforeParensOptions** (``SpaceBeforeParensCustom``) :versionbadge:`clang-format 14`
3698+
Control of individual space before parentheses.
3699+
3700+
If ``SpaceBeforeParens`` is set to ``Custom``, use this to specify
3701+
how each individual space before parentheses case should be handled.
3702+
Otherwise, this is ignored.
3703+
3704+
.. code-block:: yaml
3705+
3706+
# Example of usage:
3707+
SpaceBeforeParens: Custom
3708+
SpaceBeforeParensOptions:
3709+
AfterControlStatements: true
3710+
AfterFunctionDefinitionName: true
3711+
3712+
Nested configuration flags:
3713+
3714+
3715+
* ``bool AfterControlStatements`` If ``true``, put space betwee control statement keywords
3716+
(for/if/while...) and opening parentheses.
3717+
3718+
.. code-block:: c++
3719+
3720+
true: false:
3721+
if (...) {} vs. if(...) {}
3722+
3723+
* ``bool AfterForeachMacros`` If ``true``, put space between foreach macros and opening parentheses.
3724+
3725+
.. code-block:: c++
3726+
3727+
true: false:
3728+
FOREACH (...) vs. FOREACH(...)
3729+
<loop-body> <loop-body>
3730+
3731+
* ``bool AfterFunctionDeclarationName`` If ``true``, put a space between function declaration name and opening
3732+
parentheses.
3733+
3734+
.. code-block:: c++
3735+
3736+
true: false:
3737+
void f (); vs. void f();
3738+
3739+
* ``bool AfterFunctionDefinitionName`` If ``true``, put a space between function definition name and opening
3740+
parentheses.
3741+
3742+
.. code-block:: c++
3743+
3744+
true: false:
3745+
void f () {} vs. void f() {}
3746+
3747+
* ``bool AfterIfMacros`` If ``true``, put space between if macros and opening parentheses.
3748+
3749+
.. code-block:: c++
3750+
3751+
true: false:
3752+
IF (...) vs. IF(...)
3753+
<conditional-body> <conditional-body>
3754+
3755+
* ``bool BeforeNonEmptyParentheses`` If ``true``, put a space before opening parentheses only if the
3756+
parentheses are not empty.
3757+
3758+
.. code-block:: c++
3759+
3760+
true: false:
3761+
void f (int a); vs. void f();
3762+
f (a); f();
36913763

36923764

36933765
**SpaceBeforeRangeBasedForLoopColon** (``Boolean``) :versionbadge:`clang-format 7`

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@ clang-format
244244
`const` `volatile` `static` `inline` `constexpr` `restrict`
245245
to be controlled relative to the `type`.
246246

247+
- Add a ``Custom`` style to ``SpaceBeforeParens``, to better configure the
248+
space before parentheses. The custom options can be set using
249+
``SpaceBeforeParensOptions``.
250+
247251
libclang
248252
--------
249253

clang/include/clang/Format/Format.h

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3258,7 +3258,7 @@ struct FormatStyle {
32583258
bool SpaceBeforeInheritanceColon;
32593259

32603260
/// Different ways to put a space before opening parentheses.
3261-
enum SpaceBeforeParensOptions : unsigned char {
3261+
enum SpaceBeforeParensStyle : unsigned char {
32623262
/// Never put a space before opening parentheses.
32633263
/// \code
32643264
/// void f() {
@@ -3313,12 +3313,100 @@ struct FormatStyle {
33133313
/// }
33143314
/// }
33153315
/// \endcode
3316-
SBPO_Always
3316+
SBPO_Always,
3317+
/// Configure each individual space before parentheses in
3318+
/// `SpaceBeforeParensOptions`.
3319+
SBPO_Custom,
33173320
};
33183321

33193322
/// Defines in which cases to put a space before opening parentheses.
33203323
/// \version 3.5
3321-
SpaceBeforeParensOptions SpaceBeforeParens;
3324+
SpaceBeforeParensStyle SpaceBeforeParens;
3325+
3326+
/// Precise control over the spacing before parentheses.
3327+
/// \code
3328+
/// # Should be declared this way:
3329+
/// SpaceBeforeParens: Custom
3330+
/// SpaceBeforeParensOptions:
3331+
/// AfterControlStatements: true
3332+
/// AfterFunctionDefinitionName: true
3333+
/// \endcode
3334+
struct SpaceBeforeParensCustom {
3335+
/// If ``true``, put space betwee control statement keywords
3336+
/// (for/if/while...) and opening parentheses.
3337+
/// \code
3338+
/// true: false:
3339+
/// if (...) {} vs. if(...) {}
3340+
/// \endcode
3341+
bool AfterControlStatements;
3342+
/// If ``true``, put space between foreach macros and opening parentheses.
3343+
/// \code
3344+
/// true: false:
3345+
/// FOREACH (...) vs. FOREACH(...)
3346+
/// <loop-body> <loop-body>
3347+
/// \endcode
3348+
bool AfterForeachMacros;
3349+
/// If ``true``, put a space between function declaration name and opening
3350+
/// parentheses.
3351+
/// \code
3352+
/// true: false:
3353+
/// void f (); vs. void f();
3354+
/// \endcode
3355+
bool AfterFunctionDeclarationName;
3356+
/// If ``true``, put a space between function definition name and opening
3357+
/// parentheses.
3358+
/// \code
3359+
/// true: false:
3360+
/// void f () {} vs. void f() {}
3361+
/// \endcode
3362+
bool AfterFunctionDefinitionName;
3363+
/// If ``true``, put space between if macros and opening parentheses.
3364+
/// \code
3365+
/// true: false:
3366+
/// IF (...) vs. IF(...)
3367+
/// <conditional-body> <conditional-body>
3368+
/// \endcode
3369+
bool AfterIfMacros;
3370+
/// If ``true``, put a space before opening parentheses only if the
3371+
/// parentheses are not empty.
3372+
/// \code
3373+
/// true: false:
3374+
/// void f (int a); vs. void f();
3375+
/// f (a); f();
3376+
/// \endcode
3377+
bool BeforeNonEmptyParentheses;
3378+
3379+
SpaceBeforeParensCustom()
3380+
: AfterControlStatements(false), AfterForeachMacros(false),
3381+
AfterFunctionDeclarationName(false),
3382+
AfterFunctionDefinitionName(false), AfterIfMacros(false),
3383+
BeforeNonEmptyParentheses(false) {}
3384+
3385+
bool operator==(const SpaceBeforeParensCustom &Other) const {
3386+
return AfterControlStatements == Other.AfterControlStatements &&
3387+
AfterForeachMacros == Other.AfterForeachMacros &&
3388+
AfterFunctionDeclarationName ==
3389+
Other.AfterFunctionDeclarationName &&
3390+
AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName &&
3391+
AfterIfMacros == Other.AfterIfMacros &&
3392+
BeforeNonEmptyParentheses == Other.BeforeNonEmptyParentheses;
3393+
}
3394+
};
3395+
3396+
/// Control of individual space before parentheses.
3397+
///
3398+
/// If ``SpaceBeforeParens`` is set to ``Custom``, use this to specify
3399+
/// how each individual space before parentheses case should be handled.
3400+
/// Otherwise, this is ignored.
3401+
/// \code{.yaml}
3402+
/// # Example of usage:
3403+
/// SpaceBeforeParens: Custom
3404+
/// SpaceBeforeParensOptions:
3405+
/// AfterControlStatements: true
3406+
/// AfterFunctionDefinitionName: true
3407+
/// \endcode
3408+
/// \version 14
3409+
SpaceBeforeParensCustom SpaceBeforeParensOptions;
33223410

33233411
/// If ``false``, spaces will be removed before range-based for loop
33243412
/// colon.
@@ -3715,6 +3803,7 @@ struct FormatStyle {
37153803
R.SpaceBeforeCtorInitializerColon &&
37163804
SpaceBeforeInheritanceColon == R.SpaceBeforeInheritanceColon &&
37173805
SpaceBeforeParens == R.SpaceBeforeParens &&
3806+
SpaceBeforeParensOptions == R.SpaceBeforeParensOptions &&
37183807
SpaceAroundPointerQualifiers == R.SpaceAroundPointerQualifiers &&
37193808
SpaceBeforeRangeBasedForLoopColon ==
37203809
R.SpaceBeforeRangeBasedForLoopColon &&

clang/lib/Format/Format.cpp

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -451,9 +451,8 @@ struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
451451
};
452452

453453
template <>
454-
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
455-
static void enumeration(IO &IO,
456-
FormatStyle::SpaceBeforeParensOptions &Value) {
454+
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
455+
static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
457456
IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
458457
IO.enumCase(Value, "ControlStatements",
459458
FormatStyle::SBPO_ControlStatements);
@@ -462,6 +461,7 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
462461
IO.enumCase(Value, "NonEmptyParentheses",
463462
FormatStyle::SBPO_NonEmptyParentheses);
464463
IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
464+
IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);
465465

466466
// For backward compatibility.
467467
IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
@@ -787,6 +787,7 @@ template <> struct MappingTraits<FormatStyle> {
787787
IO.mapOptional("SpaceBeforeInheritanceColon",
788788
Style.SpaceBeforeInheritanceColon);
789789
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
790+
IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
790791
IO.mapOptional("SpaceAroundPointerQualifiers",
791792
Style.SpaceAroundPointerQualifiers);
792793
IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
@@ -845,6 +846,20 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
845846
}
846847
};
847848

849+
template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
850+
static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
851+
IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);
852+
IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);
853+
IO.mapOptional("AfterFunctionDefinitionName",
854+
Spacing.AfterFunctionDefinitionName);
855+
IO.mapOptional("AfterFunctionDeclarationName",
856+
Spacing.AfterFunctionDeclarationName);
857+
IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
858+
IO.mapOptional("BeforeNonEmptyParentheses",
859+
Spacing.BeforeNonEmptyParentheses);
860+
}
861+
};
862+
848863
template <> struct MappingTraits<FormatStyle::RawStringFormat> {
849864
static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
850865
IO.mapOptional("Language", Format.Language);
@@ -939,10 +954,9 @@ std::string ParseErrorCategory::message(int EV) const {
939954
llvm_unreachable("unexpected parse error");
940955
}
941956

942-
static FormatStyle expandPresets(const FormatStyle &Style) {
943-
if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
944-
return Style;
945-
FormatStyle Expanded = Style;
957+
static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
958+
if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom)
959+
return;
946960
Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
947961
/*AfterClass=*/false,
948962
/*AfterControlStatement=*/FormatStyle::BWACS_Never,
@@ -961,7 +975,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
961975
/*SplitEmptyFunction=*/true,
962976
/*SplitEmptyRecord=*/true,
963977
/*SplitEmptyNamespace=*/true};
964-
switch (Style.BreakBeforeBraces) {
978+
switch (Expanded.BreakBeforeBraces) {
965979
case FormatStyle::BS_Linux:
966980
Expanded.BraceWrapping.AfterClass = true;
967981
Expanded.BraceWrapping.AfterFunction = true;
@@ -1042,7 +1056,33 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
10421056
default:
10431057
break;
10441058
}
1045-
return Expanded;
1059+
}
1060+
1061+
static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) {
1062+
if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom)
1063+
return;
1064+
// Reset all flags
1065+
Expanded.SpaceBeforeParensOptions = {};
1066+
1067+
switch (Expanded.SpaceBeforeParens) {
1068+
case FormatStyle::SBPO_Never:
1069+
break;
1070+
case FormatStyle::SBPO_ControlStatements:
1071+
Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1072+
Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true;
1073+
Expanded.SpaceBeforeParensOptions.AfterIfMacros = true;
1074+
break;
1075+
case FormatStyle::SBPO_ControlStatementsExceptControlMacros:
1076+
Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1077+
break;
1078+
case FormatStyle::SBPO_NonEmptyParentheses:
1079+
Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true;
1080+
break;
1081+
case FormatStyle::SBPO_Always:
1082+
break;
1083+
default:
1084+
break;
1085+
}
10461086
}
10471087

10481088
FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
@@ -1174,6 +1214,9 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
11741214
LLVMStyle.SpaceBeforeCtorInitializerColon = true;
11751215
LLVMStyle.SpaceBeforeInheritanceColon = true;
11761216
LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
1217+
LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
1218+
LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
1219+
LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
11771220
LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
11781221
LLVMStyle.SpaceBeforeAssignmentOperators = true;
11791222
LLVMStyle.SpaceBeforeCpp11BracedList = false;
@@ -1649,8 +1692,11 @@ std::string configurationAsText(const FormatStyle &Style) {
16491692
llvm::yaml::Output Output(Stream);
16501693
// We use the same mapping method for input and output, so we need a non-const
16511694
// reference here.
1652-
FormatStyle NonConstStyle = expandPresets(Style);
1695+
FormatStyle NonConstStyle = Style;
1696+
expandPresetsBraceWrapping(NonConstStyle);
1697+
expandPresetsSpaceBeforeParens(NonConstStyle);
16531698
Output << NonConstStyle;
1699+
16541700
return Stream.str();
16551701
}
16561702

@@ -2929,7 +2975,9 @@ reformat(const FormatStyle &Style, StringRef Code,
29292975
ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
29302976
unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
29312977
FormattingAttemptStatus *Status) {
2932-
FormatStyle Expanded = expandPresets(Style);
2978+
FormatStyle Expanded = Style;
2979+
expandPresetsBraceWrapping(Expanded);
2980+
expandPresetsSpaceBeforeParens(Expanded);
29332981
if (Expanded.DisableFormat)
29342982
return {tooling::Replacements(), 0};
29352983
if (isLikelyXml(Code))

0 commit comments

Comments
 (0)