Initial support for formatting range-based for-loops.
authorDaniel Jasper <djasper@google.com>
Mon, 28 Jan 2013 13:21:16 +0000 (13:21 +0000)
committerDaniel Jasper <djasper@google.com>
Mon, 28 Jan 2013 13:21:16 +0000 (13:21 +0000)
Before (in good cases):
for (auto aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
     : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}
for (auto aaaaaaaaaaaaaaaaaaaa : aaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa,
aaaa)) {}

After:
for (auto aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :
     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}
for (auto aaaaaaaaaaaaaaaaaaaa :
     aaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa, aaaa)) {}

llvm-svn: 173684

clang/lib/Format/Format.cpp
clang/unittests/Format/FormatTest.cpp

index 85f2c32a988df8bfc5b1a479b748edc0686078ed..a6a53f48fd80ed6a6914d74a7864cc2e9b35cdea 100644 (file)
@@ -40,6 +40,7 @@ enum TokenType {
   TT_CastRParen,
   TT_ConditionalExpr,
   TT_CtorInitializerColon,
+  TT_RangeBasedForLoopColon,
   TT_ImplicitStringLiteral,
   TT_LineComment,
   TT_ObjCBlockLParen,
@@ -562,7 +563,8 @@ private:
                                 State.Stack.back().Indent) + 4;
       } else if (Current.Type == TT_ConditionalExpr) {
         State.Column = State.Stack.back().QuestionColumn;
-      } else if (RootToken.is(tok::kw_for) && Previous.is(tok::comma)) {
+      } else if (RootToken.is(tok::kw_for) && ParenLevel == 1 &&
+                 Previous.is(tok::comma)) {
         State.Column = State.ForLoopVariablePos;
       } else if (State.NextToken->Parent->ClosesTemplateDeclaration) {
         State.Column = State.Stack[ParenLevel].Indent - 4;
@@ -713,6 +715,9 @@ private:
     if (Left.is(tok::coloncolon))
       return 500;
 
+    if (Left.Type == TT_RangeBasedForLoopColon)
+      return 5;
+
     // In for-loops, prefer breaking at ',' and ';'.
     if (RootToken.is(tok::kw_for) &&
         (Left.isNot(tok::comma) && Left.isNot(tok::semi)))
@@ -869,7 +874,7 @@ public:
   public:
     AnnotatingParser(AnnotatedToken &RootToken)
         : CurrentToken(&RootToken), KeywordVirtualFound(false),
-          ColonIsObjCMethodExpr(false) {}
+          ColonIsObjCMethodExpr(false), ColonIsForRangeExpr(false) {}
 
     /// \brief A helper class to manage AnnotatingParser::ColonIsObjCMethodExpr.
     struct ObjCSelectorRAII {
@@ -1077,8 +1082,10 @@ public:
         // Colons from ?: are handled in parseConditional().
         if (Tok->Parent->is(tok::r_paren))
           Tok->Type = TT_CtorInitializerColon;
-        if (ColonIsObjCMethodExpr)
+        else if (ColonIsObjCMethodExpr)
           Tok->Type = TT_ObjCMethodExpr;
+        else if (ColonIsForRangeExpr)
+          Tok->Type = TT_RangeBasedForLoopColon;
         break;
       case tok::kw_if:
       case tok::kw_while:
@@ -1088,6 +1095,12 @@ public:
             return false;
         }
         break;
+      case tok::kw_for:
+        ColonIsForRangeExpr = true;
+        next();
+        if (!parseParens())
+          return false;
+        break;
       case tok::l_paren:
         if (!parseParens())
           return false;
@@ -1238,6 +1251,7 @@ public:
     AnnotatedToken *CurrentToken;
     bool KeywordVirtualFound;
     bool ColonIsObjCMethodExpr;
+    bool ColonIsForRangeExpr;
   };
 
   void calculateExtraInformation(AnnotatedToken &Current) {
@@ -1599,6 +1613,8 @@ private:
       return true;
     if (Right.Type == TT_ConditionalExpr || Right.is(tok::question))
       return true;
+    if (Left.Type == TT_RangeBasedForLoopColon)
+      return true;
     if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser ||
         Left.Type == TT_UnaryOperator || Left.Type == TT_ConditionalExpr ||
         Left.is(tok::question))
index 240ce1aeadf754d83d2586384c24614b2079a719..c1430193eb6f88ad5cdd5cc743e40f6dc69c8b4a 100644 (file)
@@ -241,6 +241,13 @@ TEST_F(FormatTest, FormatsForLoop) {
       "     ++IIIII) {\n}");
 }
 
+TEST_F(FormatTest, RangeBasedForLoops) {
+  verifyFormat("for (auto aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n"
+               "     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n}");
+  verifyFormat("for (auto aaaaaaaaaaaaaaaaaaaaa :\n"
+               "     aaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaa, aaaaaaaaaaaaa)) {\n}");
+}
+
 TEST_F(FormatTest, FormatsWhileLoop) {
   verifyFormat("while (true) {\n}");
   verifyFormat("while (true)\n"