Skip to content

Commit 7ed738a

Browse files
fiskersindresorhus
andauthoredFeb 2, 2023
prefer-negative-index: Check .toSpliced() and .with() (#2031)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
1 parent fcd8934 commit 7ed738a

6 files changed

+135
-7
lines changed
 

‎docs/rules/prefer-negative-index.md

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Prefer negative index over `.length - index` for `{String,Array,TypedArray}#{slice,at}()` and `Array#splice()`
1+
# Prefer negative index over `.length - index` when possible
22

33
💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs).
44

@@ -7,7 +7,25 @@
77
<!-- end auto-generated rule header -->
88
<!-- Do not manually modify this header. Run: `npm run fix:eslint-docs` -->
99

10-
Prefer negative index over calculating from `.length` for [`String#slice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice), [`Array#slice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice), [`TypedArray#slice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice), [`String#at()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/at), [`Array#at()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at), [`TypedArray#at()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/at), and [`Array#splice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)
10+
Prefer negative index over calculating from `.length` for:
11+
12+
- [`String#slice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice)
13+
- [`Array#slice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice)
14+
- [`TypedArray#slice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice)
15+
- [`String#at()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/at)
16+
- [`Array#at()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at)
17+
- [`TypedArray#at()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/at)
18+
- [`Array#splice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)
19+
- [`Array#toSpliced()`](https://github.com/tc39/proposal-change-array-by-copy#overview)
20+
- [`Array#with()`](https://github.com/tc39/proposal-change-array-by-copy#overview)
21+
- [`TypedArray#with()`](https://github.com/tc39/proposal-change-array-by-copy#overview)
22+
23+
<!--
24+
TODO: Use MDN links when available
25+
- [`Array#toSpliced()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSpliced)
26+
- [`Array#with()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/with)
27+
- [`TypedArray#with()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/with)
28+
-->
1129

1230
## Fail
1331

‎readme.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c
134134
| [prefer-modern-math-apis](docs/rules/prefer-modern-math-apis.md) | Prefer modern `Math` APIs over legacy patterns. || 🔧 | |
135135
| [prefer-module](docs/rules/prefer-module.md) | Prefer JavaScript modules (ESM) over CommonJS. || 🔧 | 💡 |
136136
| [prefer-native-coercion-functions](docs/rules/prefer-native-coercion-functions.md) | Prefer using `String`, `Number`, `BigInt`, `Boolean`, and `Symbol` directly. || 🔧 | |
137-
| [prefer-negative-index](docs/rules/prefer-negative-index.md) | Prefer negative index over `.length - index` for `{String,Array,TypedArray}#{slice,at}()` and `Array#splice()`. || 🔧 | |
137+
| [prefer-negative-index](docs/rules/prefer-negative-index.md) | Prefer negative index over `.length - index` when possible. || 🔧 | |
138138
| [prefer-node-protocol](docs/rules/prefer-node-protocol.md) | Prefer using the `node:` protocol when importing Node.js builtin modules. || 🔧 | |
139139
| [prefer-number-properties](docs/rules/prefer-number-properties.md) | Prefer `Number` static properties over global ones. || 🔧 | 💡 |
140140
| [prefer-object-from-entries](docs/rules/prefer-object-from-entries.md) | Prefer using `Object.fromEntries(…)` to transform a list of key-value pairs into an object. || 🔧 | |

‎rules/prefer-negative-index.js

+22-3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ const methods = new Map([
3636
]),
3737
},
3838
],
39+
[
40+
'toSpliced',
41+
{
42+
argumentsIndexes: [0],
43+
supportObjects: new Set([
44+
'Array',
45+
]),
46+
},
47+
],
3948
[
4049
'at',
4150
{
@@ -47,6 +56,16 @@ const methods = new Map([
4756
]),
4857
},
4958
],
59+
[
60+
'with',
61+
{
62+
argumentsIndexes: [0],
63+
supportObjects: new Set([
64+
'Array',
65+
...typedArray,
66+
]),
67+
},
68+
],
5069
]);
5170

5271
const getMemberName = node => {
@@ -92,12 +111,12 @@ function parse(node) {
92111
const parentCallee = callee.object.object;
93112

94113
if (
95-
// [].{slice,splice}
114+
// `[].{slice,splice,toSpliced,at,with}`
96115
(
97116
parentCallee.type === 'ArrayExpression'
98117
&& parentCallee.elements.length === 0
99118
)
100-
// ''.slice
119+
// `''.slice`
101120
|| (
102121
method === 'slice'
103122
&& isLiteral(parentCallee, '')
@@ -175,7 +194,7 @@ module.exports = {
175194
meta: {
176195
type: 'suggestion',
177196
docs: {
178-
description: 'Prefer negative index over `.length - index` for `{String,Array,TypedArray}#{slice,at}()` and `Array#splice()`.',
197+
description: 'Prefer negative index over `.length - index` when possible.',
179198
},
180199
fixable: 'code',
181200
messages,

‎test/prefer-negative-index.mjs

+12-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,13 @@ test({
344344
});
345345

346346
test.snapshot({
347-
valid: [],
347+
valid: [
348+
// There is no `String#{toSpliced,with}`
349+
'String.prototype.toSpliced.call(foo, foo.length - 1)',
350+
'String.prototype.with.call(foo, foo.length - 1)',
351+
// There is no `TypedArray#toSpliced`
352+
'Uint8Array.prototype.toSpliced.call(foo, foo.length - 1)',
353+
],
348354
invalid: [
349355
'foo.slice(foo.length - 2, foo.length - 1)',
350356
'foo.splice(foo.length - 1, 1)',
@@ -361,5 +367,10 @@ test.snapshot({
361367
Array.prototype.at.call(foo, foo.length - 2);
362368
Array.prototype.at.apply(foo, [foo.length - 3]);
363369
`,
370+
'foo.toSpliced(foo.length - 3, foo.length - 6)',
371+
'Array.prototype.toSpliced.call(foo, foo.length - 3, foo.length - 6)',
372+
'[].toSpliced.call(foo, foo.length - 3, foo.length - 6)',
373+
'foo.with(foo.length - 3, foo.length - 6)',
374+
'Array.prototype.with.call(foo, foo.length - 3, foo.length - 6)',
364375
],
365376
});

‎test/snapshots/prefer-negative-index.mjs.md

+80
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,83 @@ Generated by [AVA](https://avajs.dev).
139139
> 3 | Array.prototype.at.apply(foo, [foo.length - 3]);␊
140140
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`at\`.␊
141141
`
142+
143+
## Invalid #8
144+
1 | foo.toSpliced(foo.length - 3, foo.length - 6)
145+
146+
> Output
147+
148+
`␊
149+
1 | foo.toSpliced(- 3, foo.length - 6)␊
150+
`
151+
152+
> Error 1/1
153+
154+
`␊
155+
> 1 | foo.toSpliced(foo.length - 3, foo.length - 6)␊
156+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`toSpliced\`.␊
157+
`
158+
159+
## Invalid #9
160+
1 | Array.prototype.toSpliced.call(foo, foo.length - 3, foo.length - 6)
161+
162+
> Output
163+
164+
`␊
165+
1 | Array.prototype.toSpliced.call(foo, - 3, foo.length - 6)␊
166+
`
167+
168+
> Error 1/1
169+
170+
`␊
171+
> 1 | Array.prototype.toSpliced.call(foo, foo.length - 3, foo.length - 6)␊
172+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`toSpliced\`.␊
173+
`
174+
175+
## Invalid #10
176+
1 | [].toSpliced.call(foo, foo.length - 3, foo.length - 6)
177+
178+
> Output
179+
180+
`␊
181+
1 | [].toSpliced.call(foo, - 3, foo.length - 6)␊
182+
`
183+
184+
> Error 1/1
185+
186+
`␊
187+
> 1 | [].toSpliced.call(foo, foo.length - 3, foo.length - 6)␊
188+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`toSpliced\`.␊
189+
`
190+
191+
## Invalid #11
192+
1 | foo.with(foo.length - 3, foo.length - 6)
193+
194+
> Output
195+
196+
`␊
197+
1 | foo.with(- 3, foo.length - 6)␊
198+
`
199+
200+
> Error 1/1
201+
202+
`␊
203+
> 1 | foo.with(foo.length - 3, foo.length - 6)␊
204+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`with\`.␊
205+
`
206+
207+
## Invalid #12
208+
1 | Array.prototype.with.call(foo, foo.length - 3, foo.length - 6)
209+
210+
> Output
211+
212+
`␊
213+
1 | Array.prototype.with.call(foo, - 3, foo.length - 6)␊
214+
`
215+
216+
> Error 1/1
217+
218+
`␊
219+
> 1 | Array.prototype.with.call(foo, foo.length - 3, foo.length - 6)␊
220+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`with\`.␊
221+
`
271 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)
Please sign in to comment.