From 7df56bfcf7186f73c99564cd54216f07a8db7352 Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Tue, 20 Aug 2013 12:36:34 +0000 Subject: [PATCH] clang-format: Additional options for spaces around parentheses. This patch adds four new options to control: - Spaces after control keyworks (if(..) vs if (..)) - Spaces in empty parentheses (f( ) vs f()) - Spaces in c-style casts (( int )1.0 vs (int)1.0) - Spaces in other parentheses (f(a) vs f( a )) Patch by Joe Hermaszewski. Thank you for working on this! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188793 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Format/Format.h | 22 ++++++++- lib/Format/Format.cpp | 15 ++++++ lib/Format/TokenAnnotator.cpp | 19 +++++--- unittests/Format/FormatTest.cpp | 86 +++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 7 deletions(-) diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index d6062e5c6a..658977c323 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -194,6 +194,20 @@ struct FormatStyle { /// are not also definitions after the type. bool IndentFunctionDeclarationAfterType; + /// \brief If \c true, spaces will be inserted after every '(' and before + /// every ')'. + bool SpacesInParentheses; + + /// \brief If \c false, spaces may be inserted into '()'. + bool SpaceInEmptyParentheses; + + /// \brief If \c false, spaces may be inserted into C style casts. + bool SpacesInCStyleCastParentheses; + + /// \brief If \c true, spaces will be inserted between 'for'/'if'/'while'/... + /// and '('. + bool SpaceAfterControlStatementKeyword; + bool operator==(const FormatStyle &R) const { return AccessModifierOffset == R.AccessModifierOffset && ConstructorInitializerIndentWidth == @@ -231,7 +245,13 @@ struct FormatStyle { Cpp11BracedListStyle == R.Cpp11BracedListStyle && Standard == R.Standard && UseTab == R.UseTab && IndentFunctionDeclarationAfterType == - R.IndentFunctionDeclarationAfterType; + R.IndentFunctionDeclarationAfterType && + SpacesInParentheses == R.SpacesInParentheses && + SpaceInEmptyParentheses == R.SpaceInEmptyParentheses && + SpacesInCStyleCastParentheses == + R.SpacesInCStyleCastParentheses && + SpaceAfterControlStatementKeyword == + R.SpaceAfterControlStatementKeyword; } }; diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 20a2af5012..c4a5e88de7 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -137,6 +137,13 @@ template <> struct MappingTraits { IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); IO.mapOptional("IndentFunctionDeclarationAfterType", Style.IndentFunctionDeclarationAfterType); + IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses); + IO.mapOptional("SpaceInEmptyParentheses", + Style.SpaceInEmptyParentheses); + IO.mapOptional("SpacesInCStyleCastParentheses", + Style.SpacesInCStyleCastParentheses); + IO.mapOptional("SpaceAfterControlStatementKeyword", + Style.SpaceAfterControlStatementKeyword); } }; } @@ -182,6 +189,10 @@ FormatStyle getLLVMStyle() { LLVMStyle.SpacesBeforeTrailingComments = 1; LLVMStyle.Standard = FormatStyle::LS_Cpp03; LLVMStyle.UseTab = false; + LLVMStyle.SpacesInParentheses = false; + LLVMStyle.SpaceInEmptyParentheses = false; + LLVMStyle.SpacesInCStyleCastParentheses = false; + LLVMStyle.SpaceAfterControlStatementKeyword = true; setDefaultPenalties(LLVMStyle); LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60; @@ -219,6 +230,10 @@ FormatStyle getGoogleStyle() { GoogleStyle.SpacesBeforeTrailingComments = 2; GoogleStyle.Standard = FormatStyle::LS_Auto; GoogleStyle.UseTab = false; + GoogleStyle.SpacesInParentheses = false; + GoogleStyle.SpaceInEmptyParentheses = false; + GoogleStyle.SpacesInCStyleCastParentheses = false; + GoogleStyle.SpaceAfterControlStatementKeyword = true; setDefaultPenalties(GoogleStyle); GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index ad6f41005c..ee3ca67d27 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -1120,7 +1120,14 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return Left.is(tok::hash); if (Left.isOneOf(tok::hashhash, tok::hash)) return Right.is(tok::hash); - if (Right.isOneOf(tok::r_paren, tok::semi, tok::comma)) + if (Left.is(tok::l_paren) && Right.is(tok::r_paren)) + return Style.SpaceInEmptyParentheses; + if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) + return Right.Type == TT_CastRParen || + (Left.MatchingParen && Left.MatchingParen->Type == TT_CastRParen) + ? Style.SpacesInCStyleCastParentheses + : Style.SpacesInParentheses; + if (Right.isOneOf(tok::semi, tok::comma)) return false; if (Right.is(tok::less) && (Left.is(tok::kw_template) || @@ -1168,17 +1175,17 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return Left.Type != TT_ObjCMethodExpr; if (Right.is(tok::colon)) return Right.Type != TT_ObjCMethodExpr && !Left.is(tok::question); - if (Left.is(tok::l_paren)) - return false; if (Right.is(tok::l_paren)) { if (Left.is(tok::r_paren) && Left.MatchingParen && Left.MatchingParen->Previous && Left.MatchingParen->Previous->is(tok::kw___attribute)) return true; return Line.Type == LT_ObjCDecl || - Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch, - tok::kw_return, tok::kw_catch, tok::kw_new, - tok::kw_delete, tok::semi); + Left.isOneOf(tok::kw_return, tok::kw_new, + tok::kw_delete, tok::semi) || + (Style.SpaceAfterControlStatementKeyword && + Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch, + tok::kw_catch)); } if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword) return false; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index e9384c4644..5ebae5f6b2 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -5424,6 +5424,88 @@ TEST_F(FormatTest, ConfigurableUseOfTab) { "}")); } +TEST_F(FormatTest, ConfigurableSpaceAfterControlStatementKeyword) { + FormatStyle NoSpace = getLLVMStyle(); + NoSpace.SpaceAfterControlStatementKeyword = false; + + verifyFormat("while(true)\n" + " continue;", NoSpace); + verifyFormat("for(;;)\n" + " continue;", NoSpace); + verifyFormat("if(true)\n" + " f();\n" + "else if(true)\n" + " f();", NoSpace); + verifyFormat("do {\n" + " do_something();\n" + "} while(something());", NoSpace); + verifyFormat("switch(x) {\n" + "default:\n" + " break;\n" + "}", NoSpace); +} + +TEST_F(FormatTest, ConfigurableSpacesInParentheses) { + FormatStyle Spaces = getLLVMStyle(); + + Spaces.SpacesInParentheses = true; + verifyFormat("call( x, y, z );", Spaces); + verifyFormat("while ( (bool)1 )\n" + " continue;", Spaces); + verifyFormat("for ( ;; )\n" + " continue;", Spaces); + verifyFormat("if ( true )\n" + " f();\n" + "else if ( true )\n" + " f();", Spaces); + verifyFormat("do {\n" + " do_something( (int)i );\n" + "} while ( something() );", Spaces); + verifyFormat("switch ( x ) {\n" + "default:\n" + " break;\n" + "}", Spaces); + + Spaces.SpacesInParentheses = false; + Spaces.SpacesInCStyleCastParentheses = true; + verifyFormat("Type *A = ( Type * )P;", Spaces); + verifyFormat("Type *A = ( vector )P;", Spaces); + verifyFormat("x = ( int32 )y;", Spaces); + verifyFormat("int a = ( int )(2.0f);", Spaces); + verifyFormat("#define AA(X) sizeof((( X * )NULL)->a)", Spaces); + verifyFormat("my_int a = ( my_int )sizeof(int);", Spaces); + verifyFormat("#define x (( int )-1)", Spaces); + + Spaces.SpacesInParentheses = false; + Spaces.SpaceInEmptyParentheses = true; + verifyFormat("call(x, y, z);", Spaces); + verifyFormat("call( )", Spaces); + + // Run the first set of tests again with + // Spaces.SpacesInParentheses = false, + // Spaces.SpaceInEmptyParentheses = true and + // Spaces.SpacesInCStyleCastParentheses = true + Spaces.SpacesInParentheses = false, + Spaces.SpaceInEmptyParentheses = true; + Spaces.SpacesInCStyleCastParentheses = true; + verifyFormat("call(x, y, z);", Spaces); + verifyFormat("while (( bool )1)\n" + " continue;", Spaces); + verifyFormat("for (;;)\n" + " continue;", Spaces); + verifyFormat("if (true)\n" + " f( );\n" + "else if (true)\n" + " f( );", Spaces); + verifyFormat("do {\n" + " do_something(( int )i);\n" + "} while (something( ));", Spaces); + verifyFormat("switch (x) {\n" + "default:\n" + " break;\n" + "}", Spaces); +} + TEST_F(FormatTest, LinuxBraceBreaking) { FormatStyle BreakBeforeBrace = getLLVMStyle(); BreakBeforeBrace.BreakBeforeBraces = FormatStyle::BS_Linux; @@ -5661,6 +5743,10 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE_BOOL(Cpp11BracedListStyle); CHECK_PARSE_BOOL(UseTab); CHECK_PARSE_BOOL(IndentFunctionDeclarationAfterType); + CHECK_PARSE_BOOL(SpacesInParentheses); + CHECK_PARSE_BOOL(SpaceInEmptyParentheses); + CHECK_PARSE_BOOL(SpacesInCStyleCastParentheses); + CHECK_PARSE_BOOL(SpaceAfterControlStatementKeyword); CHECK_PARSE("AccessModifierOffset: -1234", AccessModifierOffset, -1234); CHECK_PARSE("ConstructorInitializerIndentWidth: 1234", -- 2.50.1