Skip to content

Commit 8ca5b46

Browse files
authored
Add prefer-at rule (#1331)
1 parent cfd31a5 commit 8ca5b46

File tree

13 files changed

+1983
-9
lines changed

13 files changed

+1983
-9
lines changed

docs/rules/prefer-array-flat-map.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@ const foo = bar.flat().map(element => unicorn(element));
3636

3737
## Related rules
3838

39-
- [prefer-array-flat](./prefer-array-flat.md)
39+
- [unicorn/prefer-array-flat](./prefer-array-flat.md)

docs/rules/prefer-array-flat.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,4 @@ const foo = utils.flat(bar); // Fails
9999

100100
## Related rules
101101

102-
- [prefer-array-flat-map](./prefer-array-flat-map.md)
102+
- [unicorn/prefer-array-flat-map](./prefer-array-flat-map.md)

docs/rules/prefer-at.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Prefer `.at()` method for index access and `String#charAt()`
2+
3+
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()`.
4+
5+
This rule is fixable.
6+
7+
## Fail
8+
9+
```js
10+
const foo = array[array.length - 1];
11+
```
12+
13+
```js
14+
const foo = array[array.length - 5];
15+
```
16+
17+
```js
18+
const foo = array.slice(-1)[0];
19+
```
20+
21+
```js
22+
const foo = array.slice(-1).pop();
23+
```
24+
25+
```js
26+
const foo = array.slice(-5).shift();
27+
```
28+
29+
```js
30+
const foo = string.charAt(string.length - 5);
31+
```
32+
33+
```js
34+
const foo = lodash.last(array);
35+
```
36+
37+
## Pass
38+
39+
```js
40+
const foo = array.at(-1);
41+
```
42+
43+
```js
44+
const foo = array.at(-5);
45+
```
46+
47+
```js
48+
const foo = array[100];
49+
```
50+
51+
```js
52+
// This rule is not checking this case, but `unicorn/prefer-negative-index` rule will fix it.
53+
const foo = array.at(array.length - 1);
54+
```
55+
56+
```js
57+
array[array.length - 1] = foo;
58+
```
59+
60+
## Options
61+
62+
Type: `object`
63+
64+
### checkAllIndexAccess
65+
66+
Type: `boolean`\
67+
Default: `false`
68+
69+
This rule only check negative indexes by default, but you can also check positive indexes by setting `checkAllIndexAccess` to `true`.
70+
71+
Example:
72+
73+
```js
74+
{
75+
'unicorn/prefer-at': [
76+
'error',
77+
{
78+
checkAllIndexAccess: true
79+
}
80+
]
81+
}
82+
```
83+
84+
```js
85+
// eslint unicorn/prefer-at: ["error", {"checkAllIndexAccess": true}]
86+
const foo = bar[10]; // Fails, will fix to `bar.at(10)`
87+
const foo = bar[unknownProperty]; // Passes
88+
const foo = string.chatAt(unknownIndex); // Fails
89+
```
90+
91+
### getLastElementFunctions
92+
93+
Type: `string[]`
94+
95+
You can also check custom functions that get last element of objects.
96+
97+
`_.last()`, `lodash.last()`, and `underscore.last()` are checked by default.
98+
99+
Example:
100+
101+
```js
102+
{
103+
'unicorn/prefer-at': [
104+
'error',
105+
{
106+
getLastElementFunctions: [
107+
'getLast',
108+
'utils.lastElement'
109+
]
110+
}
111+
]
112+
}
113+
```
114+
115+
```js
116+
// eslint unicorn/prefer-at: ["error", {"getLastElementFunctions": ["utils.lastElement"]}]
117+
const foo = utils.lastElement(bar); // Fails
118+
```
119+
120+
## Related rules
121+
122+
- [unicorn/prefer-negative-index](./prefer-negative-index.md)

docs/rules/prefer-negative-index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,7 @@ Array.prototype.slice.call(foo, -2, -1);
4747
```js
4848
Array.prototype.slice.apply(foo, [-2, -1]);
4949
```
50+
51+
## Related rules
52+
53+
- [unicorn/prefer-at](./prefer-at.md)

index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ module.exports = {
8787
'unicorn/prefer-array-flat-map': 'error',
8888
'unicorn/prefer-array-index-of': 'error',
8989
'unicorn/prefer-array-some': 'error',
90+
// TODO: Enable this by default when targeting a Node.js version that supports `Array#at`.
91+
'unicorn/prefer-at': 'off',
9092
'unicorn/prefer-date-now': 'error',
9193
'unicorn/prefer-default-parameters': 'error',
9294
'unicorn/prefer-dom-node-append': 'error',
@@ -101,7 +103,7 @@ module.exports = {
101103
'unicorn/prefer-negative-index': 'error',
102104
'unicorn/prefer-node-protocol': 'error',
103105
'unicorn/prefer-number-properties': 'error',
104-
// TODO: Enable this by default when targeting Node.js support `Object.hasOwn`.
106+
// TODO: Enable this by default when targeting a Node.js version that supports `Object.hasOwn`.
105107
'unicorn/prefer-object-has-own': 'off',
106108
'unicorn/prefer-optional-catch-binding': 'error',
107109
'unicorn/prefer-prototype-methods': 'error',

readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Configure it in `package.json`.
8383
"unicorn/prefer-array-flat-map": "error",
8484
"unicorn/prefer-array-index-of": "error",
8585
"unicorn/prefer-array-some": "error",
86+
"unicorn/prefer-at": "off",
8687
"unicorn/prefer-date-now": "error",
8788
"unicorn/prefer-default-parameters": "error",
8889
"unicorn/prefer-dom-node-append": "error",
@@ -183,6 +184,7 @@ Each rule has emojis denoting:
183184
| [prefer-array-flat-map](docs/rules/prefer-array-flat-map.md) | Prefer `.flatMap(…)` over `.map(…).flat()`. || 🔧 | |
184185
| [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. || 🔧 | 💡 |
185186
| [prefer-array-some](docs/rules/prefer-array-some.md) | Prefer `.some(…)` over `.find(…)`. || | 💡 |
187+
| [prefer-at](docs/rules/prefer-at.md) | Prefer `.at()` method for index access and `String#charAt()`. | | 🔧 | 💡 |
186188
| [prefer-date-now](docs/rules/prefer-date-now.md) | Prefer `Date.now()` to get the number of milliseconds since the Unix Epoch. || 🔧 | |
187189
| [prefer-default-parameters](docs/rules/prefer-default-parameters.md) | Prefer default parameters over reassignment. || 🔧 | 💡 |
188190
| [prefer-dom-node-append](docs/rules/prefer-dom-node-append.md) | Prefer `Node#append()` over `Node#appendChild()`. || 🔧 | |

rules/consistent-destructuring.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22
const avoidCapture = require('./utils/avoid-capture');
33
const getDocumentationUrl = require('./utils/get-documentation-url');
4-
const {not} = require('./selectors');
4+
const {not, notLeftHandSideSelector} = require('./selectors');
55

66
const MESSAGE_ID = 'consistentDestructuring';
77
const MESSAGE_ID_SUGGEST = 'consistentDestructuringSuggest';
@@ -16,12 +16,10 @@ const declaratorSelector = [
1616
const memberSelector = [
1717
'MemberExpression',
1818
'[computed!=true]',
19+
notLeftHandSideSelector(),
1920
not([
20-
'AssignmentExpression > .left',
2121
'CallExpression > .callee',
22-
'NewExpression > .callee',
23-
'UpdateExpression > .argument',
24-
'UnaryExpression[operator="delete"] > .argument'
22+
'NewExpression> .callee'
2523
])
2624
].join('');
2725

0 commit comments

Comments
 (0)