Skip to content

Commit

Permalink
prefer-negative-index: Check .toSpliced() and .with() (#2031)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
fisker and sindresorhus committed Feb 2, 2023
1 parent fcd8934 commit 7ed738a
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 7 deletions.
22 changes: 20 additions & 2 deletions docs/rules/prefer-negative-index.md
@@ -1,4 +1,4 @@
# Prefer negative index over `.length - index` for `{String,Array,TypedArray}#{slice,at}()` and `Array#splice()`
# Prefer negative index over `.length - index` when possible

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

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

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)
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)
- [`Array#splice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)
- [`Array#toSpliced()`](https://github.com/tc39/proposal-change-array-by-copy#overview)
- [`Array#with()`](https://github.com/tc39/proposal-change-array-by-copy#overview)
- [`TypedArray#with()`](https://github.com/tc39/proposal-change-array-by-copy#overview)

<!--
TODO: Use MDN links when available
- [`Array#toSpliced()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSpliced)
- [`Array#with()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/with)
- [`TypedArray#with()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/with)
-->

## Fail

Expand Down
2 changes: 1 addition & 1 deletion readme.md
Expand Up @@ -134,7 +134,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c
| [prefer-modern-math-apis](docs/rules/prefer-modern-math-apis.md) | Prefer modern `Math` APIs over legacy patterns. || 🔧 | |
| [prefer-module](docs/rules/prefer-module.md) | Prefer JavaScript modules (ESM) over CommonJS. || 🔧 | 💡 |
| [prefer-native-coercion-functions](docs/rules/prefer-native-coercion-functions.md) | Prefer using `String`, `Number`, `BigInt`, `Boolean`, and `Symbol` directly. || 🔧 | |
| [prefer-negative-index](docs/rules/prefer-negative-index.md) | Prefer negative index over `.length - index` for `{String,Array,TypedArray}#{slice,at}()` and `Array#splice()`. || 🔧 | |
| [prefer-negative-index](docs/rules/prefer-negative-index.md) | Prefer negative index over `.length - index` when possible. || 🔧 | |
| [prefer-node-protocol](docs/rules/prefer-node-protocol.md) | Prefer using the `node:` protocol when importing Node.js builtin modules. || 🔧 | |
| [prefer-number-properties](docs/rules/prefer-number-properties.md) | Prefer `Number` static properties over global ones. || 🔧 | 💡 |
| [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. || 🔧 | |
Expand Down
25 changes: 22 additions & 3 deletions rules/prefer-negative-index.js
Expand Up @@ -36,6 +36,15 @@ const methods = new Map([
]),
},
],
[
'toSpliced',
{
argumentsIndexes: [0],
supportObjects: new Set([
'Array',
]),
},
],
[
'at',
{
Expand All @@ -47,6 +56,16 @@ const methods = new Map([
]),
},
],
[
'with',
{
argumentsIndexes: [0],
supportObjects: new Set([
'Array',
...typedArray,
]),
},
],
]);

const getMemberName = node => {
Expand Down Expand Up @@ -92,12 +111,12 @@ function parse(node) {
const parentCallee = callee.object.object;

if (
// [].{slice,splice}
// `[].{slice,splice,toSpliced,at,with}`
(
parentCallee.type === 'ArrayExpression'
&& parentCallee.elements.length === 0
)
// ''.slice
// `''.slice`
|| (
method === 'slice'
&& isLiteral(parentCallee, '')
Expand Down Expand Up @@ -175,7 +194,7 @@ module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'Prefer negative index over `.length - index` for `{String,Array,TypedArray}#{slice,at}()` and `Array#splice()`.',
description: 'Prefer negative index over `.length - index` when possible.',
},
fixable: 'code',
messages,
Expand Down
13 changes: 12 additions & 1 deletion test/prefer-negative-index.mjs
Expand Up @@ -344,7 +344,13 @@ test({
});

test.snapshot({
valid: [],
valid: [
// There is no `String#{toSpliced,with}`
'String.prototype.toSpliced.call(foo, foo.length - 1)',
'String.prototype.with.call(foo, foo.length - 1)',
// There is no `TypedArray#toSpliced`
'Uint8Array.prototype.toSpliced.call(foo, foo.length - 1)',
],
invalid: [
'foo.slice(foo.length - 2, foo.length - 1)',
'foo.splice(foo.length - 1, 1)',
Expand All @@ -361,5 +367,10 @@ test.snapshot({
Array.prototype.at.call(foo, foo.length - 2);
Array.prototype.at.apply(foo, [foo.length - 3]);
`,
'foo.toSpliced(foo.length - 3, foo.length - 6)',
'Array.prototype.toSpliced.call(foo, foo.length - 3, foo.length - 6)',
'[].toSpliced.call(foo, foo.length - 3, foo.length - 6)',
'foo.with(foo.length - 3, foo.length - 6)',
'Array.prototype.with.call(foo, foo.length - 3, foo.length - 6)',
],
});
80 changes: 80 additions & 0 deletions test/snapshots/prefer-negative-index.mjs.md
Expand Up @@ -139,3 +139,83 @@ Generated by [AVA](https://avajs.dev).
> 3 | Array.prototype.at.apply(foo, [foo.length - 3]);␊
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`at\`.␊
`

## Invalid #8
1 | foo.toSpliced(foo.length - 3, foo.length - 6)

> Output
`␊
1 | foo.toSpliced(- 3, foo.length - 6)␊
`

> Error 1/1
`␊
> 1 | foo.toSpliced(foo.length - 3, foo.length - 6)␊
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`toSpliced\`.␊
`

## Invalid #9
1 | Array.prototype.toSpliced.call(foo, foo.length - 3, foo.length - 6)

> Output
`␊
1 | Array.prototype.toSpliced.call(foo, - 3, foo.length - 6)␊
`

> Error 1/1
`␊
> 1 | Array.prototype.toSpliced.call(foo, foo.length - 3, foo.length - 6)␊
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`toSpliced\`.␊
`

## Invalid #10
1 | [].toSpliced.call(foo, foo.length - 3, foo.length - 6)

> Output
`␊
1 | [].toSpliced.call(foo, - 3, foo.length - 6)␊
`

> Error 1/1
`␊
> 1 | [].toSpliced.call(foo, foo.length - 3, foo.length - 6)␊
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`toSpliced\`.␊
`

## Invalid #11
1 | foo.with(foo.length - 3, foo.length - 6)

> Output
`␊
1 | foo.with(- 3, foo.length - 6)␊
`

> Error 1/1
`␊
> 1 | foo.with(foo.length - 3, foo.length - 6)␊
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`with\`.␊
`

## Invalid #12
1 | Array.prototype.with.call(foo, foo.length - 3, foo.length - 6)

> Output
`␊
1 | Array.prototype.with.call(foo, - 3, foo.length - 6)␊
`

> Error 1/1
`␊
> 1 | Array.prototype.with.call(foo, foo.length - 3, foo.length - 6)␊
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negative index over length minus index for \`with\`.␊
`
Binary file modified test/snapshots/prefer-negative-index.mjs.snap
Binary file not shown.

0 comments on commit 7ed738a

Please sign in to comment.