forked from OSchip/llvm-project
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 llvm-svn: 303049
This commit is contained in:
parent
4ab5193735
commit
2c1cdae2df
|
@ -674,6 +674,8 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
|
||||||
return State.Stack[State.Stack.size() - 2].LastSpace;
|
return State.Stack[State.Stack.size() - 2].LastSpace;
|
||||||
return State.FirstIndent;
|
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())
|
if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
|
||||||
return State.Stack[State.Stack.size() - 2].LastSpace;
|
return State.Stack[State.Stack.size() - 2].LastSpace;
|
||||||
if (Current.is(tok::identifier) && Current.Next &&
|
if (Current.is(tok::identifier) && Current.Next &&
|
||||||
|
@ -1038,13 +1040,20 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
|
||||||
NestedBlockIndent = Column;
|
NestedBlockIndent = Column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EndsInComma =
|
||||||
|
Current.MatchingParen &&
|
||||||
|
Current.MatchingParen->getPreviousNonComment() &&
|
||||||
|
Current.MatchingParen->getPreviousNonComment()->is(tok::comma);
|
||||||
|
|
||||||
AvoidBinPacking =
|
AvoidBinPacking =
|
||||||
|
(Style.Language == FormatStyle::LK_JavaScript && EndsInComma) ||
|
||||||
(State.Line->MustBeDeclaration && !Style.BinPackParameters) ||
|
(State.Line->MustBeDeclaration && !Style.BinPackParameters) ||
|
||||||
(!State.Line->MustBeDeclaration && !Style.BinPackArguments) ||
|
(!State.Line->MustBeDeclaration && !Style.BinPackArguments) ||
|
||||||
(Style.ExperimentalAutoDetectBinPacking &&
|
(Style.ExperimentalAutoDetectBinPacking &&
|
||||||
(Current.PackingKind == PPK_OnePerLine ||
|
(Current.PackingKind == PPK_OnePerLine ||
|
||||||
(!BinPackInconclusiveFunctions &&
|
(!BinPackInconclusiveFunctions &&
|
||||||
Current.PackingKind == PPK_Inconclusive)));
|
Current.PackingKind == PPK_Inconclusive)));
|
||||||
|
|
||||||
if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen) {
|
if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen) {
|
||||||
if (Style.ColumnLimit) {
|
if (Style.ColumnLimit) {
|
||||||
// If this '[' opens an ObjC call, determine whether all parameters fit
|
// If this '[' opens an ObjC call, determine whether all parameters fit
|
||||||
|
@ -1065,6 +1074,9 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Style.Language == FormatStyle::LK_JavaScript && EndsInComma)
|
||||||
|
BreakBeforeParameter = true;
|
||||||
}
|
}
|
||||||
// Generally inherit NoLineBreak from the current scope to nested scope.
|
// Generally inherit NoLineBreak from the current scope to nested scope.
|
||||||
// However, don't do this for non-empty nested blocks, dict literals and
|
// However, don't do this for non-empty nested blocks, dict literals and
|
||||||
|
|
|
@ -2463,16 +2463,20 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the last token before a '}' is a comma or a trailing comment, the
|
// If the last token before a '}', ']', or ')' is a comma or a trailing
|
||||||
// intention is to insert a line break after it in order to make shuffling
|
// comment, the intention is to insert a line break after it in order to make
|
||||||
// around entries easier.
|
// shuffling around entries easier.
|
||||||
const FormatToken *BeforeClosingBrace = nullptr;
|
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)
|
Left.BlockKind != BK_Block && Left.MatchingParen)
|
||||||
BeforeClosingBrace = Left.MatchingParen->Previous;
|
BeforeClosingBrace = Left.MatchingParen->Previous;
|
||||||
else if (Right.MatchingParen &&
|
else if (Right.MatchingParen &&
|
||||||
Right.MatchingParen->isOneOf(tok::l_brace,
|
(Right.MatchingParen->isOneOf(tok::l_brace,
|
||||||
TT_ArrayInitializerLSquare))
|
TT_ArrayInitializerLSquare) ||
|
||||||
|
(Style.Language == FormatStyle::LK_JavaScript &&
|
||||||
|
Right.MatchingParen->is(tok::l_paren))))
|
||||||
BeforeClosingBrace = &Left;
|
BeforeClosingBrace = &Left;
|
||||||
if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||
|
if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||
|
||||||
BeforeClosingBrace->isTrailingComment()))
|
BeforeClosingBrace->isTrailingComment()))
|
||||||
|
|
|
@ -2106,7 +2106,7 @@ TEST_F(FormatTest, LayoutStatementsAroundPreprocessorDirectives) {
|
||||||
|
|
||||||
verifyIncompleteFormat("void f(\n"
|
verifyIncompleteFormat("void f(\n"
|
||||||
"#if A\n"
|
"#if A\n"
|
||||||
" );\n"
|
");\n"
|
||||||
"#else\n"
|
"#else\n"
|
||||||
"#endif");
|
"#endif");
|
||||||
}
|
}
|
||||||
|
@ -4475,7 +4475,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) {
|
||||||
EXPECT_EQ("static_cast<A< //\n"
|
EXPECT_EQ("static_cast<A< //\n"
|
||||||
" B> *>(\n"
|
" B> *>(\n"
|
||||||
"\n"
|
"\n"
|
||||||
" );",
|
");",
|
||||||
format("static_cast<A<//\n"
|
format("static_cast<A<//\n"
|
||||||
" B>*>(\n"
|
" B>*>(\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -6567,7 +6567,7 @@ TEST_F(FormatTest, BreaksStringLiteralsWithin_TMacro) {
|
||||||
"#if !TEST\n"
|
"#if !TEST\n"
|
||||||
" _T(\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXn\")\n"
|
" _T(\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXn\")\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
" );",
|
");",
|
||||||
format("f(\n"
|
format("f(\n"
|
||||||
"#if !TEST\n"
|
"#if !TEST\n"
|
||||||
"_T(\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXn\")\n"
|
"_T(\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXn\")\n"
|
||||||
|
|
|
@ -550,6 +550,30 @@ TEST_F(FormatTestJS, AsyncFunctions) {
|
||||||
"}\n");
|
"}\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) {
|
TEST_F(FormatTestJS, ArrayLiterals) {
|
||||||
verifyFormat("var aaaaa: List<SomeThing> =\n"
|
verifyFormat("var aaaaa: List<SomeThing> =\n"
|
||||||
" [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
|
" [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
|
||||||
|
|
Loading…
Reference in New Issue