Skip to content

Commit

Permalink
prefer-spread: Improve auto-fix (#1080)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker committed Jan 29, 2021
1 parent da94ca9 commit e54dc66
Show file tree
Hide file tree
Showing 4 changed files with 478 additions and 15 deletions.
65 changes: 51 additions & 14 deletions rules/prefer-spread.js
Expand Up @@ -5,6 +5,8 @@ const methodSelector = require('./utils/method-selector');
const needsSemicolon = require('./utils/needs-semicolon');
const getParentheses = require('./utils/get-parentheses');
const shouldAddParenthesesToSpreadElementArgument = require('./utils/should-add-parentheses-to-spread-element-argument');
const replaceNodeOrTokenAndSpacesBefore = require('./utils/replace-node-or-token-and-spaces-before');
const removeSpacesAfter = require('./utils/remove-spaces-after');

const ERROR_ARRAY_FROM = 'array-from';
const ERROR_ARRAY_CONCAT = 'array-concat';
Expand Down Expand Up @@ -230,28 +232,63 @@ function getConcatFixableArguments(argumentsList, scope) {
return fixableArguments;
}

function fixArrayFrom(node, sourceCode) {
const [object] = node.arguments;

function getObjectText() {
if (isArrayLiteral(object)) {
return sourceCode.getText(object);
}

const [start, end] = getParenthesizedRange(object, sourceCode);
let text = sourceCode.text.slice(start, end);

if (
!isParenthesized(object, sourceCode) &&
shouldAddParenthesesToSpreadElementArgument(object)
) {
text = `(${text})`;
}

return `[...${text}]`;
}

function * removeObject(fixer) {
yield * replaceNodeOrTokenAndSpacesBefore(object, '', fixer, sourceCode);
const commaToken = sourceCode.getTokenAfter(object, isCommaToken);
yield * replaceNodeOrTokenAndSpacesBefore(commaToken, '', fixer, sourceCode);
yield removeSpacesAfter(commaToken, sourceCode, fixer);
}

return function * (fixer) {
// Fixed code always starts with `[`
if (needsSemicolon(sourceCode.getTokenBefore(node), sourceCode, '[')) {
yield fixer.insertTextBefore(node, ';');
}

const objectText = getObjectText();

if (node.arguments.length === 1) {
yield fixer.replaceText(node, objectText);
return;
}

// `Array.from(object, mapFunction, thisArgument)` -> `[...object].map(mapFunction, thisArgument)`
yield fixer.replaceText(node.callee.object, objectText);
yield fixer.replaceText(node.callee.property, 'map');
yield * removeObject(fixer);
};
}

const create = context => {
const sourceCode = context.getSourceCode();
const getSource = node => sourceCode.getText(node);

return {
[arrayFromCallSelector](node) {
context.report({
node,
messageId: ERROR_ARRAY_FROM,
fix: fixer => {
const [arrayLikeArgument, mapFn, thisArgument] = node.arguments.map(node => getSource(node));
let replacement = `${
needsSemicolon(sourceCode.getTokenBefore(node), sourceCode) ? ';' : ''
}[...${arrayLikeArgument}]`;

if (mapFn) {
const mapArguments = [mapFn, thisArgument].filter(Boolean);
replacement += `.map(${mapArguments.join(', ')})`;
}

return fixer.replaceText(node, replacement);
}
fix: fixArrayFrom(node, sourceCode)
});
},
[arrayConcatCallSelector](node) {
Expand Down
28 changes: 27 additions & 1 deletion test/prefer-spread.js
Expand Up @@ -130,7 +130,33 @@ test.snapshot({
outdent`
const foo = {}
Array.from(arrayLike).forEach(doSomething)
`
`,

'(Array).from(foo)',
'(Array.from)(foo)',
'((Array).from)(foo)',
'(Array).from((0, foo))',
'(Array.from)((0, foo))',
'((Array).from)((0, foo))',
'(Array).from(foo, bar)',
'(Array.from)(foo, bar)',
'((Array).from)(foo, bar)',
'(Array).from((0, foo), bar)',
'(Array.from)((0, foo), bar)',
'((Array).from)((0, foo), bar)',
'(Array).from(foo, bar, baz)',
'(Array.from)(foo, bar, baz)',
'((Array).from)(foo, bar, baz)',
'(Array).from((0, foo), bar, baz)',
'(Array.from)((0, foo), bar, baz)',
'((Array).from)((0, foo), bar, baz)',
'Array.from(a, (0, bar), (0, baz),)',
'Array.from(a ? b : c)',
'Array.from([...a, ...b], b, c)',
'Array.from([1])',
'Array.from([...a, ...b])',
'/* 1 */ Array /* 2 */ .from /* 3 */ ( /* 4 */ a /* 5 */, /* 6 */ b /* 7 */, /* 8 */ c /* 9 */,)',
'/* 1 */ Array /* 2 */ .from /* 3 */ ( /* 4 */ a /* 5 */,)'
]
});

Expand Down

0 comments on commit e54dc66

Please sign in to comment.