Change clang-format's affinity for breaking after return types.

Function declarations are now broken with the following preferences:
1) break amongst arguments.
2) break after return type.
3) break after (.
4) break before after nested name specifiers.

Options #2 or #3 are preferred over #1 only if a substantial number of
lines can be saved by that.

llvm-svn: 179287
This commit is contained in:
Daniel Jasper 2013-04-11 14:29:13 +00:00
parent 18f0820552
commit 6728fc11bc
3 changed files with 66 additions and 12 deletions

View File

@ -48,7 +48,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.AllowShortIfStatementsOnASingleLine = false; LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
LLVMStyle.ObjCSpaceBeforeProtocolList = true; LLVMStyle.ObjCSpaceBeforeProtocolList = true;
LLVMStyle.PenaltyExcessCharacter = 1000000; LLVMStyle.PenaltyExcessCharacter = 1000000;
LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 5; LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 75;
return LLVMStyle; return LLVMStyle;
} }
@ -68,7 +68,7 @@ FormatStyle getGoogleStyle() {
GoogleStyle.AllowShortIfStatementsOnASingleLine = false; GoogleStyle.AllowShortIfStatementsOnASingleLine = false;
GoogleStyle.ObjCSpaceBeforeProtocolList = false; GoogleStyle.ObjCSpaceBeforeProtocolList = false;
GoogleStyle.PenaltyExcessCharacter = 1000000; GoogleStyle.PenaltyExcessCharacter = 1000000;
GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 100; GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
return GoogleStyle; return GoogleStyle;
} }
@ -1395,7 +1395,7 @@ public:
// Adapt level to the next line if this is a comment. // Adapt level to the next line if this is a comment.
// FIXME: Can/should this be done in the UnwrappedLineParser? // FIXME: Can/should this be done in the UnwrappedLineParser?
const AnnotatedLine* NextNoneCommentLine = NULL; const AnnotatedLine *NextNoneCommentLine = NULL;
for (unsigned i = AnnotatedLines.size() - 1; i > 0; --i) { for (unsigned i = AnnotatedLines.size() - 1; i > 0; --i) {
if (NextNoneCommentLine && AnnotatedLines[i].First.is(tok::comment) && if (NextNoneCommentLine && AnnotatedLines[i].First.is(tok::comment) &&
AnnotatedLines[i].First.Children.empty()) AnnotatedLines[i].First.Children.empty())

View File

@ -81,7 +81,7 @@ public:
AnnotatingParser(SourceManager &SourceMgr, Lexer &Lex, AnnotatedLine &Line, AnnotatingParser(SourceManager &SourceMgr, Lexer &Lex, AnnotatedLine &Line,
IdentifierInfo &Ident_in) IdentifierInfo &Ident_in)
: SourceMgr(SourceMgr), Lex(Lex), Line(Line), CurrentToken(&Line.First), : SourceMgr(SourceMgr), Lex(Lex), Line(Line), CurrentToken(&Line.First),
KeywordVirtualFound(false), Ident_in(Ident_in) { KeywordVirtualFound(false), NameFound(false), Ident_in(Ident_in) {
Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/ false)); Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/ false));
} }
@ -347,7 +347,7 @@ private:
case tok::l_paren: case tok::l_paren:
if (!parseParens()) if (!parseParens())
return false; return false;
if (Line.MustBeDeclaration) if (Line.MustBeDeclaration && NameFound && !Contexts.back().IsExpression)
Line.MightBeFunctionDecl = true; Line.MightBeFunctionDecl = true;
break; break;
case tok::l_square: case tok::l_square:
@ -602,6 +602,7 @@ private:
Current.Parent->Type == TT_TemplateCloser)) { Current.Parent->Type == TT_TemplateCloser)) {
Contexts.back().FirstStartOfName = &Current; Contexts.back().FirstStartOfName = &Current;
Current.Type = TT_StartOfName; Current.Type = TT_StartOfName;
NameFound = true;
} else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) { } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
Current.Type = Current.Type =
determineStarAmpUsage(Current, Contexts.back().IsExpression); determineStarAmpUsage(Current, Contexts.back().IsExpression);
@ -759,6 +760,7 @@ private:
AnnotatedLine &Line; AnnotatedLine &Line;
AnnotatedToken *CurrentToken; AnnotatedToken *CurrentToken;
bool KeywordVirtualFound; bool KeywordVirtualFound;
bool NameFound;
IdentifierInfo &Ident_in; IdentifierInfo &Ident_in;
}; };
@ -916,7 +918,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
// FIXME: Clean up hack of using BindingStrength to find top-level names. // FIXME: Clean up hack of using BindingStrength to find top-level names.
return Style.PenaltyReturnTypeOnItsOwnLine; return Style.PenaltyReturnTypeOnItsOwnLine;
else else
return 100; return 200;
} }
if (Left.is(tok::equal) && Right.is(tok::l_brace)) if (Left.is(tok::equal) && Right.is(tok::l_brace))
return 150; return 150;
@ -954,6 +956,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr) if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
return 20; return 20;
if (Left.is(tok::l_paren) && Line.MightBeFunctionDecl)
return 100;
if (Left.opensScope()) if (Left.opensScope())
return Left.ParameterCount > 1 ? prec::Comma : 20; return Left.ParameterCount > 1 ? prec::Comma : 20;

View File

@ -1199,8 +1199,8 @@ TEST_F(FormatTest, FormatsSmallMacroDefinitionsInSingleLine) {
TEST_F(FormatTest, DoesNotBreakPureVirtualFunctionDefinition) { TEST_F(FormatTest, DoesNotBreakPureVirtualFunctionDefinition) {
verifyFormat( verifyFormat(
"virtual void\n" "virtual void write(ELFWriter *writerrr,\n"
"write(ELFWriter *writerrr, OwningPtr<FileOutputBuffer> &buffer) = 0;"); " OwningPtr<FileOutputBuffer> &buffer) = 0;");
} }
TEST_F(FormatTest, LayoutUnknownPPDirective) { TEST_F(FormatTest, LayoutUnknownPPDirective) {
@ -1700,6 +1700,56 @@ TEST_F(FormatTest, BreaksAsHighAsPossible) {
" Intervals[i - 1].getRange().getLast()) {\n}"); " Intervals[i - 1].getRange().getLast()) {\n}");
} }
TEST_F(FormatTest, BreaksFunctionDeclarations) {
// Principially, we break function declarations in a certain order:
// 1) break amongst arguments.
verifyFormat("Aaaaaaaaaaaaaa bbbbbbbbbbbbbb(Cccccccccccccc cccccccccccccc,\n"
" Cccccccccccccc cccccccccccccc);");
// 2) break after return type.
verifyFormat("Aaaaaaaaaaaaaaaaaaaaaaaa\n"
"bbbbbbbbbbbbbb(Cccccccccccccc cccccccccccccccccccccccccc);");
// 3) break after (.
verifyFormat(
"Aaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbb(\n"
" Cccccccccccccccccccccccccccccc cccccccccccccccccccccccccccccccc);");
// 4) break before after nested name specifiers.
verifyFormat(
"Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
"SomeClasssssssssssssssssssssssssssssssssssssss::\n"
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(Cccccccccccccc cccccccccc);");
// However, there are exceptions, if a sufficient amount of lines can be
// saved.
// FIXME: The precise cut-offs wrt. the number of saved lines might need some
// more adjusting.
verifyFormat("Aaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbb(Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc);");
verifyFormat(
"Aaaaaaaaaaaaaaaaaa\n"
"bbbbbbbbbbbbbb(Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc);");
verifyFormat(
"Aaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc);");
verifyFormat("Aaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(\n"
" Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc,\n"
" Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc);");
}
TEST_F(FormatTest, BreaksDesireably) { TEST_F(FormatTest, BreaksDesireably) {
verifyFormat("if (aaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa) ||\n" verifyFormat("if (aaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa) ||\n"
" aaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa) ||\n" " aaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa) ||\n"
@ -1850,7 +1900,7 @@ TEST_F(FormatTest, DoesNotBreakTrailingAnnotation) {
" aaaaaaaaaaaaaaaaaaaaaaaaa));"); " aaaaaaaaaaaaaaaaaaaaaaaaa));");
verifyFormat("bool aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" verifyFormat("bool aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
" __attribute__((unused));"); " __attribute__((unused));");
// FIXME: This is bad indentation, but generally hard to distinguish from a // FIXME: This is bad indentation, but generally hard to distinguish from a
// function declaration. // function declaration.
verifyFormat( verifyFormat(
@ -2600,9 +2650,9 @@ TEST_F(FormatTest, BreaksLongDeclarations) {
verifyFormat("int *someFunction(int LoooooooooooooooooooongParam1,\n" verifyFormat("int *someFunction(int LoooooooooooooooooooongParam1,\n"
" int LoooooooooooooooooooongParam2) {}"); " int LoooooooooooooooooooongParam2) {}");
verifyFormat( verifyFormat(
"TypeSpecDecl *\n" "TypeSpecDecl *TypeSpecDecl::Create(ASTContext &C, DeclContext *DC,\n"
"TypeSpecDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,\n" " SourceLocation L, IdentifierIn *II,\n"
" IdentifierIn *II, Type *T) {}"); " Type *T) {}");
verifyFormat("ReallyLongReturnType<TemplateParam1, TemplateParam2>\n" verifyFormat("ReallyLongReturnType<TemplateParam1, TemplateParam2>\n"
"ReallyReallyLongFunctionName(\n" "ReallyReallyLongFunctionName(\n"
" const std::string &SomeParameter,\n" " const std::string &SomeParameter,\n"