Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -1201,6 +1201,18 @@ /// \endcode bool SpaceBeforeAssignmentOperators; + /// \brief If ``false``, spaces will be removed before colon. + /// This affects C++11 loop, initializer list, inheritance list and container + /// literals. + /// \code + /// true: false: + /// class Foo : Bar {} vs. class Foo: Bar {} + /// Foo::Foo() : a(a) {} Foo::Foo(): a(a) {} + /// for (auto i : myList) {} for (auto i: myList) {} + /// f({a : 1, b : 2, c : 3}); f({a: 1, b: 2, c: 3}); + /// \endcode + bool SpaceBeforeColon; + /// \brief Different ways to put a space before opening parentheses. enum SpaceBeforeParensOptions { /// Never put a space before opening parentheses. @@ -1414,6 +1426,7 @@ SpaceAfterCStyleCast == R.SpaceAfterCStyleCast && SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword && SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators && + SpaceBeforeColon == R.SpaceBeforeColon && SpaceBeforeParens == R.SpaceBeforeParens && SpaceInEmptyParentheses == R.SpaceInEmptyParentheses && SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments && Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -346,6 +346,7 @@ IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword); IO.mapOptional("SpaceBeforeAssignmentOperators", Style.SpaceBeforeAssignmentOperators); + IO.mapOptional("SpaceBeforeColon", Style.SpaceBeforeColon); IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses); IO.mapOptional("SpacesBeforeTrailingComments", @@ -565,6 +566,7 @@ LLVMStyle.SpacesInCStyleCastParentheses = false; LLVMStyle.SpaceAfterCStyleCast = false; LLVMStyle.SpaceAfterTemplateKeyword = true; + LLVMStyle.SpaceBeforeColon = true; LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; LLVMStyle.SpaceBeforeAssignmentOperators = true; LLVMStyle.SpacesInAngles = false; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -2341,8 +2341,10 @@ if (Right.is(tok::comma)) return false; if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen)) - return true; + return Style.SpaceBeforeColon; if (Right.is(tok::colon)) { + if (!Style.SpaceBeforeColon && Right.isNot(TT_ConditionalExpr)) + return false; if (Line.First->isOneOf(tok::kw_case, tok::kw_default) || !Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi)) return false; Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -7519,6 +7519,20 @@ verifyFormat("a or_eq 8;", Spaces); } +TEST_F(FormatTest, ConfigurableSpaceBeforeColon) { + verifyFormat("class Foo : public Bar {};"); + verifyFormat("Foo::Foo() : foo(1) {}"); + verifyFormat("for (auto a : b) {\n}"); + verifyFormat("int x = a ? b : c;"); + + FormatStyle Spaces = getLLVMStyle(); + Spaces.SpaceBeforeColon = false; + verifyFormat("class Foo: public Bar {};", Spaces); + verifyFormat("Foo::Foo(): foo(1) {}", Spaces); + verifyFormat("for (auto a: b) {\n}", Spaces); + verifyFormat("int x = a ? b : c;", Spaces); +} + TEST_F(FormatTest, AlignConsecutiveAssignments) { FormatStyle Alignment = getLLVMStyle(); Alignment.AlignConsecutiveAssignments = false; @@ -8703,6 +8717,7 @@ CHECK_PARSE_BOOL(SpaceAfterCStyleCast); CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword); CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators); + CHECK_PARSE_BOOL(SpaceBeforeColon); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterControlStatement);