Skip to content

Commit

Permalink
Add prefer-at rule (#1331)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker authored Jun 3, 2021
1 parent cfd31a5 commit 8ca5b46
Show file tree
Hide file tree
Showing 13 changed files with 1,983 additions and 9 deletions.
2 changes: 1 addition & 1 deletion docs/rules/prefer-array-flat-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ const foo = bar.flat().map(element => unicorn(element));

## Related rules

- [prefer-array-flat](./prefer-array-flat.md)
- [unicorn/prefer-array-flat](./prefer-array-flat.md)
2 changes: 1 addition & 1 deletion docs/rules/prefer-array-flat.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@ const foo = utils.flat(bar); // Fails

## Related rules

- [prefer-array-flat-map](./prefer-array-flat-map.md)
- [unicorn/prefer-array-flat-map](./prefer-array-flat-map.md)
122 changes: 122 additions & 0 deletions docs/rules/prefer-at.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Prefer `.at()` method for index access and `String#charAt()`

Prefer [`Array#at()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at), [`String#at()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/at), and `{TypedArray,NodeList,CSSRuleList,…}#at()` for index access and `String#charAt()`.

This rule is fixable.

## Fail

```js
const foo = array[array.length - 1];
```

```js
const foo = array[array.length - 5];
```

```js
const foo = array.slice(-1)[0];
```

```js
const foo = array.slice(-1).pop();
```

```js
const foo = array.slice(-5).shift();
```

```js
const foo = string.charAt(string.length - 5);
```

```js
const foo = lodash.last(array);
```

## Pass

```js
const foo = array.at(-1);
```

```js
const foo = array.at(-5);
```

```js
const foo = array[100];
```

```js
// This rule is not checking this case, but `unicorn/prefer-negative-index` rule will fix it.
const foo = array.at(array.length - 1);
```

```js
array[array.length - 1] = foo;
```

## Options

Type: `object`

### checkAllIndexAccess

Type: `boolean`\
Default: `false`

This rule only check negative indexes by default, but you can also check positive indexes by setting `checkAllIndexAccess` to `true`.

Example:

```js
{
'unicorn/prefer-at': [
'error',
{
checkAllIndexAccess: true
}
]
}
```

```js
// eslint unicorn/prefer-at: ["error", {"checkAllIndexAccess": true}]
const foo = bar[10]; // Fails, will fix to `bar.at(10)`
const foo = bar[unknownProperty]; // Passes
const foo = string.chatAt(unknownIndex); // Fails
```

### getLastElementFunctions

Type: `string[]`

You can also check custom functions that get last element of objects.

`_.last()`, `lodash.last()`, and `underscore.last()` are checked by default.

Example:

```js
{
'unicorn/prefer-at': [
'error',
{
getLastElementFunctions: [
'getLast',
'utils.lastElement'
]
}
]
}
```

```js
// eslint unicorn/prefer-at: ["error", {"getLastElementFunctions": ["utils.lastElement"]}]
const foo = utils.lastElement(bar); // Fails
```

## Related rules

- [unicorn/prefer-negative-index](./prefer-negative-index.md)
4 changes: 4 additions & 0 deletions docs/rules/prefer-negative-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,7 @@ Array.prototype.slice.call(foo, -2, -1);
```js
Array.prototype.slice.apply(foo, [-2, -1]);
```

## Related rules

- [unicorn/prefer-at](./prefer-at.md)
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ module.exports = {
'unicorn/prefer-array-flat-map': 'error',
'unicorn/prefer-array-index-of': 'error',
'unicorn/prefer-array-some': 'error',
// TODO: Enable this by default when targeting a Node.js version that supports `Array#at`.
'unicorn/prefer-at': 'off',
'unicorn/prefer-date-now': 'error',
'unicorn/prefer-default-parameters': 'error',
'unicorn/prefer-dom-node-append': 'error',
Expand All @@ -101,7 +103,7 @@ module.exports = {
'unicorn/prefer-negative-index': 'error',
'unicorn/prefer-node-protocol': 'error',
'unicorn/prefer-number-properties': 'error',
// TODO: Enable this by default when targeting Node.js support `Object.hasOwn`.
// TODO: Enable this by default when targeting a Node.js version that supports `Object.hasOwn`.
'unicorn/prefer-object-has-own': 'off',
'unicorn/prefer-optional-catch-binding': 'error',
'unicorn/prefer-prototype-methods': 'error',
Expand Down
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Configure it in `package.json`.
"unicorn/prefer-array-flat-map": "error",
"unicorn/prefer-array-index-of": "error",
"unicorn/prefer-array-some": "error",
"unicorn/prefer-at": "off",
"unicorn/prefer-date-now": "error",
"unicorn/prefer-default-parameters": "error",
"unicorn/prefer-dom-node-append": "error",
Expand Down Expand Up @@ -183,6 +184,7 @@ Each rule has emojis denoting:
| [prefer-array-flat-map](docs/rules/prefer-array-flat-map.md) | Prefer `.flatMap(…)` over `.map(…).flat()`. || 🔧 | |
| [prefer-array-index-of](docs/rules/prefer-array-index-of.md) | Prefer `Array#indexOf()` over `Array#findIndex()` when looking for the index of an item. || 🔧 | 💡 |
| [prefer-array-some](docs/rules/prefer-array-some.md) | Prefer `.some(…)` over `.find(…)`. || | 💡 |
| [prefer-at](docs/rules/prefer-at.md) | Prefer `.at()` method for index access and `String#charAt()`. | | 🔧 | 💡 |
| [prefer-date-now](docs/rules/prefer-date-now.md) | Prefer `Date.now()` to get the number of milliseconds since the Unix Epoch. || 🔧 | |
| [prefer-default-parameters](docs/rules/prefer-default-parameters.md) | Prefer default parameters over reassignment. || 🔧 | 💡 |
| [prefer-dom-node-append](docs/rules/prefer-dom-node-append.md) | Prefer `Node#append()` over `Node#appendChild()`. || 🔧 | |
Expand Down
8 changes: 3 additions & 5 deletions rules/consistent-destructuring.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';
const avoidCapture = require('./utils/avoid-capture');
const getDocumentationUrl = require('./utils/get-documentation-url');
const {not} = require('./selectors');
const {not, notLeftHandSideSelector} = require('./selectors');

const MESSAGE_ID = 'consistentDestructuring';
const MESSAGE_ID_SUGGEST = 'consistentDestructuringSuggest';
Expand All @@ -16,12 +16,10 @@ const declaratorSelector = [
const memberSelector = [
'MemberExpression',
'[computed!=true]',
notLeftHandSideSelector(),
not([
'AssignmentExpression > .left',
'CallExpression > .callee',
'NewExpression > .callee',
'UpdateExpression > .argument',
'UnaryExpression[operator="delete"] > .argument'
'NewExpression> .callee'
])
].join('');

Expand Down
Loading

0 comments on commit 8ca5b46

Please sign in to comment.