Merge pull request babel/eslint-plugin-babel#64 from zertosh/master

Add func-params-comma-dangle rule
This commit is contained in:
Henry Zhu 2016-06-21 16:15:36 -04:00
parent 148e6be60f
commit 8cd329f611
4 changed files with 420 additions and 1 deletions

View File

@ -33,7 +33,8 @@ original ones as well!).
"babel/object-shorthand": 1,
"babel/arrow-parens": 1,
"babel/no-await-in-loop": 1,
"babel/flow-object-type": 1
"babel/flow-object-type": 1,
"babel/func-params-comma-dangle": 1
}
}
```
@ -57,3 +58,4 @@ the current JavaScript standard or supported by `eslint`.
- `babel/flow-object-type`: Require a particular separator between properties in Flow object types. (🛠 )
- Use the option `semicolon` to require semicolons (e.g. `type Foo = { bar: number; baz: string }`).
- Use the option `comma` to require commas (e.g. `type Foo = { bar: number, baz: string }`).
- `babel/func-params-comma-dangle`: Require or forbid trailing commas for function paramater lists. Behaves like, and takes the same options as, `eslint`'s [`comma-dangle`](http://eslint.org/docs/rules/comma-dangle). (🛠 )

View File

@ -10,6 +10,7 @@ module.exports = {
'arrow-parens': require('./rules/arrow-parens'),
'no-await-in-loop': require('./rules/no-await-in-loop'),
'flow-object-type': require('./rules/flow-object-type'),
'func-params-comma-dangle': require('./rules/func-params-comma-dangle'),
},
rulesConfig: {
'generator-star-spacing': 0,
@ -20,5 +21,6 @@ module.exports = {
'arrow-parens': 0,
'no-await-in-loop': 0,
'flow-object-type': 0,
'func-params-comma-dangle': 0,
}
};

View File

@ -0,0 +1,137 @@
'use strict';
// Based on https://github.com/eslint/eslint/blob/v2.11.1/lib/rules/comma-dangle.js
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
function last(arr) {
return arr.length !== 0 ? arr[arr.length - 1] : undefined;
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
var mode = context.options[0];
var UNEXPECTED_MESSAGE = 'Unexpected trailing comma.';
var MISSING_MESSAGE = 'Missing trailing comma.';
function isMultiline(node) {
var lastItem = last(node.params || node.arguments);
if (!lastItem) {
return false;
}
var sourceCode = context.getSourceCode();
var penultimateToken = sourceCode.getLastToken(lastItem);
var lastToken = sourceCode.getTokenAfter(penultimateToken);
if (lastToken.value === ',') {
penultimateToken = lastToken;
lastToken = sourceCode.getTokenAfter(lastToken);
}
return lastToken.loc.end.line !== penultimateToken.loc.end.line;
}
function forbidTrailingComma(node) {
var lastItem = last(node.params || node.arguments);
if (!lastItem) {
return;
}
var sourceCode = context.getSourceCode();
var trailingToken = sourceCode.getTokenAfter(lastItem);
if (trailingToken.value === ',') {
context.report({
node: lastItem,
loc: trailingToken.loc.start,
message: UNEXPECTED_MESSAGE,
fix: function(fixer) {
return fixer.remove(trailingToken);
}
});
}
}
function forceTrailingComma(node) {
var lastItem = last(node.params || node.arguments);
if (!lastItem) {
return;
}
// `f(...a,)` is ok, but `function f(...a,) {}` is invalid syntax.
if (lastItem.type === 'RestElement') {
return;
}
var sourceCode = context.getSourceCode();
var penultimateToken = lastItem;
var trailingToken = sourceCode.getTokenAfter(lastItem);
// `f = a, => {}` is invalid syntax.
if (node.type === 'ArrowFunctionExpression' &&
node.params.length === 1 &&
sourceCode.getTokenBefore(lastItem).value !== '(') {
return;
}
if (trailingToken.value !== ',') {
context.report({
node: lastItem,
loc: lastItem.loc.end,
message: MISSING_MESSAGE,
fix: function(fixer) {
return fixer.insertTextAfter(penultimateToken, ',');
}
});
}
}
function forceTrailingCommaIfMultiline(node) {
if (isMultiline(node)) {
forceTrailingComma(node);
} else {
forbidTrailingComma(node);
}
}
function allowTrailingCommaIfMultiline(node) {
if (!isMultiline(node)) {
forbidTrailingComma(node);
}
}
var checkForTrailingComma;
if (mode === 'always') {
checkForTrailingComma = forceTrailingComma;
} else if (mode === 'always-multiline') {
checkForTrailingComma = forceTrailingCommaIfMultiline;
} else if (mode === 'only-multiline') {
checkForTrailingComma = allowTrailingCommaIfMultiline;
} else {
checkForTrailingComma = forbidTrailingComma;
}
return {
ArrowFunctionExpression: checkForTrailingComma,
FunctionDeclaration: checkForTrailingComma,
FunctionExpression: checkForTrailingComma,
CallExpression: checkForTrailingComma,
NewExpression: checkForTrailingComma,
};
};
module.exports.fixable = 'code';
module.exports.schema = [
{
enum: ['always', 'always-multiline', 'only-multiline', 'never']
}
];

View File

@ -0,0 +1,278 @@
'use strict';
var rule = require('../rules/func-params-comma-dangle');
var RuleTester = require('eslint').RuleTester;
var MISSING_I = [{message: 'Missing trailing comma.', type: 'Identifier'}];
var MISSING_AP = [{message: 'Missing trailing comma.', type: 'AssignmentPattern'}];
var MISSING_SE = [{message: 'Missing trailing comma.', type: 'SpreadElement'}];
var UNEXPECTED_I = [{message: 'Unexpected trailing comma.', type: 'Identifier'}];
var UNEXPECTED_AP = [{message: 'Unexpected trailing comma.', type: 'AssignmentPattern'}];
var UNEXPECTED_SE = [{message: 'Unexpected trailing comma.', type: 'SpreadElement'}];
var ruleTester = new RuleTester({parser: 'babel-eslint'});
ruleTester.run('func-params-comma-dangle', rule, {
valid: [
{code: 'function f() {}'},
{code: 'function f(\n) {}'},
{code: 'function f(...a) {}'},
{code: 'function f(...a\n) {}'},
{code: 'f()'},
{code: 'f(\n)'},
{code: 'new F()'},
{code: 'new F(\n)'},
// FunctionDeclaration
{code: 'function f(a) {}', options: ['always-multiline']},
{code: 'function f(a) {}', options: ['never']},
{code: 'function f(a) {}', options: ['only-multiline']},
{code: 'function f(a,) {}', options: ['always']},
{code: 'function f(a,\n) {}', options: ['always']},
{code: 'function f(a,\n) {}', options: ['always-multiline']},
{code: 'function f(a,\n) {}', options: ['only-multiline']},
{code: 'function f(a\n) {}', options: ['never']},
{code: 'function f(a\n) {}', options: ['only-multiline']},
{code: 'function f(a=1) {}', options: ['always-multiline']},
{code: 'function f(a=1) {}', options: ['never']},
{code: 'function f(a=1) {}', options: ['only-multiline']},
{code: 'function f(a=1,) {}', options: ['always']},
{code: 'function f(a=1,\n) {}', options: ['always']},
{code: 'function f(a=1,\n) {}', options: ['always-multiline']},
{code: 'function f(a=1,\n) {}', options: ['only-multiline']},
{code: 'function f(a=1\n) {}', options: ['never']},
{code: 'function f(a=1\n) {}', options: ['only-multiline']},
{code: 'function f(a:T) {}', options: ['always-multiline']},
{code: 'function f(a:T) {}', options: ['never']},
{code: 'function f(a:T) {}', options: ['only-multiline']},
{code: 'function f(a:T,) {}', options: ['always']},
{code: 'function f(a:T,\n) {}', options: ['always']},
{code: 'function f(a:T,\n) {}', options: ['always-multiline']},
{code: 'function f(a:T,\n) {}', options: ['only-multiline']},
{code: 'function f(a:T\n) {}', options: ['never']},
{code: 'function f(a:T\n) {}', options: ['only-multiline']},
// FunctionExpression
{code: 'f = function(a) {}', options: ['always-multiline']},
{code: 'f = function(a) {}', options: ['never']},
{code: 'f = function(a) {}', options: ['only-multiline']},
{code: 'f = function(a,) {}', options: ['always']},
{code: 'f = function(a,\n) {}', options: ['always']},
{code: 'f = function(a,\n) {}', options: ['always-multiline']},
{code: 'f = function(a,\n) {}', options: ['only-multiline']},
{code: 'f = function(a\n) {}', options: ['never']},
{code: 'f = function(a\n) {}', options: ['only-multiline']},
{code: 'f = function(a=1) {}', options: ['always-multiline']},
{code: 'f = function(a=1) {}', options: ['never']},
{code: 'f = function(a=1) {}', options: ['only-multiline']},
{code: 'f = function(a=1,) {}', options: ['always']},
{code: 'f = function(a=1,\n) {}', options: ['always']},
{code: 'f = function(a=1,\n) {}', options: ['always-multiline']},
{code: 'f = function(a=1,\n) {}', options: ['only-multiline']},
{code: 'f = function(a=1\n) {}', options: ['never']},
{code: 'f = function(a=1\n) {}', options: ['only-multiline']},
{code: 'f = function(a:T) {}', options: ['always-multiline']},
{code: 'f = function(a:T) {}', options: ['never']},
{code: 'f = function(a:T) {}', options: ['only-multiline']},
{code: 'f = function(a:T,) {}', options: ['always']},
{code: 'f = function(a:T,\n) {}', options: ['always']},
{code: 'f = function(a:T,\n) {}', options: ['always-multiline']},
{code: 'f = function(a:T,\n) {}', options: ['only-multiline']},
{code: 'f = function(a:T\n) {}', options: ['never']},
{code: 'f = function(a:T\n) {}', options: ['only-multiline']},
// ArrowFunctionExpression
{code: 'f = (a) => {}', options: ['always-multiline']},
{code: 'f = (a) => {}', options: ['never']},
{code: 'f = (a) => {}', options: ['only-multiline']},
{code: 'f = (a,) => {}', options: ['always']},
{code: 'f = (a,\n) => {}', options: ['always']},
{code: 'f = (a,\n) => {}', options: ['always-multiline']},
{code: 'f = (a,\n) => {}', options: ['only-multiline']},
{code: 'f = (a\n) => {}', options: ['never']},
{code: 'f = (a\n) => {}', options: ['only-multiline']},
{code: 'f = a => {}', options: ['always-multiline']},
{code: 'f = a => {}', options: ['never']},
{code: 'f = a => {}', options: ['only-multiline']},
{code: 'f = a => {}', options: ['always']},
{code: 'f = (a=1) => {}', options: ['always-multiline']},
{code: 'f = (a=1) => {}', options: ['never']},
{code: 'f = (a=1) => {}', options: ['only-multiline']},
{code: 'f = (a=1,) => {}', options: ['always']},
{code: 'f = (a=1,\n) => {}', options: ['always']},
{code: 'f = (a=1,\n) => {}', options: ['always-multiline']},
{code: 'f = (a=1,\n) => {}', options: ['only-multiline']},
{code: 'f = (a=1\n) => {}', options: ['never']},
{code: 'f = (a=1\n) => {}', options: ['only-multiline']},
{code: 'f = (a:T) => {}', options: ['always-multiline']},
{code: 'f = (a:T) => {}', options: ['never']},
{code: 'f = (a:T) => {}', options: ['only-multiline']},
// Arrow functions with flow types aren't getting the correct loc.
// {code: 'f = (a:T,) => {}', options: ['always']},
// {code: 'f = (a:T,\n) => {}', options: ['always']},
{code: 'f = (a:T,\n) => {}', options: ['always-multiline']},
{code: 'f = (a:T,\n) => {}', options: ['only-multiline']},
{code: 'f = (a:T\n) => {}', options: ['never']},
{code: 'f = (a:T\n) => {}', options: ['only-multiline']},
// CallExpression
{code: 'f(a)', options: ['always-multiline']},
{code: 'f(a)', options: ['never']},
{code: 'f(a)', options: ['only-multiline']},
{code: 'f(a,)', options: ['always']},
{code: 'f(a,\n)', options: ['always']},
{code: 'f(a,\n)', options: ['always-multiline']},
{code: 'f(a,\n)', options: ['only-multiline']},
{code: 'f(a\n)', options: ['never']},
{code: 'f(a\n)', options: ['only-multiline']},
{code: 'f(...a)', options: ['always-multiline']},
{code: 'f(...a)', options: ['never']},
{code: 'f(...a)', options: ['only-multiline']},
{code: 'f(...a,)', options: ['always']},
{code: 'f(...a,\n)', options: ['always']},
{code: 'f(...a,\n)', options: ['always-multiline']},
{code: 'f(...a,\n)', options: ['only-multiline']},
{code: 'f(...a\n)', options: ['never']},
{code: 'f(...a\n)', options: ['only-multiline']},
// NewExpression
{code: 'new F(a)', options: ['always-multiline']},
{code: 'new F(a)', options: ['never']},
{code: 'new F(a)', options: ['only-multiline']},
{code: 'new F(a,)', options: ['always']},
{code: 'new F(a,\n)', options: ['always']},
{code: 'new F(a,\n)', options: ['always-multiline']},
{code: 'new F(a,\n)', options: ['only-multiline']},
{code: 'new F(a\n)', options: ['never']},
{code: 'new F(a\n)', options: ['only-multiline']},
{code: 'new F(...a)', options: ['always-multiline']},
{code: 'new F(...a)', options: ['never']},
{code: 'new F(...a)', options: ['only-multiline']},
{code: 'new F(...a,)', options: ['always']},
{code: 'new F(...a,\n)', options: ['always']},
{code: 'new F(...a,\n)', options: ['always-multiline']},
{code: 'new F(...a,\n)', options: ['only-multiline']},
{code: 'new F(...a\n)', options: ['never']},
{code: 'new F(...a\n)', options: ['only-multiline']},
],
invalid: [
// FunctionDeclaration
{code: 'function f(a) {}', output: 'function f(a,) {}', options: ['always'], errors: MISSING_I},
{code: 'function f(a,) {}', output: 'function f(a) {}', options: ['always-multiline'], errors: UNEXPECTED_I},
{code: 'function f(a,) {}', output: 'function f(a) {}', options: ['only-multiline'], errors: UNEXPECTED_I},
{code: 'function f(a,) {}', output: 'function f(a) {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'function f(a,\n) {}', output: 'function f(a\n) {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'function f(a\n) {}', output: 'function f(a,\n) {}', options: ['always'], errors: MISSING_I},
{code: 'function f(a\n) {}', output: 'function f(a,\n) {}', options: ['always-multiline'], errors: MISSING_I},
{code: 'function f(a=1) {}', output: 'function f(a=1,) {}', options: ['always'], errors: MISSING_AP},
{code: 'function f(a=1,) {}', output: 'function f(a=1) {}', options: ['always-multiline'], errors: UNEXPECTED_AP},
{code: 'function f(a=1,) {}', output: 'function f(a=1) {}', options: ['always-multiline'], errors: UNEXPECTED_AP},
{code: 'function f(a=1,) {}', output: 'function f(a=1) {}', options: ['only-multiline'], errors: UNEXPECTED_AP},
{code: 'function f(a=1,) {}', output: 'function f(a=1) {}', options: ['never'], errors: UNEXPECTED_AP},
{code: 'function f(a=1,\n) {}', output: 'function f(a=1\n) {}', options: ['never'], errors: UNEXPECTED_AP},
{code: 'function f(a=1\n) {}', output: 'function f(a=1,\n) {}', options: ['always'], errors: MISSING_AP},
{code: 'function f(a=1\n) {}', output: 'function f(a=1,\n) {}', options: ['always-multiline'], errors: MISSING_AP},
{code: 'function f(a:T) {}', output: 'function f(a:T,) {}', options: ['always'], errors: MISSING_I},
{code: 'function f(a:T,) {}', output: 'function f(a:T) {}', options: ['always-multiline'], errors: UNEXPECTED_I},
{code: 'function f(a:T,) {}', output: 'function f(a:T) {}', options: ['only-multiline'], errors: UNEXPECTED_I},
{code: 'function f(a:T,) {}', output: 'function f(a:T) {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'function f(a:T,\n) {}', output: 'function f(a:T\n) {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'function f(a:T\n) {}', output: 'function f(a:T,\n) {}', options: ['always'], errors: MISSING_I},
{code: 'function f(a:T\n) {}', output: 'function f(a:T,\n) {}', options: ['always-multiline'], errors: MISSING_I},
// FunctionExpression
{code: 'f = function f(a) {}', output: 'f = function f(a,) {}', options: ['always'], errors: MISSING_I},
{code: 'f = function f(a,) {}', output: 'f = function f(a) {}', options: ['always-multiline'], errors: UNEXPECTED_I},
{code: 'f = function f(a,) {}', output: 'f = function f(a) {}', options: ['only-multiline'], errors: UNEXPECTED_I},
{code: 'f = function f(a,) {}', output: 'f = function f(a) {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'f = function f(a,\n) {}', output: 'f = function f(a\n) {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'f = function f(a\n) {}', output: 'f = function f(a,\n) {}', options: ['always'], errors: MISSING_I},
{code: 'f = function f(a\n) {}', output: 'f = function f(a,\n) {}', options: ['always-multiline'], errors: MISSING_I},
{code: 'f = function f(a=1) {}', output: 'f = function f(a=1,) {}', options: ['always'], errors: MISSING_AP},
{code: 'f = function f(a=1,) {}', output: 'f = function f(a=1) {}', options: ['always-multiline'], errors: UNEXPECTED_AP},
{code: 'f = function f(a=1,) {}', output: 'f = function f(a=1) {}', options: ['only-multiline'], errors: UNEXPECTED_AP},
{code: 'f = function f(a=1,) {}', output: 'f = function f(a=1) {}', options: ['never'], errors: UNEXPECTED_AP},
{code: 'f = function f(a=1,\n) {}', output: 'f = function f(a=1\n) {}', options: ['never'], errors: UNEXPECTED_AP},
{code: 'f = function f(a=1\n) {}', output: 'f = function f(a=1,\n) {}', options: ['always'], errors: MISSING_AP},
{code: 'f = function f(a=1\n) {}', output: 'f = function f(a=1,\n) {}', options: ['always-multiline'], errors: MISSING_AP},
{code: 'f = function f(a:T) {}', output: 'f = function f(a:T,) {}', options: ['always'], errors: MISSING_I},
{code: 'f = function f(a:T,) {}', output: 'f = function f(a:T) {}', options: ['always-multiline'], errors: UNEXPECTED_I},
{code: 'f = function f(a:T,) {}', output: 'f = function f(a:T) {}', options: ['only-multiline'], errors: UNEXPECTED_I},
{code: 'f = function f(a:T,) {}', output: 'f = function f(a:T) {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'f = function f(a:T,\n) {}', output: 'f = function f(a:T\n) {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'f = function f(a:T\n) {}', output: 'f = function f(a:T,\n) {}', options: ['always'], errors: MISSING_I},
{code: 'f = function f(a:T\n) {}', output: 'f = function f(a:T,\n) {}', options: ['always-multiline'], errors: MISSING_I},
// ArrowFunctionExpression
{code: 'f = (a) => {}', output: 'f = (a,) => {}', options: ['always'], errors: MISSING_I},
{code: 'f = (a,) => {}', output: 'f = (a) => {}', options: ['always-multiline'], errors: UNEXPECTED_I},
{code: 'f = (a,) => {}', output: 'f = (a) => {}', options: ['only-multiline'], errors: UNEXPECTED_I},
{code: 'f = (a,) => {}', output: 'f = (a) => {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'f = (a,\n) => {}', output: 'f = (a\n) => {}', options: ['never'], errors: UNEXPECTED_I},
{code: 'f = (a\n) => {}', output: 'f = (a,\n) => {}', options: ['always'], errors: MISSING_I},
{code: 'f = (a\n) => {}', output: 'f = (a,\n) => {}', options: ['always-multiline'], errors: MISSING_I},
{code: 'f = (a=1) => {}', output: 'f = (a=1,) => {}', options: ['always'], errors: MISSING_AP},
{code: 'f = (a=1,) => {}', output: 'f = (a=1) => {}', options: ['always-multiline'], errors: UNEXPECTED_AP},
{code: 'f = (a=1,) => {}', output: 'f = (a=1) => {}', options: ['only-multiline'], errors: UNEXPECTED_AP},
{code: 'f = (a=1,) => {}', output: 'f = (a=1) => {}', options: ['never'], errors: UNEXPECTED_AP},
{code: 'f = (a=1,\n) => {}', output: 'f = (a=1\n) => {}', options: ['never'], errors: UNEXPECTED_AP},
{code: 'f = (a=1\n) => {}', output: 'f = (a=1,\n) => {}', options: ['always'], errors: MISSING_AP},
{code: 'f = (a=1\n) => {}', output: 'f = (a=1,\n) => {}', options: ['always-multiline'], errors: MISSING_AP},
// Arrow functions with flow types aren't getting the correct loc.
// {code: 'f = (a:T) => {}', output: 'f = (a:T,) => {}', options: ['always'], errors: MISSING_I},
// {code: 'f = (a:T,) => {}', output: 'f = (a:T) => {}', options: ['always-multiline'], errors: UNEXPECTED_I},
// {code: 'f = (a:T,) => {}', output: 'f = (a:T) => {}', options: ['only-multiline'], errors: UNEXPECTED_I},
// {code: 'f = (a:T,) => {}', output: 'f = (a:T) => {}', options: ['never'], errors: UNEXPECTED_I},
// {code: 'f = (a:T,\n) => {}', output: 'f = (a:T\n) => {}', options: ['never'], errors: UNEXPECTED_I},
// {code: 'f = (a:T\n) => {}', output: 'f = (a:T,\n) => {}', options: ['always'], errors: MISSING_I},
// {code: 'f = (a:T\n) => {}', output: 'f = (a:T,\n) => {}', options: ['always-multiline'], errors: MISSING_I},
// CallExpression
{code: 'f(a)', output: 'f(a,)', options: ['always'], errors: MISSING_I},
{code: 'f(a,)', output: 'f(a)', options: ['always-multiline'], errors: UNEXPECTED_I},
{code: 'f(a,)', output: 'f(a)', options: ['only-multiline'], errors: UNEXPECTED_I},
{code: 'f(a,)', output: 'f(a)', options: ['never'], errors: UNEXPECTED_I},
{code: 'f(a,\n)', output: 'f(a\n)', options: ['never'], errors: UNEXPECTED_I},
{code: 'f(a\n)', output: 'f(a,\n)', options: ['always'], errors: MISSING_I},
{code: 'f(a\n)', output: 'f(a,\n)', options: ['always-multiline'], errors: MISSING_I},
{code: 'f(...a)', output: 'f(...a,)', options: ['always'], errors: MISSING_SE},
{code: 'f(...a,)', output: 'f(...a)', options: ['always-multiline'], errors: UNEXPECTED_SE},
{code: 'f(...a,)', output: 'f(...a)', options: ['only-multiline'], errors: UNEXPECTED_SE},
{code: 'f(...a,)', output: 'f(...a)', options: ['never'], errors: UNEXPECTED_SE},
{code: 'f(...a,\n)', output: 'f(...a\n)', options: ['never'], errors: UNEXPECTED_SE},
{code: 'f(...a\n)', output: 'f(...a,\n)', options: ['always'], errors: MISSING_SE},
{code: 'f(...a\n)', output: 'f(...a,\n)', options: ['always-multiline'], errors: MISSING_SE},
// NewExpression
{code: 'new F(a)', output: 'new F(a,)', options: ['always'], errors: MISSING_I},
{code: 'new F(a,)', output: 'new F(a)', options: ['always-multiline'], errors: UNEXPECTED_I},
{code: 'new F(a,)', output: 'new F(a)', options: ['only-multiline'], errors: UNEXPECTED_I},
{code: 'new F(a,)', output: 'new F(a)', options: ['never'], errors: UNEXPECTED_I},
{code: 'new F(a,\n)', output: 'new F(a\n)', options: ['never'], errors: UNEXPECTED_I},
{code: 'new F(a\n)', output: 'new F(a,\n)', options: ['always'], errors: MISSING_I},
{code: 'new F(a\n)', output: 'new F(a,\n)', options: ['always-multiline'], errors: MISSING_I},
{code: 'new F(...a)', output: 'new F(...a,)', options: ['always'], errors: MISSING_SE},
{code: 'new F(...a,)', output: 'new F(...a)', options: ['always-multiline'], errors: UNEXPECTED_SE},
{code: 'new F(...a,)', output: 'new F(...a)', options: ['only-multiline'], errors: UNEXPECTED_SE},
{code: 'new F(...a,)', output: 'new F(...a)', options: ['never'], errors: UNEXPECTED_SE},
{code: 'new F(...a,\n)', output: 'new F(...a\n)', options: ['never'], errors: UNEXPECTED_SE},
{code: 'new F(...a\n)', output: 'new F(...a,\n)', options: ['always'], errors: MISSING_SE},
{code: 'new F(...a\n)', output: 'new F(...a,\n)', options: ['always-multiline'], errors: MISSING_SE},
],
});