babel/eslint/babel-eslint-plugin/rules/func-params-comma-dangle.js
2016-06-21 16:15:36 -04:00

138 lines
3.8 KiB
JavaScript

'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']
}
];