[cfe-commits] r170457 - in /cfe/trunk: lib/Format/Format.cpp unittests/Format/FormatTest.cpp
Daniel Jasper
djasper at google.com
Tue Dec 18 13:05:13 PST 2012
Author: djasper
Date: Tue Dec 18 15:05:13 2012
New Revision: 170457
URL: http://llvm.org/viewvc/llvm-project?rev=170457&view=rev
Log:
Better support for constructor initializers.
We used to format initializers like this (with a sort of hacky implementation):
Constructor()
: Val1(A),
Val2(B) {
and now format like this (with a somewhat better solution):
Constructor()
: Val1(A), Val2(B) {
assuming this would not fit on a single line. Also added tests.
As a side effect we now first analyze whether an UnwrappedLine needs to be
split at all. If not, not splitting it is the best solution by definition. As
this should be a very common case in normal code, not exploring the entire
solution space can provide significant speedup.
Modified:
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/unittests/Format/FormatTest.cpp
Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=170457&r1=170456&r2=170457&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Tue Dec 18 15:05:13 2012
@@ -37,6 +37,7 @@
TT_OverloadedOperator,
TT_PointerOrReference,
TT_ConditionalExpr,
+ TT_CtorInitializerColon,
TT_LineComment,
TT_BlockComment
};
@@ -73,7 +74,6 @@
}
struct OptimizationParameters {
- unsigned PenaltyExtraLine;
unsigned PenaltyIndentLevel;
};
@@ -83,13 +83,9 @@
const UnwrappedLine &Line,
const std::vector<TokenAnnotation> &Annotations,
tooling::Replacements &Replaces, bool StructuralError)
- : Style(Style),
- SourceMgr(SourceMgr),
- Line(Line),
- Annotations(Annotations),
- Replaces(Replaces),
+ : Style(Style), SourceMgr(SourceMgr), Line(Line),
+ Annotations(Annotations), Replaces(Replaces),
StructuralError(StructuralError) {
- Parameters.PenaltyExtraLine = 100;
Parameters.PenaltyIndentLevel = 5;
}
@@ -100,8 +96,6 @@
// Initialize state dependent on indent.
IndentState State;
State.Column = Indent;
- State.CtorInitializerOnNewLine = false;
- State.InCtorInitializer = false;
State.ConsumedTokens = 0;
State.Indent.push_back(Indent + 4);
State.LastSpace.push_back(Indent);
@@ -110,11 +104,33 @@
// The first token has already been indented and thus consumed.
moveStateToNextToken(State);
+ // Check whether the UnwrappedLine can be put onto a single line. If so,
+ // this is bound to be the optimal solution (by definition) and we don't
+ // need to analyze the entire solution space.
+ unsigned Columns = State.Column;
+ bool FitsOnALine = true;
+ for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
+ Columns += (Annotations[i].SpaceRequiredBefore ? 1 : 0) +
+ Line.Tokens[i].Tok.getLength();
+ // A special case for the colon of a constructor initializer as this only
+ // needs to be put on a new line if the line needs to be split.
+ if (Columns > Style.ColumnLimit ||
+ (Annotations[i].MustBreakBefore &&
+ Annotations[i].Type != TokenAnnotation::TT_CtorInitializerColon)) {
+ FitsOnALine = false;
+ break;
+ }
+ }
+
// Start iterating at 1 as we have correctly formatted of Token #0 above.
for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
- unsigned NoBreak = calcPenalty(State, false, UINT_MAX);
- unsigned Break = calcPenalty(State, true, NoBreak);
- addTokenToState(Break < NoBreak, false, State);
+ if (FitsOnALine) {
+ addTokenToState(false, false, State);
+ } else {
+ unsigned NoBreak = calcPenalty(State, false, UINT_MAX);
+ unsigned Break = calcPenalty(State, true, NoBreak);
+ addTokenToState(Break < NoBreak, false, State);
+ }
}
}
@@ -146,9 +162,6 @@
/// on a level.
std::vector<unsigned> FirstLessLess;
- bool CtorInitializerOnNewLine;
- bool InCtorInitializer;
-
/// \brief Comparison operator to be able to used \c IndentState in \c map.
bool operator<(const IndentState &Other) const {
if (Other.ConsumedTokens != ConsumedTokens)
@@ -212,11 +225,8 @@
State.LastSpace[ParenLevel] = State.Indent[ParenLevel];
if (Current.Tok.is(tok::colon) &&
- Annotations[Index].Type != TokenAnnotation::TT_ConditionalExpr) {
+ Annotations[Index].Type != TokenAnnotation::TT_ConditionalExpr)
State.Indent[ParenLevel] += 2;
- State.CtorInitializerOnNewLine = true;
- State.InCtorInitializer = true;
- }
} else {
unsigned Spaces = Annotations[Index].SpaceRequiredBefore ? 1 : 0;
if (Annotations[Index].Type == TokenAnnotation::TT_LineComment)
@@ -228,10 +238,7 @@
if (Previous.Tok.is(tok::l_paren) ||
Annotations[Index - 1].Type == TokenAnnotation::TT_TemplateOpener)
State.Indent[ParenLevel] = State.Column;
- if (Current.Tok.is(tok::colon)) {
- State.Indent[ParenLevel] = State.Column + 3;
- State.InCtorInitializer = true;
- }
+
// Top-level spaces are exempt as that mostly leads to better results.
State.Column += Spaces;
if (Spaces > 0 && ParenLevel != 0)
@@ -279,10 +286,8 @@
"Tried to calculate penalty for splitting after the last token");
const FormatToken &Left = Line.Tokens[Index];
const FormatToken &Right = Line.Tokens[Index + 1];
- if (Left.Tok.is(tok::semi))
+ if (Left.Tok.is(tok::semi) || Left.Tok.is(tok::comma))
return 0;
- if (Left.Tok.is(tok::comma))
- return 1;
if (Left.Tok.is(tok::equal) || Left.Tok.is(tok::l_paren) ||
Left.Tok.is(tok::pipepipe) || Left.Tok.is(tok::ampamp))
return 2;
@@ -313,18 +318,10 @@
if (NewLine && !Annotations[State.ConsumedTokens].CanBreakBefore)
return UINT_MAX;
- if (State.ConsumedTokens > 0 && !NewLine &&
- State.CtorInitializerOnNewLine &&
- Line.Tokens[State.ConsumedTokens - 1].Tok.is(tok::comma))
- return UINT_MAX;
-
- if (NewLine && State.InCtorInitializer && !State.CtorInitializerOnNewLine)
- return UINT_MAX;
-
unsigned CurrentPenalty = 0;
if (NewLine) {
CurrentPenalty += Parameters.PenaltyIndentLevel * State.Indent.size() +
- Parameters.PenaltyExtraLine + splitPenalty(State.ConsumedTokens - 1);
+ splitPenalty(State.ConsumedTokens - 1);
}
addTokenToState(NewLine, true, State);
@@ -413,9 +410,7 @@
public:
TokenAnnotator(const UnwrappedLine &Line, const FormatStyle &Style,
SourceManager &SourceMgr)
- : Line(Line),
- Style(Style),
- SourceMgr(SourceMgr) {
+ : Line(Line), Style(Style), SourceMgr(SourceMgr) {
}
/// \brief A parser that gathers additional information about tokens.
@@ -427,9 +422,7 @@
public:
AnnotatingParser(const SmallVector<FormatToken, 16> &Tokens,
std::vector<TokenAnnotation> &Annotations)
- : Tokens(Tokens),
- Annotations(Annotations),
- Index(0) {
+ : Tokens(Tokens), Annotations(Annotations), Index(0) {
}
bool parseAngle() {
@@ -496,6 +489,10 @@
switch (Tokens[CurrentIndex].Tok.getKind()) {
case tok::l_paren:
parseParens();
+ if (Index < Tokens.size() && Tokens[Index].Tok.is(tok::colon)) {
+ Annotations[Index].Type = TokenAnnotation::TT_CtorInitializerColon;
+ next();
+ }
break;
case tok::l_square:
parseSquare();
@@ -557,7 +554,10 @@
Annotation.CanBreakBefore =
canBreakBetween(Line.Tokens[i - 1], Line.Tokens[i]);
- if (Line.Tokens[i].Tok.is(tok::colon)) {
+ if (Annotation.Type == TokenAnnotation::TT_CtorInitializerColon) {
+ Annotation.MustBreakBefore = true;
+ Annotation.SpaceRequiredBefore = true;
+ } else if (Line.Tokens[i].Tok.is(tok::colon)) {
Annotation.SpaceRequiredBefore =
Line.Tokens[0].Tok.isNot(tok::kw_case) && i != e - 1;
} else if (Annotations[i - 1].Type == TokenAnnotation::TT_UnaryOperator) {
@@ -769,9 +769,7 @@
class LexerBasedFormatTokenSource : public FormatTokenSource {
public:
LexerBasedFormatTokenSource(Lexer &Lex, SourceManager &SourceMgr)
- : GreaterStashed(false),
- Lex(Lex),
- SourceMgr(SourceMgr),
+ : GreaterStashed(false), Lex(Lex), SourceMgr(SourceMgr),
IdentTable(Lex.getLangOpts()) {
Lex.SetKeepWhitespaceMode(true);
}
@@ -831,10 +829,7 @@
public:
Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr,
const std::vector<CharSourceRange> &Ranges)
- : Style(Style),
- Lex(Lex),
- SourceMgr(SourceMgr),
- Ranges(Ranges),
+ : Style(Style), Lex(Lex), SourceMgr(SourceMgr), Ranges(Ranges),
StructuralError(false) {
}
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=170457&r1=170456&r2=170457&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Tue Dec 18 15:05:13 2012
@@ -374,6 +374,41 @@
" parameter, parameter, parameter)), SecondLongCall(parameter));");
}
+TEST_F(FormatTest, ConstructorInitializers) {
+ verifyFormat("Constructor() : Initializer(FitsOnTheLine) {\n}");
+
+ verifyFormat(
+ "SomeClass::Constructor()\n"
+ " : aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {\n"
+ "}");
+
+ verifyFormat(
+ "SomeClass::Constructor()\n"
+ " : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {\n"
+ "}");
+
+ verifyFormat("Constructor()\n"
+ " : aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaaaaaaaaaaaa() {\n"
+ "}");
+
+ // Here a line could be saved by splitting the second initializer onto two
+ // lines, but that is not desireable.
+ verifyFormat("Constructor()\n"
+ " : aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaa(aaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaaaaaaaaaat(aaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
+ "}");
+
+ verifyGoogleFormat("MyClass::MyClass(int var)\n"
+ " : some_var_(var), // 4 space indent\n"
+ " some_other_var_(var + 1) { // lined up\n"
+ "}");
+}
+
TEST_F(FormatTest, BreaksAsHighAsPossible) {
verifyFormat(
"if ((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaa) ||\n"
@@ -461,13 +496,11 @@
}
TEST_F(FormatTest, WrapsAtFunctionCallsIfNecessary) {
- verifyFormat(
- "LoooooooooooooooooooooooooooooooooooooongObject\n"
- " .looooooooooooooooooooooooooooooooooooooongFunction();");
+ verifyFormat("LoooooooooooooooooooooooooooooooooooooongObject\n"
+ " .looooooooooooooooooooooooooooooooooooooongFunction();");
- verifyFormat(
- "LoooooooooooooooooooooooooooooooooooooongObject\n"
- " ->looooooooooooooooooooooooooooooooooooooongFunction();");
+ verifyFormat("LoooooooooooooooooooooooooooooooooooooongObject\n"
+ " ->looooooooooooooooooooooooooooooooooooooongFunction();");
verifyFormat(
"LooooooooooooooooooooooooooooooooongObject->shortFunction(Parameter1,\n"
@@ -485,10 +518,9 @@
"function(LoooooooooooooooooooooooooooooooooooongObject\n"
" ->loooooooooooooooooooooooooooooooooooooooongFunction());");
- verifyFormat(
- "if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaa) ||\n"
- " aaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
- "}");
+ verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaa) ||\n"
+ " aaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
+ "}");
}
TEST_F(FormatTest, UnderstandsTemplateParameters) {
More information about the cfe-commits
mailing list