From: Daniel Jasper Date: Mon, 28 Jan 2013 13:21:16 +0000 (+0000) Subject: Initial support for formatting range-based for-loops. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3b9a8fc5bee5434bebc9058646896423adac625b;p=clang Initial support for formatting range-based for-loops. 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)) {} git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173684 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 85f2c32a98..a6a53f48fd 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -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)) diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 240ce1aead..c1430193eb 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -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"