Skip to content

Commit 26748a3

Browse files
author
Mitchell Balan
committed
[clang-format] Add new option to add spaces around conditions
Summary: This diff adds a new option SpacesAroundConditions that inserts spaces inside the braces for conditional statements. Reviewers: klimek, owenpan, mitchell-stellar, MyDeveloperDay Patch by: timwoj Subscribers: rsmmr, cfe-commits Tags: clang, clang-format Differential Revision: https://reviews.llvm.org/D68346
1 parent 9a20c79 commit 26748a3

File tree

5 files changed

+51
-1
lines changed

5 files changed

+51
-1
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,6 +2328,9 @@ the configuration (without a prefix: ``Auto``).
23282328
true: false:
23292329
x = ( int32 )y vs. x = (int32)y
23302330

2331+
**SpacesInConditionalStatement** (``bool``)
2332+
If ``true``, spaces will be inserted around if/for/while (and similar) conditions.
2333+
23312334
**SpacesInContainerLiterals** (``bool``)
23322335
If ``true``, spaces are inserted inside container literals (e.g.
23332336
ObjC and Javascript array and dict literals).

clang/include/clang/Format/Format.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,6 +1953,15 @@ struct FormatStyle {
19531953
/// \endcode
19541954
bool SpacesInAngles;
19551955

1956+
/// If ``true``, spaces will be inserted around if/for/switch/while
1957+
/// conditions.
1958+
/// \code
1959+
/// true: false:
1960+
/// if ( a ) { ... } vs. if (a) { ... }
1961+
/// while ( i < 5 ) { ... } while (i < 5) { ... }
1962+
/// \endcode
1963+
bool SpacesInConditionalStatement;
1964+
19561965
/// If ``true``, spaces are inserted inside container literals (e.g.
19571966
/// ObjC and Javascript array and dict literals).
19581967
/// \code{.js}
@@ -2155,6 +2164,7 @@ struct FormatStyle {
21552164
SpaceInEmptyParentheses == R.SpaceInEmptyParentheses &&
21562165
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
21572166
SpacesInAngles == R.SpacesInAngles &&
2167+
SpacesInConditionalStatement == R.SpacesInConditionalStatement &&
21582168
SpacesInContainerLiterals == R.SpacesInContainerLiterals &&
21592169
SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses &&
21602170
SpacesInParentheses == R.SpacesInParentheses &&

clang/lib/Format/Format.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,8 @@ template <> struct MappingTraits<FormatStyle> {
537537
IO.mapOptional("SpacesBeforeTrailingComments",
538538
Style.SpacesBeforeTrailingComments);
539539
IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
540+
IO.mapOptional("SpacesInConditionalStatement",
541+
Style.SpacesInConditionalStatement);
540542
IO.mapOptional("SpacesInContainerLiterals",
541543
Style.SpacesInContainerLiterals);
542544
IO.mapOptional("SpacesInCStyleCastParentheses",
@@ -817,6 +819,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
817819
LLVMStyle.SpaceBeforeCpp11BracedList = false;
818820
LLVMStyle.SpaceBeforeSquareBrackets = false;
819821
LLVMStyle.SpacesInAngles = false;
822+
LLVMStyle.SpacesInConditionalStatement = false;
820823

821824
LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
822825
LLVMStyle.PenaltyBreakComment = 300;

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2592,6 +2592,13 @@ bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const {
25922592
Right.ParameterCount > 0);
25932593
}
25942594

2595+
/// Returns \c true if the token is followed by a boolean condition, \c false
2596+
/// otherwise.
2597+
static bool isKeywordWithCondition(const FormatToken &Tok) {
2598+
return Tok.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,
2599+
tok::kw_constexpr);
2600+
};
2601+
25952602
bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
25962603
const FormatToken &Left,
25972604
const FormatToken &Right) {
@@ -2610,6 +2617,15 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
26102617
(Left.is(tok::l_brace) && Left.BlockKind != BK_Block &&
26112618
Right.is(tok::r_brace) && Right.BlockKind != BK_Block))
26122619
return Style.SpaceInEmptyParentheses;
2620+
if (Style.SpacesInConditionalStatement) {
2621+
if (Left.is(tok::l_paren) && Left.Previous &&
2622+
isKeywordWithCondition(*Left.Previous))
2623+
return true;
2624+
if (Right.is(tok::r_paren) && Right.MatchingParen &&
2625+
Right.MatchingParen->Previous &&
2626+
isKeywordWithCondition(*Right.MatchingParen->Previous))
2627+
return true;
2628+
}
26132629
if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
26142630
return (Right.is(TT_CastRParen) ||
26152631
(Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen)))
@@ -3044,7 +3060,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
30443060
// The identifier might actually be a macro name such as ALWAYS_INLINE. If
30453061
// this turns out to be too lenient, add analysis of the identifier itself.
30463062
return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
3047-
if (Right.is(tok::coloncolon) && !Left.isOneOf(tok::l_brace, tok::comment))
3063+
if (Right.is(tok::coloncolon) &&
3064+
!Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren))
30483065
return (Left.is(TT_TemplateOpener) &&
30493066
Style.Standard < FormatStyle::LS_Cpp11) ||
30503067
!(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,

clang/unittests/Format/FormatTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12555,6 +12555,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
1255512555
CHECK_PARSE_BOOL(SpacesInParentheses);
1255612556
CHECK_PARSE_BOOL(SpacesInSquareBrackets);
1255712557
CHECK_PARSE_BOOL(SpacesInAngles);
12558+
CHECK_PARSE_BOOL(SpacesInConditionalStatement);
1255812559
CHECK_PARSE_BOOL(SpaceInEmptyBlock);
1255912560
CHECK_PARSE_BOOL(SpaceInEmptyParentheses);
1256012561
CHECK_PARSE_BOOL(SpacesInContainerLiterals);
@@ -14880,6 +14881,22 @@ TEST_F(FormatTest, AmbersandInLamda) {
1488014881
verifyFormat("auto lambda = [&a = a]() { a = 2; };", AlignStyle);
1488114882
}
1488214883

14884+
TEST_F(FormatTest, SpacesInConditionalStatement) {
14885+
FormatStyle Spaces = getLLVMStyle();
14886+
Spaces.SpacesInConditionalStatement = true;
14887+
verifyFormat("for ( int i = 0; i; i++ )\n continue;", Spaces);
14888+
verifyFormat("if ( !a )\n return;", Spaces);
14889+
verifyFormat("if ( a )\n return;", Spaces);
14890+
verifyFormat("if constexpr ( a )\n return;", Spaces);
14891+
verifyFormat("switch ( a )\ncase 1:\n return;", Spaces);
14892+
verifyFormat("while ( a )\n return;", Spaces);
14893+
verifyFormat("while ( (a && b) )\n return;", Spaces);
14894+
verifyFormat("do {\n} while ( 1 != 0 );", Spaces);
14895+
// Check that space on the left of "::" is inserted as expected at beginning
14896+
// of condition.
14897+
verifyFormat("while ( ::func() )\n return;", Spaces);
14898+
}
14899+
1488314900
TEST_F(FormatTest, AlternativeOperators) {
1488414901
// Test case for ensuring alternate operators are not
1488514902
// combined with their right most neighbour.

0 commit comments

Comments
 (0)