138 lines
3.8 KiB
JavaScript
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']
|
|
}
|
|
];
|