aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jasper <djasper@google.com>2012-12-21 14:37:20 +0000
committerDaniel Jasper <djasper@google.com>2012-12-21 14:37:20 +0000
commita324a0e673cf486de281c84af3f09ba58627bbd2 (patch)
tree3a78e438464d2ca56d9cca448510a1a50d6b3437
parentbb6a7e047aefd9ba4bab3ce1dcbb7ce2e2895b07 (diff)
Basic support for formatting for-loops.
We used to not really format them. Now we do: for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), SE = BB->succ_end(); SI != SE; ++SI) { This is just one example and I am sure we still mess some of them up, but it is a step forward. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@170899 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Format/Format.cpp49
-rw-r--r--unittests/Format/FormatTest.cpp9
2 files changed, 51 insertions, 7 deletions
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index d14c1ce5b5..fd08de57ba 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -103,6 +103,8 @@ public:
State.Indent.push_back(Indent + 4);
State.LastSpace.push_back(Indent);
State.FirstLessLess.push_back(0);
+ State.ForLoopVariablePos = 0;
+ State.LineContainsContinuedForLoopSection = false;
// The first token has already been indented and thus consumed.
moveStateToNextToken(State);
@@ -165,6 +167,14 @@ private:
/// on a level.
std::vector<unsigned> FirstLessLess;
+ /// \brief The column of the first variable in a for-loop declaration.
+ ///
+ /// Used to align the second variable if necessary.
+ unsigned ForLoopVariablePos;
+
+ /// \brief \c true if this line contains a continued for-loop section.
+ bool LineContainsContinuedForLoopSection;
+
/// \brief Comparison operator to be able to used \c IndentState in \c map.
bool operator<(const IndentState &Other) const {
if (Other.ConsumedTokens != ConsumedTokens)
@@ -189,6 +199,11 @@ private:
if (Other.FirstLessLess[i] != FirstLessLess[i])
return Other.FirstLessLess[i] > FirstLessLess[i];
}
+ if (Other.ForLoopVariablePos != ForLoopVariablePos)
+ return Other.ForLoopVariablePos < ForLoopVariablePos;
+ if (Other.LineContainsContinuedForLoopSection !=
+ LineContainsContinuedForLoopSection)
+ return LineContainsContinuedForLoopSection;
return false;
}
};
@@ -209,19 +224,27 @@ private:
if (Newline) {
if (Current.Tok.is(tok::string_literal) &&
- Previous.Tok.is(tok::string_literal))
+ Previous.Tok.is(tok::string_literal)) {
State.Column = State.Column - Previous.Tok.getLength();
- else if (Current.Tok.is(tok::lessless) &&
- State.FirstLessLess[ParenLevel] != 0)
+ } else if (Current.Tok.is(tok::lessless) &&
+ State.FirstLessLess[ParenLevel] != 0) {
State.Column = State.FirstLessLess[ParenLevel];
- else if (ParenLevel != 0 &&
- (Previous.Tok.is(tok::equal) || Current.Tok.is(tok::arrow) ||
- Current.Tok.is(tok::period)))
+ } else if (ParenLevel != 0 &&
+ (Previous.Tok.is(tok::equal) || Current.Tok.is(tok::arrow) ||
+ Current.Tok.is(tok::period))) {
// Indent and extra 4 spaces after '=' as it continues an expression.
// Don't do that on the top level, as we already indent 4 there.
State.Column = State.Indent[ParenLevel] + 4;
- else
+ } else if (Line.Tokens[0].Tok.is(tok::kw_for) &&
+ Previous.Tok.is(tok::comma)) {
+ State.Column = State.ForLoopVariablePos;
+ } else {
State.Column = State.Indent[ParenLevel];
+ }
+
+ if (Line.Tokens[0].Tok.is(tok::kw_for))
+ State.LineContainsContinuedForLoopSection =
+ Previous.Tok.isNot(tok::semi);
if (!DryRun)
replaceWhitespace(Current, 1, State.Column);
@@ -232,6 +255,9 @@ private:
Annotations[0].Type != TokenAnnotation::TT_ObjCMethodSpecifier)
State.Indent[ParenLevel] += 2;
} else {
+ if (Current.Tok.is(tok::equal) && Line.Tokens[0].Tok.is(tok::kw_for))
+ State.ForLoopVariablePos = State.Column - Previous.Tok.getLength();
+
unsigned Spaces = Annotations[Index].SpaceRequiredBefore ? 1 : 0;
if (Annotations[Index].Type == TokenAnnotation::TT_LineComment)
Spaces = 2;
@@ -290,6 +316,12 @@ private:
"Tried to calculate penalty for splitting after the last token");
const FormatToken &Left = Line.Tokens[Index];
const FormatToken &Right = Line.Tokens[Index + 1];
+
+ // In for-loops, prefer breaking at ',' and ';'.
+ if (Line.Tokens[0].Tok.is(tok::kw_for) &&
+ (Left.Tok.isNot(tok::comma) && Left.Tok.isNot(tok::semi)))
+ return 20;
+
if (Left.Tok.is(tok::semi) || Left.Tok.is(tok::comma))
return 0;
if (Left.Tok.is(tok::equal) || Left.Tok.is(tok::l_paren) ||
@@ -321,6 +353,9 @@ private:
return UINT_MAX;
if (NewLine && !Annotations[State.ConsumedTokens].CanBreakBefore)
return UINT_MAX;
+ if (!NewLine && Line.Tokens[State.ConsumedTokens - 1].Tok.is(tok::semi) &&
+ State.LineContainsContinuedForLoopSection)
+ return UINT_MAX;
unsigned CurrentPenalty = 0;
if (NewLine) {
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 1e92848b8e..c8088e2c0a 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -164,6 +164,15 @@ TEST_F(FormatTest, FormatsForLoop) {
verifyFormat("for (;;) {\n"
" f();\n"
"}");
+
+ verifyFormat(
+ "for (std::vector<UnwrappedLine>::iterator I = UnwrappedLines.begin(),\n"
+ " E = UnwrappedLines.end();\n"
+ " I != E; ++I) {\n}");
+
+ verifyFormat(
+ "for (MachineFun::iterator IIII = PrevIt, EEEE = F.end(); IIII != EEEE;\n"
+ " ++IIIII) {\n}");
}
TEST_F(FormatTest, FormatsWhileLoop) {