Skip to content

Commit f9262d9

Browse files
fiskersindresorhus
andauthored
no-array-push-push: Add ignore option (sindresorhus#1168)
Co-authored-by: Sindre Sorhus <[email protected]>
1 parent 3a58802 commit f9262d9

File tree

6 files changed

+198
-10
lines changed

6 files changed

+198
-10
lines changed

docs/rules/no-array-push-push.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,39 @@ foo.push(1);
2727
bar();
2828
foo.push(2);
2929
```
30+
31+
## Options
32+
33+
Type: `object`
34+
35+
### ignore
36+
37+
Type: `string[]`
38+
39+
Ignore objects, `stream`, `this`, `this.stream` are ignored by default.
40+
41+
Example:
42+
43+
```js
44+
{
45+
'unicorn/no-array-push-push': [
46+
'error',
47+
{
48+
ignore: [
49+
'readable',
50+
'foo.stream'
51+
]
52+
}
53+
]
54+
}
55+
```
56+
57+
```js
58+
// eslint unicorn/no-array-push-push: ["error", {"ignore": ["readable"]}]
59+
const {Readable} = require('stream');
60+
61+
const readable = new Readable();
62+
readable.push('one');
63+
readable.push('another');
64+
readable.push(null);
65+
```

rules/no-array-push-push.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const getDocumentationUrl = require('./utils/get-documentation-url');
44
const methodSelector = require('./utils/method-selector');
55
const getCallExpressionArgumentsText = require('./utils/get-call-expression-arguments-text');
66
const isSameReference = require('./utils/is-same-reference');
7+
const {isNodeMatches} = require('./utils/is-node-matches');
78

89
const ERROR = 'error';
910
const SUGGESTION = 'suggestion';
@@ -42,16 +43,25 @@ function getFirstExpression(node, sourceCode) {
4243
}
4344

4445
function create(context) {
46+
const {ignore} = {
47+
ignore: [],
48+
...context.options[0]
49+
};
50+
const ignoredObjects = ['stream', 'this', 'this.stream', ...ignore];
4551
const sourceCode = context.getSourceCode();
4652

4753
return {
4854
[selector](secondExpression) {
49-
const firstExpression = getFirstExpression(secondExpression, sourceCode);
50-
const firstCall = firstExpression.expression;
5155
const secondCall = secondExpression.expression;
56+
const secondCallArray = secondCall.callee.object;
57+
58+
if (isNodeMatches(secondCallArray, ignoredObjects)) {
59+
return;
60+
}
5261

62+
const firstExpression = getFirstExpression(secondExpression, sourceCode);
63+
const firstCall = firstExpression.expression;
5364
const firstCallArray = firstCall.callee.object;
54-
const secondCallArray = secondCall.callee.object;
5565

5666
// Not same array
5767
if (!isSameReference(firstCallArray, secondCallArray)) {
@@ -100,6 +110,19 @@ function create(context) {
100110
};
101111
}
102112

113+
const schema = [
114+
{
115+
type: 'object',
116+
properties: {
117+
ignore: {
118+
type: 'array',
119+
uniqueItems: true
120+
}
121+
},
122+
additionalProperties: false
123+
}
124+
];
125+
103126
module.exports = {
104127
create,
105128
meta: {
@@ -108,6 +131,7 @@ module.exports = {
108131
url: getDocumentationUrl(__filename)
109132
},
110133
fixable: 'code',
111-
messages
134+
messages,
135+
schema
112136
}
113137
};

rules/utils/is-node-matches.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@ function isNodeMatchesNameOrPath(node, nameOrPath) {
1616
}
1717

1818
if (index === 0) {
19-
return node.type === 'Identifier' && node.name === name;
19+
return (
20+
(node.type === 'Identifier' && node.name === name) ||
21+
(name === 'this' && node.type === 'ThisExpression')
22+
);
2023
}
2124

2225
if (
2326
node.type !== 'MemberExpression' ||
2427
node.optional ||
28+
node.computed ||
2529
node.property.type !== 'Identifier' ||
2630
node.property.name !== name
2731
) {

test/no-array-push-push.mjs

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,42 @@ test.snapshot({
4848
outdent`
4949
foo().bar.push(1);
5050
foo().bar.push(2);
51-
`
51+
`,
52+
// Ignored
53+
outdent`
54+
const stream = new Readable();
55+
stream.push('one string');
56+
stream.push('another string');
57+
`,
58+
outdent`
59+
class FooReadable extends Readable {
60+
pushAndEnd(chunk) {
61+
this.push(chunk);
62+
this.push(null);
63+
}
64+
}
65+
`,
66+
outdent`
67+
class Foo {
68+
pushAndEnd(chunk) {
69+
this.stream.push(chunk);
70+
this.stream.push(null);
71+
}
72+
}
73+
`,
74+
{
75+
code: outdent`
76+
foo.push(1);
77+
foo.push(2);
78+
foo.bar.push(1);
79+
foo.bar.push(2);
80+
`,
81+
options: [
82+
{
83+
ignore: ['foo', 'foo.bar']
84+
}
85+
]
86+
}
5287
],
5388
invalid: [
5489
outdent`
@@ -144,7 +179,29 @@ test.snapshot({
144179
outdent`
145180
foo.bar.push(1);
146181
(foo)['bar'].push(2);
147-
`
182+
`,
183+
// Ignored
184+
outdent`
185+
foo.push(1);
186+
foo.push(2);
187+
stream.push(1);
188+
stream.push(2);
189+
`,
190+
{
191+
code: outdent`
192+
foo.bar.push(1);
193+
foo.bar.push(2);
194+
foo.push(1);
195+
foo.push(2);
196+
bar.foo.push(1);
197+
bar.foo.push(2);
198+
`,
199+
options: [
200+
{
201+
ignore: ['foo', 'foo.bar']
202+
}
203+
]
204+
}
148205
]
149206
});
150207

@@ -173,8 +230,8 @@ test({
173230
code: outdent`
174231
class A extends B {
175232
foo() {
176-
this.push(1);
177-
this.push(2);
233+
this.x.push(1);
234+
this.x.push(2);
178235
179236
super.x.push(1);
180237
super.x.push(2);
@@ -205,7 +262,7 @@ test({
205262
output: outdent`
206263
class A extends B {
207264
foo() {
208-
this.push(1, 2);
265+
this.x.push(1, 2);
209266
210267
super.x.push(1, 2);
211268

test/snapshots/no-array-push-push.mjs.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,3 +395,70 @@ Generated by [AVA](https://avajs.dev).
395395
> 2 | (foo)['bar'].push(2);␊
396396
| ^^^^ Do not call \`Array#push()\` multiple times.␊
397397
`
398+
399+
## Invalid #21
400+
1 | foo.push(1);
401+
2 | foo.push(2);
402+
3 | stream.push(1);
403+
4 | stream.push(2);
404+
405+
> Output
406+
407+
`␊
408+
1 | foo.push(1, 2);␊
409+
2 | stream.push(1);␊
410+
3 | stream.push(2);␊
411+
`
412+
413+
> Error 1/1
414+
415+
`␊
416+
1 | foo.push(1);␊
417+
> 2 | foo.push(2);␊
418+
| ^^^^ Do not call \`Array#push()\` multiple times.␊
419+
3 | stream.push(1);␊
420+
4 | stream.push(2);␊
421+
`
422+
423+
## Invalid #22
424+
1 | foo.bar.push(1);
425+
2 | foo.bar.push(2);
426+
3 | foo.push(1);
427+
4 | foo.push(2);
428+
5 | bar.foo.push(1);
429+
6 | bar.foo.push(2);
430+
431+
> Options
432+
433+
`␊
434+
[␊
435+
{␊
436+
"ignore": [␊
437+
"foo",␊
438+
"foo.bar"␊
439+
]␊
440+
}␊
441+
]␊
442+
`
443+
444+
> Output
445+
446+
`␊
447+
1 | foo.bar.push(1);␊
448+
2 | foo.bar.push(2);␊
449+
3 | foo.push(1);␊
450+
4 | foo.push(2);␊
451+
5 | bar.foo.push(1, 2);␊
452+
`
453+
454+
> Error 1/1
455+
456+
`␊
457+
1 | foo.bar.push(1);␊
458+
2 | foo.bar.push(2);␊
459+
3 | foo.push(1);␊
460+
4 | foo.push(2);␊
461+
5 | bar.foo.push(1);␊
462+
> 6 | bar.foo.push(2);␊
463+
| ^^^^ Do not call \`Array#push()\` multiple times.␊
464+
`
170 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)