Author: mprobst Date: Mon May 15 06:15:29 2017 New Revision: 303049 URL: http://llvm.org/viewvc/llvm-project?rev=303049&view=rev Log: JavaScript allows parameter lists to include trailing commas:
myFunction(param1, param2,); For symmetry with other parenthesized lists ([...], {...}), clang-format should wrap parenthesized lists one-per-line if they contain a trailing comma: myFunction( param1, param2, ); This is particularly useful in function declarations or calls with many arguments, e.g. commonly in constructors. Differential Revision: https://reviews.llvm.org/D33023 Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp cfe/trunk/lib/Format/TokenAnnotator.cpp cfe/trunk/unittests/Format/FormatTest.cpp cfe/trunk/unittests/Format/FormatTestJS.cpp Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=303049&r1=303048&r2=303049&view=diff ============================================================================== --- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original) +++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Mon May 15 06:15:29 2017 @@ -674,6 +674,8 @@ unsigned ContinuationIndenter::getNewLin return State.Stack[State.Stack.size() - 2].LastSpace; return State.FirstIndent; } + if (Current.is(tok::r_paren) && State.Stack.size() > 1) + return State.Stack[State.Stack.size() - 2].LastSpace; if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope()) return State.Stack[State.Stack.size() - 2].LastSpace; if (Current.is(tok::identifier) && Current.Next && @@ -1038,13 +1040,20 @@ void ContinuationIndenter::moveStatePast NestedBlockIndent = Column; } + bool EndsInComma = + Current.MatchingParen && + Current.MatchingParen->getPreviousNonComment() && + Current.MatchingParen->getPreviousNonComment()->is(tok::comma); + AvoidBinPacking = + (Style.Language == FormatStyle::LK_JavaScript && EndsInComma) || (State.Line->MustBeDeclaration && !Style.BinPackParameters) || (!State.Line->MustBeDeclaration && !Style.BinPackArguments) || (Style.ExperimentalAutoDetectBinPacking && (Current.PackingKind == PPK_OnePerLine || (!BinPackInconclusiveFunctions && Current.PackingKind == PPK_Inconclusive))); + if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen) { if (Style.ColumnLimit) { // If this '[' opens an ObjC call, determine whether all parameters fit @@ -1065,6 +1074,9 @@ void ContinuationIndenter::moveStatePast } } } + + if (Style.Language == FormatStyle::LK_JavaScript && EndsInComma) + BreakBeforeParameter = true; } // Generally inherit NoLineBreak from the current scope to nested scope. // However, don't do this for non-empty nested blocks, dict literals and Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=303049&r1=303048&r2=303049&view=diff ============================================================================== --- cfe/trunk/lib/Format/TokenAnnotator.cpp (original) +++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon May 15 06:15:29 2017 @@ -2463,16 +2463,20 @@ bool TokenAnnotator::mustBreakBefore(con return true; } - // If the last token before a '}' is a comma or a trailing comment, the - // intention is to insert a line break after it in order to make shuffling - // around entries easier. + // If the last token before a '}', ']', or ')' is a comma or a trailing + // comment, the intention is to insert a line break after it in order to make + // shuffling around entries easier. const FormatToken *BeforeClosingBrace = nullptr; - if (Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) && + if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) || + (Style.Language == FormatStyle::LK_JavaScript && + Left.is(tok::l_paren))) && Left.BlockKind != BK_Block && Left.MatchingParen) BeforeClosingBrace = Left.MatchingParen->Previous; else if (Right.MatchingParen && - Right.MatchingParen->isOneOf(tok::l_brace, - TT_ArrayInitializerLSquare)) + (Right.MatchingParen->isOneOf(tok::l_brace, + TT_ArrayInitializerLSquare) || + (Style.Language == FormatStyle::LK_JavaScript && + Right.MatchingParen->is(tok::l_paren)))) BeforeClosingBrace = &Left; if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) || BeforeClosingBrace->isTrailingComment())) Modified: cfe/trunk/unittests/Format/FormatTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=303049&r1=303048&r2=303049&view=diff ============================================================================== --- cfe/trunk/unittests/Format/FormatTest.cpp (original) +++ cfe/trunk/unittests/Format/FormatTest.cpp Mon May 15 06:15:29 2017 @@ -2106,7 +2106,7 @@ TEST_F(FormatTest, LayoutStatementsAroun verifyIncompleteFormat("void f(\n" "#if A\n" - " );\n" + ");\n" "#else\n" "#endif"); } @@ -4475,7 +4475,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarat EXPECT_EQ("static_cast<A< //\n" " B> *>(\n" "\n" - " );", + ");", format("static_cast<A<//\n" " B>*>(\n" "\n" @@ -6567,7 +6567,7 @@ TEST_F(FormatTest, BreaksStringLiteralsW "#if !TEST\n" " _T(\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXn\")\n" "#endif\n" - " );", + ");", format("f(\n" "#if !TEST\n" "_T(\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXn\")\n" @@ -9639,7 +9639,7 @@ TEST_F(FormatTest, FormatsLambdas) { // Other corner cases. verifyFormat("void f() {\n" " bar([]() {} // Did not respect SpacesBeforeTrailingComments\n" - " );\n" + " );\n" "}"); // Lambdas created through weird macros. Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=303049&r1=303048&r2=303049&view=diff ============================================================================== --- cfe/trunk/unittests/Format/FormatTestJS.cpp (original) +++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon May 15 06:15:29 2017 @@ -550,6 +550,30 @@ TEST_F(FormatTestJS, AsyncFunctions) { "}\n"); } +TEST_F(FormatTestJS, FunctionParametersTrailingComma) { + verifyFormat("function trailingComma(\n" + " p1,\n" + " p2,\n" + " p3,\n" + ") {\n" + " a; //\n" + "}\n", + "function trailingComma(p1, p2, p3,) {\n" + " a; //\n" + "}\n"); + verifyFormat("trailingComma(\n" + " p1,\n" + " p2,\n" + " p3,\n" + ");\n", + "trailingComma(p1, p2, p3,);\n"); + verifyFormat("trailingComma(\n" + " p1 // hello\n" + ");\n", + "trailingComma(p1 // hello\n" + ");\n"); +} + TEST_F(FormatTestJS, ArrayLiterals) { verifyFormat("var aaaaa: List<SomeThing> =\n" " [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];"); @@ -691,7 +715,7 @@ TEST_F(FormatTestJS, FunctionLiterals) { "})\n" " .doSomethingElse(\n" " // break\n" - " );"); + " );"); Style.ColumnLimit = 33; verifyFormat("f({a: function() { return 1; }});", Style); @@ -858,7 +882,7 @@ TEST_F(FormatTestJS, ArrowFunctions) { "})\n" " .doSomethingElse(\n" " // break\n" - " );"); + " );"); } TEST_F(FormatTestJS, ReturnStatements) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits