Implemented GNU-style formatting for compound statements.

Summary:
Added BraceBreakingStyle::BS_GNU. I'm not sure about the correctness of
static initializer formatting, but compound statements should be fine.

Reviewers: djasper

Reviewed By: djasper

CC: cfe-commits, klimek

Differential Revision: http://llvm-reviews.chandlerc.com/D2372

llvm-svn: 197138
This commit is contained in:
Alexander Kornienko 2013-12-12 09:49:52 +00:00
parent a92e2311bb
commit 3a33f0292b
6 changed files with 145 additions and 26 deletions

View File

@ -218,7 +218,11 @@ struct FormatStyle {
/// Like \c Attach, but break before function definitions. /// Like \c Attach, but break before function definitions.
BS_Stroustrup, BS_Stroustrup,
/// Always break before braces. /// Always break before braces.
BS_Allman BS_Allman,
/// Always break before braces and add an extra level of indentation to
/// braces of control statements, not to those of class, function
/// or other definitions.
BS_GNU
}; };
/// \brief The brace breaking style to use. /// \brief The brace breaking style to use.

View File

@ -68,6 +68,7 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
IO.enumCase(Value, "Linux", FormatStyle::BS_Linux); IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup); IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
IO.enumCase(Value, "Allman", FormatStyle::BS_Allman); IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
} }
}; };
@ -359,7 +360,7 @@ FormatStyle getWebKitStyle() {
FormatStyle getGNUStyle() { FormatStyle getGNUStyle() {
FormatStyle Style = getLLVMStyle(); FormatStyle Style = getLLVMStyle();
Style.BreakBeforeBinaryOperators = true; Style.BreakBeforeBinaryOperators = true;
Style.BreakBeforeBraces = FormatStyle::BS_Allman; Style.BreakBeforeBraces = FormatStyle::BS_GNU;
Style.BreakBeforeTernaryOperators = true; Style.BreakBeforeTernaryOperators = true;
Style.ColumnLimit = 79; Style.ColumnLimit = 79;
Style.SpaceBeforeParens = FormatStyle::SBPO_Always; Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
@ -561,7 +562,8 @@ private:
SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) { SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
if (Limit == 0) if (Limit == 0)
return 0; return 0;
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman && if ((Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU) &&
I[1]->First->is(tok::l_brace)) I[1]->First->is(tok::l_brace))
return 0; return 0;
if (I[1]->InPPDirective != (*I)->InPPDirective || if (I[1]->InPPDirective != (*I)->InPPDirective ||

View File

@ -1410,7 +1410,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Right.Previous->isNot(tok::r_brace) && Right.isNot(tok::r_brace)) { Right.Previous->isNot(tok::r_brace) && Right.isNot(tok::r_brace)) {
return true; return true;
} else if (Right.is(tok::l_brace) && (Right.BlockKind == BK_Block)) { } else if (Right.is(tok::l_brace) && (Right.BlockKind == BK_Block)) {
return Style.BreakBeforeBraces == FormatStyle::BS_Allman; return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU;
} }
return false; return false;
} }

View File

@ -152,6 +152,27 @@ private:
SmallVectorImpl<UnwrappedLine> *OriginalLines; SmallVectorImpl<UnwrappedLine> *OriginalLines;
}; };
class CompoundStatementIndenter {
public:
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) {
Parser->addUnwrappedLine();
++LineLevel;
}
}
~CompoundStatementIndenter() {
LineLevel = OldLineLevel;
}
private:
unsigned &LineLevel;
unsigned OldLineLevel;
};
namespace { namespace {
class IndexedTokenSource : public FormatTokenSource { class IndexedTokenSource : public FormatTokenSource {
@ -677,9 +698,7 @@ void UnwrappedLineParser::parseStructuralElement() {
// structural element. // structural element.
// FIXME: Figure out cases where this is not true, and add projections // FIXME: Figure out cases where this is not true, and add projections
// for them (the one we know is missing are lambdas). // for them (the one we know is missing are lambdas).
if (Style.BreakBeforeBraces == FormatStyle::BS_Linux || if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)
Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup ||
Style.BreakBeforeBraces == FormatStyle::BS_Allman)
addUnwrappedLine(); addUnwrappedLine();
FormatTok->Type = TT_FunctionLBrace; FormatTok->Type = TT_FunctionLBrace;
parseBlock(/*MustBeDeclaration=*/false); parseBlock(/*MustBeDeclaration=*/false);
@ -938,13 +957,14 @@ void UnwrappedLineParser::parseIfThenElse() {
parseParens(); parseParens();
bool NeedsUnwrappedLine = false; bool NeedsUnwrappedLine = false;
if (FormatTok->Tok.is(tok::l_brace)) { if (FormatTok->Tok.is(tok::l_brace)) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) CompoundStatementIndenter Indenter(this, Style, Line->Level);
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false); parseBlock(/*MustBeDeclaration=*/false);
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU) {
addUnwrappedLine(); addUnwrappedLine();
else } else {
NeedsUnwrappedLine = true; NeedsUnwrappedLine = true;
}
} else { } else {
addUnwrappedLine(); addUnwrappedLine();
++Line->Level; ++Line->Level;
@ -954,8 +974,7 @@ void UnwrappedLineParser::parseIfThenElse() {
if (FormatTok->Tok.is(tok::kw_else)) { if (FormatTok->Tok.is(tok::kw_else)) {
nextToken(); nextToken();
if (FormatTok->Tok.is(tok::l_brace)) { if (FormatTok->Tok.is(tok::l_brace)) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) CompoundStatementIndenter Indenter(this, Style, Line->Level);
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false); parseBlock(/*MustBeDeclaration=*/false);
addUnwrappedLine(); addUnwrappedLine();
} else if (FormatTok->Tok.is(tok::kw_if)) { } else if (FormatTok->Tok.is(tok::kw_if)) {
@ -978,7 +997,8 @@ void UnwrappedLineParser::parseNamespace() {
nextToken(); nextToken();
if (FormatTok->Tok.is(tok::l_brace)) { if (FormatTok->Tok.is(tok::l_brace)) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Linux || if (Style.BreakBeforeBraces == FormatStyle::BS_Linux ||
Style.BreakBeforeBraces == FormatStyle::BS_Allman) Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU)
addUnwrappedLine(); addUnwrappedLine();
bool AddLevel = Style.NamespaceIndentation == FormatStyle::NI_All || bool AddLevel = Style.NamespaceIndentation == FormatStyle::NI_All ||
@ -1001,8 +1021,7 @@ void UnwrappedLineParser::parseForOrWhileLoop() {
if (FormatTok->Tok.is(tok::l_paren)) if (FormatTok->Tok.is(tok::l_paren))
parseParens(); parseParens();
if (FormatTok->Tok.is(tok::l_brace)) { if (FormatTok->Tok.is(tok::l_brace)) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) CompoundStatementIndenter Indenter(this, Style, Line->Level);
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false); parseBlock(/*MustBeDeclaration=*/false);
addUnwrappedLine(); addUnwrappedLine();
} else { } else {
@ -1017,9 +1036,10 @@ void UnwrappedLineParser::parseDoWhile() {
assert(FormatTok->Tok.is(tok::kw_do) && "'do' expected"); assert(FormatTok->Tok.is(tok::kw_do) && "'do' expected");
nextToken(); nextToken();
if (FormatTok->Tok.is(tok::l_brace)) { if (FormatTok->Tok.is(tok::l_brace)) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) CompoundStatementIndenter Indenter(this, Style, Line->Level);
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false); parseBlock(/*MustBeDeclaration=*/false);
if (Style.BreakBeforeBraces == FormatStyle::BS_GNU)
addUnwrappedLine();
} else { } else {
addUnwrappedLine(); addUnwrappedLine();
++Line->Level; ++Line->Level;
@ -1043,17 +1063,20 @@ void UnwrappedLineParser::parseLabel() {
if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0)) if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
--Line->Level; --Line->Level;
if (CommentsBeforeNextToken.empty() && FormatTok->Tok.is(tok::l_brace)) { if (CommentsBeforeNextToken.empty() && FormatTok->Tok.is(tok::l_brace)) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) CompoundStatementIndenter Indenter(this, Style, Line->Level);
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false); parseBlock(/*MustBeDeclaration=*/false);
if (FormatTok->Tok.is(tok::kw_break)) { if (FormatTok->Tok.is(tok::kw_break)) {
// "break;" after "}" on its own line only for BS_Allman // "break;" after "}" on its own line only for BS_Allman and BS_GNU
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU) {
addUnwrappedLine(); addUnwrappedLine();
}
parseStructuralElement(); parseStructuralElement();
} }
}
addUnwrappedLine(); addUnwrappedLine();
} else {
addUnwrappedLine();
}
Line->Level = OldLineLevel; Line->Level = OldLineLevel;
} }
@ -1072,8 +1095,7 @@ void UnwrappedLineParser::parseSwitch() {
if (FormatTok->Tok.is(tok::l_paren)) if (FormatTok->Tok.is(tok::l_paren))
parseParens(); parseParens();
if (FormatTok->Tok.is(tok::l_brace)) { if (FormatTok->Tok.is(tok::l_brace)) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) CompoundStatementIndenter Indenter(this, Style, Line->Level);
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false); parseBlock(/*MustBeDeclaration=*/false);
addUnwrappedLine(); addUnwrappedLine();
} else { } else {
@ -1164,7 +1186,8 @@ void UnwrappedLineParser::parseRecord() {
} }
if (FormatTok->Tok.is(tok::l_brace)) { if (FormatTok->Tok.is(tok::l_brace)) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Linux || if (Style.BreakBeforeBraces == FormatStyle::BS_Linux ||
Style.BreakBeforeBraces == FormatStyle::BS_Allman) Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU)
addUnwrappedLine(); addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/true, /*Addlevel=*/true, parseBlock(/*MustBeDeclaration=*/true, /*Addlevel=*/true,

View File

@ -185,6 +185,7 @@ private:
std::stack<int> PPChainBranchIndex; std::stack<int> PPChainBranchIndex;
friend class ScopedLineState; friend class ScopedLineState;
friend class CompoundStatementIndenter;
}; };
struct UnwrappedLineNode { struct UnwrappedLineNode {

View File

@ -6935,6 +6935,91 @@ TEST_F(FormatTest, AllmanBraceBreaking) {
BreakBeforeBraceShortIfs); BreakBeforeBraceShortIfs);
} }
TEST_F(FormatTest, GNUBraceBreaking) {
FormatStyle GNUBraceStyle = getLLVMStyle();
GNUBraceStyle.BreakBeforeBraces = FormatStyle::BS_GNU;
verifyFormat("namespace a\n"
"{\n"
"class A\n"
"{\n"
" void f()\n"
" {\n"
" int a;\n"
" {\n"
" int b;\n"
" }\n"
" if (true)\n"
" {\n"
" a();\n"
" b();\n"
" }\n"
" }\n"
" void g() { return; }\n"
"}\n"
"}",
GNUBraceStyle);
verifyFormat("void f()\n"
"{\n"
" if (true)\n"
" {\n"
" a();\n"
" }\n"
" else if (false)\n"
" {\n"
" b();\n"
" }\n"
" else\n"
" {\n"
" c();\n"
" }\n"
"}\n",
GNUBraceStyle);
verifyFormat("void f()\n"
"{\n"
" for (int i = 0; i < 10; ++i)\n"
" {\n"
" a();\n"
" }\n"
" while (false)\n"
" {\n"
" b();\n"
" }\n"
" do\n"
" {\n"
" c();\n"
" }\n"
" while (false);\n"
"}\n",
GNUBraceStyle);
verifyFormat("void f(int a)\n"
"{\n"
" switch (a)\n"
" {\n"
" case 0:\n"
" break;\n"
" case 1:\n"
" {\n"
" break;\n"
" }\n"
" case 2:\n"
" {\n"
" }\n"
" break;\n"
" default:\n"
" break;\n"
" }\n"
"}\n",
GNUBraceStyle);
verifyFormat("enum X\n"
"{\n"
" Y = 0,\n"
"}\n",
GNUBraceStyle);
}
TEST_F(FormatTest, CatchExceptionReferenceBinding) { TEST_F(FormatTest, CatchExceptionReferenceBinding) {
verifyFormat("void f() {\n" verifyFormat("void f() {\n"
" try {\n" " try {\n"
@ -7132,6 +7217,9 @@ TEST_F(FormatTest, ParsesConfiguration) {
FormatStyle::BS_Linux); FormatStyle::BS_Linux);
CHECK_PARSE("BreakBeforeBraces: Stroustrup", BreakBeforeBraces, CHECK_PARSE("BreakBeforeBraces: Stroustrup", BreakBeforeBraces,
FormatStyle::BS_Stroustrup); FormatStyle::BS_Stroustrup);
CHECK_PARSE("BreakBeforeBraces: Allman", BreakBeforeBraces,
FormatStyle::BS_Allman);
CHECK_PARSE("BreakBeforeBraces: GNU", BreakBeforeBraces, FormatStyle::BS_GNU);
Style.NamespaceIndentation = FormatStyle::NI_All; Style.NamespaceIndentation = FormatStyle::NI_All;
CHECK_PARSE("NamespaceIndentation: None", NamespaceIndentation, CHECK_PARSE("NamespaceIndentation: None", NamespaceIndentation,