Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -178,12 +178,31 @@ /// or other definitions. BS_GNU, /// Like ``Attach``, but break before functions. - BS_WebKit + BS_WebKit, + + /// Configure each individual brace in \c BraceWrapping. + BS_Custom }; /// \brief The brace breaking style to use. BraceBreakingStyle BreakBeforeBraces; + struct BraceWrappingFlags { + bool AfterClass; + bool AfterControlStatement; + bool AfterEnum; + bool AfterFunction; + bool AfterNamespace; + bool AfterObjCDeclaration; + bool AfterStruct; + bool AfterUnion; + bool BeforeCatch; + bool BeforeElse; + bool IndentBraces; + }; + + BraceWrappingFlags BraceWrapping; + /// \brief If \c true, ternary operators will be placed after line breaks. bool BreakBeforeTernaryOperators; Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -99,11 +99,14 @@ IO.enumCase(Value, "Allman", FormatStyle::BS_Allman); IO.enumCase(Value, "GNU", FormatStyle::BS_GNU); IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit); + IO.enumCase(Value, "Custom", FormatStyle::BS_Custom); } }; -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { +template <> +struct ScalarEnumerationTraits { + static void + enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { IO.enumCase(Value, "None", FormatStyle::DRTBS_None); IO.enumCase(Value, "All", FormatStyle::DRTBS_All); IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel); @@ -221,6 +224,7 @@ Style.AlwaysBreakTemplateDeclarations); IO.mapOptional("BinPackArguments", Style.BinPackArguments); IO.mapOptional("BinPackParameters", Style.BinPackParameters); + IO.mapOptional("BraceWrapping", Style.BraceWrapping); IO.mapOptional("BreakBeforeBinaryOperators", Style.BreakBeforeBinaryOperators); IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); @@ -285,6 +289,21 @@ } }; +template <> struct MappingTraits { + static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) { + IO.mapOptional("AfterClass", Wrapping.AfterClass); + IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement); + IO.mapOptional("AfterEnum", Wrapping.AfterEnum); + IO.mapOptional("AfterFunction", Wrapping.AfterFunction); + IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace); + IO.mapOptional("AfterStruct", Wrapping.AfterStruct); + IO.mapOptional("AfterUnion", Wrapping.AfterUnion); + IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); + IO.mapOptional("BeforeElse", Wrapping.BeforeElse); + IO.mapOptional("IndentBraces", Wrapping.IndentBraces); + } +}; + // Allows to read vector while keeping default values. // IO.getContext() should contain a pointer to the FormatStyle structure, that // will be used to get default values for missing keys. @@ -340,6 +359,60 @@ llvm_unreachable("unexpected parse error"); } +static FormatStyle expandPresets(const FormatStyle &Style) { + FormatStyle Expanded = Style; + Expanded.BraceWrapping = {false, false, false, false, false, false, + false, false, false, false, false}; + switch (Style.BreakBeforeBraces) { + case FormatStyle::BS_Linux: + Expanded.BraceWrapping.AfterClass = true; + Expanded.BraceWrapping.AfterFunction = true; + Expanded.BraceWrapping.AfterNamespace = true; + Expanded.BraceWrapping.BeforeElse = true; + break; + case FormatStyle::BS_Mozilla: + Expanded.BraceWrapping.AfterClass = true; + Expanded.BraceWrapping.AfterEnum = true; + Expanded.BraceWrapping.AfterFunction = true; + Expanded.BraceWrapping.AfterStruct = true; + Expanded.BraceWrapping.AfterUnion = true; + break; + case FormatStyle::BS_Stroustrup: + Expanded.BraceWrapping.AfterFunction = true; + Expanded.BraceWrapping.BeforeCatch = true; + Expanded.BraceWrapping.BeforeElse = true; + break; + case FormatStyle::BS_Allman: + Expanded.BraceWrapping.AfterClass = true; + Expanded.BraceWrapping.AfterControlStatement = true; + Expanded.BraceWrapping.AfterEnum = true; + Expanded.BraceWrapping.AfterFunction = true; + Expanded.BraceWrapping.AfterNamespace = true; + Expanded.BraceWrapping.AfterObjCDeclaration = true; + Expanded.BraceWrapping.AfterStruct = true; + Expanded.BraceWrapping.BeforeCatch = true; + Expanded.BraceWrapping.BeforeElse = true; + break; + case FormatStyle::BS_GNU: + Expanded.BraceWrapping.AfterClass = true; + Expanded.BraceWrapping.AfterControlStatement = true; + Expanded.BraceWrapping.AfterEnum = true; + Expanded.BraceWrapping.AfterFunction = true; + Expanded.BraceWrapping.AfterNamespace = true; + Expanded.BraceWrapping.AfterObjCDeclaration = true; + Expanded.BraceWrapping.BeforeCatch = true; + Expanded.BraceWrapping.BeforeElse = true; + Expanded.BraceWrapping.IndentBraces = true; + break; + case FormatStyle::BS_WebKit: + Expanded.BraceWrapping.AfterFunction = true; + break; + default: + break; + } + return Expanded; +} + FormatStyle getLLVMStyle() { FormatStyle LLVMStyle; LLVMStyle.Language = FormatStyle::LK_Cpp; @@ -1677,9 +1750,10 @@ SourceManager &SourceMgr, FileID ID, ArrayRef Ranges, bool *IncompleteFormat) { - if (Style.DisableFormat) + FormatStyle Expanded = expandPresets(Style); + if (Expanded.DisableFormat) return tooling::Replacements(); - Formatter formatter(Style, SourceMgr, ID, Ranges); + Formatter formatter(Expanded, SourceMgr, ID, Ranges); return formatter.format(IncompleteFormat); } Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -2157,10 +2157,9 @@ if (Right.is(TT_InlineASMBrace)) return Right.HasUnescapedNewline; if (isAllmanBrace(Left) || isAllmanBrace(Right)) - return Style.BreakBeforeBraces == FormatStyle::BS_Allman || - Style.BreakBeforeBraces == FormatStyle::BS_GNU || - (Style.BreakBeforeBraces == FormatStyle::BS_Mozilla && - Line.startsWith(tok::kw_enum)); + return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) || + (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) || + (Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct); if (Style.Language == FormatStyle::LK_Proto && Left.isNot(tok::l_brace) && Right.is(TT_SelectorName)) return true; Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -199,12 +199,12 @@ return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0; } if (TheLine->Last->is(tok::l_brace)) { - return Style.BreakBeforeBraces == FormatStyle::BS_Attach + return !Style.BraceWrapping.AfterFunction ? tryMergeSimpleBlock(I, E, Limit) : 0; } if (I[1]->First->is(TT_FunctionLBrace) && - Style.BreakBeforeBraces != FormatStyle::BS_Attach) { + Style.BraceWrapping.AfterFunction) { if (I[1]->Last->is(TT_LineComment)) return 0; @@ -263,8 +263,7 @@ SmallVectorImpl::const_iterator E, unsigned Limit) { if (Limit == 0) return 0; - if ((Style.BreakBeforeBraces == FormatStyle::BS_Allman || - Style.BreakBeforeBraces == FormatStyle::BS_GNU) && + if (Style.BraceWrapping.AfterControlStatement && (I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine)) return 0; if (I[1]->InPPDirective != (*I)->InPPDirective || Index: lib/Format/UnwrappedLineParser.cpp =================================================================== --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -154,12 +154,10 @@ CompoundStatementIndenter(UnwrappedLineParser *Parser, const FormatStyle &Style, unsigned &LineLevel) : LineLevel(LineLevel), OldLineLevel(LineLevel) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) { - Parser->addUnwrappedLine(); - } else if (Style.BreakBeforeBraces == FormatStyle::BS_GNU) { + if (Style.BraceWrapping.AfterControlStatement) Parser->addUnwrappedLine(); + if (Style.BraceWrapping.IndentBraces) ++LineLevel; - } } ~CompoundStatementIndenter() { LineLevel = OldLineLevel; } @@ -456,17 +454,15 @@ static bool ShouldBreakBeforeBrace(const FormatStyle &Style, const FormatToken &InitialToken) { - switch (Style.BreakBeforeBraces) { - case FormatStyle::BS_Linux: - return InitialToken.isOneOf(tok::kw_namespace, tok::kw_class); - case FormatStyle::BS_Mozilla: - return InitialToken.isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union); - case FormatStyle::BS_Allman: - case FormatStyle::BS_GNU: - return true; - default: - return false; - } + if (InitialToken.is(tok::kw_namespace)) + return Style.BraceWrapping.AfterNamespace; + if (InitialToken.is(tok::kw_class)) + return Style.BraceWrapping.AfterClass; + if (InitialToken.is(tok::kw_union)) + return Style.BraceWrapping.AfterUnion; + if (InitialToken.is(tok::kw_struct)) + return Style.BraceWrapping.AfterStruct; + return false; } void UnwrappedLineParser::parseChildBlock() { @@ -681,8 +677,7 @@ case tok::objc_autoreleasepool: nextToken(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || - Style.BreakBeforeBraces == FormatStyle::BS_GNU) + if (Style.BraceWrapping.AfterObjCDeclaration) addUnwrappedLine(); parseBlock(/*MustBeDeclaration=*/false); } @@ -871,7 +866,7 @@ // structural element. // FIXME: Figure out cases where this is not true, and add projections // for them (the one we know is missing are lambdas). - if (Style.BreakBeforeBraces != FormatStyle::BS_Attach) + if (Style.BraceWrapping.AfterFunction) addUnwrappedLine(); FormatTok->Type = TT_FunctionLBrace; parseBlock(/*MustBeDeclaration=*/false); @@ -1259,12 +1254,10 @@ if (FormatTok->Tok.is(tok::l_brace)) { CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || - Style.BreakBeforeBraces == FormatStyle::BS_GNU) { + if (Style.BraceWrapping.BeforeElse) addUnwrappedLine(); - } else { + else NeedsUnwrappedLine = true; - } } else { addUnwrappedLine(); ++Line->Level; @@ -1272,8 +1265,6 @@ --Line->Level; } if (FormatTok->Tok.is(tok::kw_else)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) - addUnwrappedLine(); nextToken(); if (FormatTok->Tok.is(tok::l_brace)) { CompoundStatementIndenter Indenter(this, Style, Line->Level); @@ -1314,9 +1305,7 @@ if (FormatTok->is(tok::l_brace)) { CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || - Style.BreakBeforeBraces == FormatStyle::BS_GNU || - Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) { + if (Style.BraceWrapping.BeforeCatch) { addUnwrappedLine(); } else { NeedsUnwrappedLine = true; @@ -1354,17 +1343,13 @@ NeedsUnwrappedLine = false; CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || - Style.BreakBeforeBraces == FormatStyle::BS_GNU || - Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) { + if (Style.BraceWrapping.BeforeCatch) addUnwrappedLine(); - } else { + else NeedsUnwrappedLine = true; - } } - if (NeedsUnwrappedLine) { + if (NeedsUnwrappedLine) addUnwrappedLine(); - } } void UnwrappedLineParser::parseNamespace() { @@ -1440,7 +1425,7 @@ if (FormatTok->Tok.is(tok::l_brace)) { CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); - if (Style.BreakBeforeBraces == FormatStyle::BS_GNU) + if (Style.BraceWrapping.IndentBraces) addUnwrappedLine(); } else { addUnwrappedLine(); @@ -1468,11 +1453,8 @@ CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); if (FormatTok->Tok.is(tok::kw_break)) { - // "break;" after "}" on its own line only for BS_Allman and BS_GNU - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || - Style.BreakBeforeBraces == FormatStyle::BS_GNU) { + if (Style.BraceWrapping.AfterControlStatement) addUnwrappedLine(); - } parseStructuralElement(); } addUnwrappedLine(); @@ -1736,8 +1718,7 @@ parseObjCProtocolList(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || - Style.BreakBeforeBraces == FormatStyle::BS_GNU) + if (Style.BraceWrapping.AfterObjCDeclaration) addUnwrappedLine(); parseBlock(/*MustBeDeclaration=*/true); }