Skip to content

Commit ab71971

Browse files
authored
prefer-spread: Ignore Array#join().concat() and (a + b).concat() (#1859)
1 parent c32e02e commit ab71971

File tree

4 files changed

+47
-11
lines changed

4 files changed

+47
-11
lines changed

rules/prefer-spread.js

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22
const {isParenthesized, getStaticValue, isCommaToken, hasSideEffect} = require('eslint-utils');
3-
const {methodCallSelector, not} = require('./selectors/index.js');
3+
const {methodCallSelector} = require('./selectors/index.js');
44
const needsSemicolon = require('./utils/needs-semicolon.js');
55
const {getParenthesizedRange, getParenthesizedText} = require('./utils/parentheses.js');
66
const shouldAddParenthesesToSpreadElementArgument = require('./utils/should-add-parentheses-to-spread-element-argument.js');
@@ -11,6 +11,7 @@ const {
1111
removeMethodCall,
1212
} = require('./fix/index.js');
1313
const {isLiteral} = require('./ast/index.js');
14+
const isMethodNamed = require('./utils/is-method-named.js');
1415

1516
const ERROR_ARRAY_FROM = 'array-from';
1617
const ERROR_ARRAY_CONCAT = 'array-concat';
@@ -44,15 +45,7 @@ const arrayFromCallSelector = [
4445
'[arguments.0.type!="ObjectExpression"]',
4546
].join('');
4647

47-
const arrayConcatCallSelector = [
48-
methodCallSelector('concat'),
49-
not(
50-
[
51-
'Literal',
52-
'TemplateLiteral',
53-
].map(type => `[callee.object.type="${type}"]`),
54-
),
55-
].join('');
48+
const arrayConcatCallSelector = methodCallSelector('concat');
5649

5750
const arraySliceCallSelector = [
5851
methodCallSelector({
@@ -320,6 +313,26 @@ function isClassName(node) {
320313
return /^[A-Z]./.test(name) && name.toUpperCase() !== name;
321314
}
322315

316+
function isNotArray(node, scope) {
317+
if (
318+
node.type === 'TemplateLiteral'
319+
|| node.type === 'Literal'
320+
|| node.type === 'BinaryExpression'
321+
|| isClassName(node)
322+
// `foo.join()`
323+
|| (isMethodNamed(node, 'join') && node.arguments.length <= 1)
324+
) {
325+
return true;
326+
}
327+
328+
const staticValue = getStaticValue(node, scope);
329+
if (staticValue && !Array.isArray(staticValue.value)) {
330+
return true;
331+
}
332+
333+
return false;
334+
}
335+
323336
/** @param {import('eslint').Rule.RuleContext} context */
324337
const create = context => {
325338
const sourceCode = context.getSourceCode();
@@ -335,7 +348,7 @@ const create = context => {
335348
[arrayConcatCallSelector](node) {
336349
const {object} = node.callee;
337350

338-
if (isClassName(object)) {
351+
if (isNotArray(object, context.getScope())) {
339352
return;
340353
}
341354

test/prefer-spread.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,11 @@ test.snapshot({
180180
'Foo.concat(1)',
181181
'FooBar.concat(1)',
182182
'global.Buffer.concat([])',
183+
// #1809
184+
'["1", "2"].join(",").concat("...")',
185+
'foo.join(",").concat("...")',
186+
'foo.join().concat(bar)',
187+
'(a + b).concat(c)',
183188
],
184189
invalid: [
185190
'[1].concat(2)',
@@ -288,6 +293,8 @@ test.snapshot({
288293
const baz = [2];
289294
call(foo, ...[bar].concat(baz));
290295
`,
296+
// This not considered `Array#join()` since there are more than one argument
297+
'foo.join(foo, bar).concat("...")',
291298
],
292299
});
293300

test/snapshots/prefer-spread.mjs.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,22 @@ Generated by [AVA](https://avajs.dev).
20342034
| ^^^^^^ Prefer the spread operator over \`Array#concat(…)\`.␊
20352035
`
20362036

2037+
## Invalid #68
2038+
1 | foo.join(foo, bar).concat("...")
2039+
2040+
> Output
2041+
2042+
`␊
2043+
1 | [...foo.join(foo, bar), "..."]␊
2044+
`
2045+
2046+
> Error 1/1
2047+
2048+
`␊
2049+
> 1 | foo.join(foo, bar).concat("...")␊
2050+
| ^^^^^^ Prefer the spread operator over \`Array#concat(…)\`.␊
2051+
`
2052+
20372053
## Invalid #1
20382054
1 | array.slice()
20392055

56 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)