Skip to content

Commit 6d4f6bc

Browse files
authored
Add no-array-prototype-findlast-findlastindex rule (#34)
1 parent 0eb60fd commit 6d4f6bc

File tree

7 files changed

+302
-2
lines changed

7 files changed

+302
-2
lines changed

docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ There is a config that enables the rules in this category: `plugin:es-x/no-new-i
1010

1111
| Rule ID | Description | |
1212
|:--------|:------------|:--:|
13+
| [es-x/no-array-prototype-findlast-findlastindex](./no-array-prototype-findlast-findlastindex.md) | disallow the `Array.prototype.{findLast,findLastIndex}` methods. | |
1314
| [es-x/no-hashbang](./no-hashbang.md) | disallow Hashbang comments. | |
1415

1516
## ES2022
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
title: "es-x/no-array-prototype-findlast-findlastindex"
3+
description: "disallow the `Array.prototype.{findLast,findLastIndex}` methods"
4+
---
5+
6+
# es-x/no-array-prototype-findlast-findlastindex
7+
> disallow the `Array.prototype.{findLast,findLastIndex}` methods
8+
9+
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
10+
- ✅ The following configurations enable this rule: `plugin:es-x/no-new-in-esnext`
11+
12+
This rule reports ES2023 [`Array.prototype.{findLast,findLastIndex}` methods](https://github.com/tc39/proposal-array-find-from-last) as errors.
13+
14+
This rule is silent by default because it's hard to know types. You need to configure [the aggressive mode](../#the-aggressive-mode) or TypeScript in order to enable this rule.
15+
16+
## 💡 Examples
17+
18+
⛔ Examples of **incorrect** code for this rule:
19+
20+
<eslint-playground type="bad">
21+
22+
```js
23+
/*eslint es-x/no-array-prototype-findlast-findlastindex: [error, { aggressive: true }] */
24+
array.findLast(e => test(e))
25+
array.findLastIndex(e => test(e))
26+
```
27+
28+
</eslint-playground>
29+
30+
## 🔧 Options
31+
32+
This rule has an option.
33+
34+
```yml
35+
rules:
36+
es-x/no-array-prototype-findlast-findlastindex: [error, { aggressive: false }]
37+
```
38+
39+
### aggressive: boolean
40+
41+
Configure the aggressive mode for only this rule.
42+
This is prior to the `settings['es-x'].aggressive` setting.
43+
44+
## 📚 References
45+
46+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-es-x/blob/master/lib/rules/no-array-prototype-findlast-findlastindex.js)
47+
- [Test source](https://github.com/ota-meshi/eslint-plugin-es-x/blob/master/tests/lib/rules/no-array-prototype-findlast-findlastindex.js)

docs/rules/no-hashbang.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ description: "disallow Hashbang comments"
99
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
1010
- ✅ The following configurations enable this rule: `plugin:es-x/no-new-in-esnext`
1111

12-
This rule reports ES2023 Hashbang comment as errors.
12+
This rule reports ES2023 [Hashbang comment](https://github.com/tc39/proposal-hashbang) as errors.
1313

1414
## 💡 Examples
1515

lib/configs/no-new-in-esnext.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,10 @@
44
*/
55
"use strict"
66

7-
module.exports = { plugins: ["es-x"], rules: { "es-x/no-hashbang": "error" } }
7+
module.exports = {
8+
plugins: ["es-x"],
9+
rules: {
10+
"es-x/no-array-prototype-findlast-findlastindex": "error",
11+
"es-x/no-hashbang": "error",
12+
},
13+
}

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ module.exports = {
6565
"no-array-prototype-filter": require("./rules/no-array-prototype-filter"),
6666
"no-array-prototype-find": require("./rules/no-array-prototype-find"),
6767
"no-array-prototype-findindex": require("./rules/no-array-prototype-findindex"),
68+
"no-array-prototype-findlast-findlastindex": require("./rules/no-array-prototype-findlast-findlastindex"),
6869
"no-array-prototype-flat": require("./rules/no-array-prototype-flat"),
6970
"no-array-prototype-foreach": require("./rules/no-array-prototype-foreach"),
7071
"no-array-prototype-includes": require("./rules/no-array-prototype-includes"),
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"use strict"
2+
3+
const {
4+
definePrototypeMethodHandler,
5+
} = require("../util/define-prototype-method-handler")
6+
7+
module.exports = {
8+
meta: {
9+
docs: {
10+
description:
11+
"disallow the `Array.prototype.{findLast,findLastIndex}` methods.",
12+
category: "ES2023",
13+
recommended: false,
14+
url: "http://ota-meshi.github.io/eslint-plugin-es-x/rules/no-array-prototype-findlast-findlastindex.html",
15+
},
16+
fixable: null,
17+
messages: {
18+
forbidden: "ES2023 '{{name}}' method is forbidden.",
19+
},
20+
schema: [
21+
{
22+
type: "object",
23+
properties: {
24+
aggressive: { type: "boolean" },
25+
},
26+
additionalProperties: false,
27+
},
28+
],
29+
type: "problem",
30+
},
31+
create(context) {
32+
return definePrototypeMethodHandler(context, {
33+
Array: ["findLast", "findLastIndex"],
34+
})
35+
},
36+
}
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
"use strict"
2+
3+
const path = require("path")
4+
const RuleTester = require("../../tester")
5+
const rule = require("../../../lib/rules/no-array-prototype-findlast-findlastindex.js")
6+
const ruleId = "no-array-prototype-findlast-findlastindex"
7+
8+
new RuleTester().run(ruleId, rule, {
9+
valid: [
10+
"findLast(predicate)",
11+
"findLastIndex(predicate)",
12+
"foo.find(predicate)",
13+
"foo.findLast(predicate)",
14+
"foo.findLastIndex(predicate)",
15+
{
16+
code: "findLast(predicate)",
17+
settings: { "es-x": { aggressive: true } },
18+
},
19+
{
20+
code: "findLastIndex(predicate)",
21+
settings: { "es-x": { aggressive: true } },
22+
},
23+
{
24+
code: "foo.find(predicate)",
25+
settings: { "es-x": { aggressive: true } },
26+
},
27+
{
28+
code: "foo.findLast(predicate)",
29+
options: [{ aggressive: false }],
30+
settings: { "es-x": { aggressive: true } },
31+
},
32+
],
33+
invalid: [
34+
{
35+
code: "['foo'].findLast(predicate)",
36+
errors: ["ES2023 'Array.prototype.findLast' method is forbidden."],
37+
},
38+
{
39+
code: "['foo'].findLastIndex(predicate)",
40+
errors: [
41+
"ES2023 'Array.prototype.findLastIndex' method is forbidden.",
42+
],
43+
},
44+
{
45+
code: "foo.findLast(predicate)",
46+
errors: ["ES2023 'Array.prototype.findLast' method is forbidden."],
47+
settings: { "es-x": { aggressive: true } },
48+
},
49+
{
50+
code: "foo.findLastIndex(predicate)",
51+
errors: [
52+
"ES2023 'Array.prototype.findLastIndex' method is forbidden.",
53+
],
54+
settings: { "es-x": { aggressive: true } },
55+
},
56+
{
57+
code: "foo.findLast(predicate)",
58+
options: [{ aggressive: true }],
59+
errors: ["ES2023 'Array.prototype.findLast' method is forbidden."],
60+
settings: { "es-x": { aggressive: false } },
61+
},
62+
],
63+
})
64+
65+
// -----------------------------------------------------------------------------
66+
// TypeScript
67+
// -----------------------------------------------------------------------------
68+
const parser = require.resolve("@typescript-eslint/parser")
69+
const tsconfigRootDir = path.resolve(__dirname, "../../fixtures")
70+
const project = "tsconfig.json"
71+
const filename = path.join(tsconfigRootDir, "test.ts")
72+
73+
new RuleTester({ parser }).run(`${ruleId} TS`, rule, {
74+
valid: [
75+
{ filename, code: "findLast(predicate)" },
76+
{ filename, code: "foo.find(predicate)" },
77+
{ filename, code: "foo.findLast(predicate)" },
78+
{ filename, code: "let foo = {}; foo.findLast(predicate)" },
79+
{
80+
filename,
81+
code: "findLast(predicate)",
82+
settings: { "es-x": { aggressive: true } },
83+
},
84+
{
85+
filename,
86+
code: "foo.find(predicate)",
87+
settings: { "es-x": { aggressive: true } },
88+
},
89+
90+
// `Array` is unknown type if tsconfig.json is not configured.
91+
{ filename, code: "let foo = []; foo.findLast(predicate)" },
92+
{
93+
filename,
94+
code: "let foo = ['foo']; foo.findLast(predicate)",
95+
errors: ["ES2023 'Array.prototype.findLast' method is forbidden."],
96+
},
97+
{
98+
filename,
99+
code: "function f<T extends string[]>(a: T) { a.findLast(predicate) }",
100+
errors: ["ES2023 'Array.prototype.findLast' method is forbidden."],
101+
},
102+
{
103+
filename,
104+
code: "function f<T extends (string | number)[]>(a: T) { a.findLast(predicate) }",
105+
errors: ["ES2023 'Array.prototype.findLast' method is forbidden."],
106+
},
107+
],
108+
invalid: [
109+
{
110+
filename,
111+
code: "['foo'].findLast(predicate)",
112+
errors: ["ES2023 'Array.prototype.findLast' method is forbidden."],
113+
},
114+
{
115+
filename,
116+
code: "['foo'].findLastIndex(predicate)",
117+
errors: [
118+
"ES2023 'Array.prototype.findLastIndex' method is forbidden.",
119+
],
120+
},
121+
{
122+
filename,
123+
code: "let foo = []; foo.findLast(predicate)",
124+
errors: ["ES2023 'Array.prototype.findLast' method is forbidden."],
125+
settings: { "es-x": { aggressive: true } },
126+
},
127+
{
128+
filename,
129+
code: "foo.findLast(predicate)",
130+
errors: ["ES2023 'Array.prototype.findLast' method is forbidden."],
131+
settings: { "es-x": { aggressive: true } },
132+
},
133+
],
134+
})
135+
136+
new RuleTester({ parser, parserOptions: { tsconfigRootDir, project } }).run(
137+
`${ruleId} TS Full Type Information`,
138+
rule,
139+
{
140+
valid: [
141+
{ filename, code: "findLast(predicate)" },
142+
{ filename, code: "foo.find(predicate)" },
143+
{ filename, code: "foo.findLast(predicate)" },
144+
{ filename, code: "let foo = {}; foo.findLast(predicate)" },
145+
{
146+
filename,
147+
code: "findLast(predicate)",
148+
settings: { "es-x": { aggressive: true } },
149+
},
150+
{
151+
filename,
152+
code: "foo.find(predicate)",
153+
settings: { "es-x": { aggressive: true } },
154+
},
155+
],
156+
invalid: [
157+
{
158+
filename,
159+
code: "['foo'].findLast(predicate)",
160+
errors: [
161+
"ES2023 'Array.prototype.findLast' method is forbidden.",
162+
],
163+
},
164+
{
165+
filename,
166+
code: "['foo'].findLastIndex(predicate)",
167+
errors: [
168+
"ES2023 'Array.prototype.findLastIndex' method is forbidden.",
169+
],
170+
},
171+
{
172+
filename,
173+
code: "let foo = ['foo']; foo.findLast(predicate)",
174+
errors: [
175+
"ES2023 'Array.prototype.findLast' method is forbidden.",
176+
],
177+
},
178+
{
179+
filename,
180+
code: "let foo = []; foo.findLast(predicate)",
181+
errors: [
182+
"ES2023 'Array.prototype.findLast' method is forbidden.",
183+
],
184+
},
185+
{
186+
filename,
187+
code: "function f<T extends string[]>(a: T) { a.findLast(predicate) }",
188+
errors: [
189+
"ES2023 'Array.prototype.findLast' method is forbidden.",
190+
],
191+
},
192+
{
193+
filename,
194+
code: "function f<T extends (string | number)[]>(a: T) { a.findLast(predicate) }",
195+
errors: [
196+
"ES2023 'Array.prototype.findLast' method is forbidden.",
197+
],
198+
},
199+
{
200+
filename,
201+
code: "foo.findLast(predicate)",
202+
errors: [
203+
"ES2023 'Array.prototype.findLast' method is forbidden.",
204+
],
205+
settings: { "es-x": { aggressive: true } },
206+
},
207+
],
208+
},
209+
)

0 commit comments

Comments
 (0)