Skip to content

Commit

Permalink
Add es-x/no-iterator-prototype-find rule
Browse files Browse the repository at this point in the history
  • Loading branch information
ota-meshi committed Oct 31, 2024
1 parent 7933283 commit ac5e1c5
Show file tree
Hide file tree
Showing 10 changed files with 293 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/configs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ export default [
disallow proposal ES2025 [Iterator Helpers](https://github.com/tc39/proposal-iterator-helpers)\
⚠️ This config will be changed in the minor versions of this plugin.

This configs includes rules for [es-x/no-iterator-prototype-drop](../rules/no-iterator-prototype-drop.md), [es-x/no-iterator-prototype-every](../rules/no-iterator-prototype-every.md), [es-x/no-iterator-prototype-filter](../rules/no-iterator-prototype-filter.md), and [es-x/no-iterator](../rules/no-iterator.md).
This configs includes rules for [es-x/no-iterator-prototype-drop](../rules/no-iterator-prototype-drop.md), [es-x/no-iterator-prototype-every](../rules/no-iterator-prototype-every.md), [es-x/no-iterator-prototype-filter](../rules/no-iterator-prototype-filter.md), [es-x/no-iterator-prototype-find](../rules/no-iterator-prototype-find.md), and [es-x/no-iterator](../rules/no-iterator.md).

### [Config (Flat Config)]

Expand Down
1 change: 1 addition & 0 deletions docs/rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ There is a config that enables the rules in this category: [`no-new-in-esnext`]
| [es-x/no-iterator-prototype-drop](./no-iterator-prototype-drop.md) | disallow the `Iterator.prototype.drop` method. | |
| [es-x/no-iterator-prototype-every](./no-iterator-prototype-every.md) | disallow the `Iterator.prototype.every` method. | |
| [es-x/no-iterator-prototype-filter](./no-iterator-prototype-filter.md) | disallow the `Iterator.prototype.filter` method. | |
| [es-x/no-iterator-prototype-find](./no-iterator-prototype-find.md) | disallow the `Iterator.prototype.find` method. | |
| [es-x/no-iterator](./no-iterator.md) | disallow the `Iterator` class. | |
| [es-x/no-json-modules](./no-json-modules.md) | disallow JSON Modules. | |
| [es-x/no-regexp-duplicate-named-capturing-groups](./no-regexp-duplicate-named-capturing-groups.md) | disallow RegExp duplicate named capturing groups. | |
Expand Down
38 changes: 38 additions & 0 deletions docs/rules/no-iterator-prototype-find.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: "es-x/no-iterator-prototype-find"
description: "disallow the `Iterator.prototype.find` method"
---

# es-x/no-iterator-prototype-find
> disallow the `Iterator.prototype.find` method
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
- ✅ The following configurations enable this rule: [no-iterator-helpers] and [no-new-in-esnext]

This rule reports ES2025 [`Iterator.prototype.find`](https://github.com/tc39/proposal-iterator-helpers) as errors.\

## 💡 Examples

⛔ Examples of **incorrect** code for this rule:

<eslint-playground type="bad">

```js
/*eslint es-x/no-iterator-prototype-find: error */
const result = naturals()
.find(n => n % 2);

function* naturals() {
// ...
}
```

</eslint-playground>

## 📚 References

- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-iterator-prototype-find.js)
- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-iterator-prototype-find.js)

[no-iterator-helpers]: ../configs/index.md#no-iterator-helpers
[no-new-in-esnext]: ../configs/index.md#no-new-in-esnext
1 change: 1 addition & 0 deletions lib/configs/flat/no-iterator-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = {
"es-x/no-iterator-prototype-drop": "error",
"es-x/no-iterator-prototype-every": "error",
"es-x/no-iterator-prototype-filter": "error",
"es-x/no-iterator-prototype-find": "error",
"es-x/no-iterator": "error",
},
}
1 change: 1 addition & 0 deletions lib/configs/flat/no-new-in-esnext.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = {
"es-x/no-iterator-prototype-drop": "error",
"es-x/no-iterator-prototype-every": "error",
"es-x/no-iterator-prototype-filter": "error",
"es-x/no-iterator-prototype-find": "error",
"es-x/no-iterator": "error",
"es-x/no-json-modules": "error",
"es-x/no-regexp-duplicate-named-capturing-groups": "error",
Expand Down
1 change: 1 addition & 0 deletions lib/configs/no-iterator-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
"es-x/no-iterator-prototype-drop": "error",
"es-x/no-iterator-prototype-every": "error",
"es-x/no-iterator-prototype-filter": "error",
"es-x/no-iterator-prototype-find": "error",
"es-x/no-iterator": "error",
},
}
1 change: 1 addition & 0 deletions lib/configs/no-new-in-esnext.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
"es-x/no-iterator-prototype-drop": "error",
"es-x/no-iterator-prototype-every": "error",
"es-x/no-iterator-prototype-filter": "error",
"es-x/no-iterator-prototype-find": "error",
"es-x/no-iterator": "error",
"es-x/no-json-modules": "error",
"es-x/no-regexp-duplicate-named-capturing-groups": "error",
Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ module.exports = {
"no-iterator-prototype-drop": require("./rules/no-iterator-prototype-drop"),
"no-iterator-prototype-every": require("./rules/no-iterator-prototype-every"),
"no-iterator-prototype-filter": require("./rules/no-iterator-prototype-filter"),
"no-iterator-prototype-find": require("./rules/no-iterator-prototype-find"),
"no-json": require("./rules/no-json"),
"no-json-modules": require("./rules/no-json-modules"),
"no-json-superset": require("./rules/no-json-superset"),
Expand Down
36 changes: 36 additions & 0 deletions lib/rules/no-iterator-prototype-find.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use strict"

const {
definePrototypeMethodHandler,
} = require("../util/define-prototype-method-handler")

module.exports = {
meta: {
docs: {
description: "disallow the `Iterator.prototype.find` method.",
category: "ES2025",
proposal: "iterator-helpers",
recommended: false,
url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-iterator-prototype-find.html",
},
fixable: null,
messages: {
forbidden: "ES2025 '{{name}}' method is forbidden.",
},
schema: [
{
type: "object",
properties: {
aggressive: { type: "boolean" },
},
additionalProperties: false,
},
],
type: "problem",
},
create(context) {
return definePrototypeMethodHandler(context, {
Iterator: ["find"],
})
},
}
212 changes: 212 additions & 0 deletions tests/lib/rules/no-iterator-prototype-find.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
"use strict"

const path = require("path")
const RuleTester = require("../../tester")
const rule = require("../../../lib/rules/no-iterator-prototype-find.js")
const ruleId = "no-iterator-prototype-find"

if (!RuleTester.isSupported(2025)) {
//eslint-disable-next-line no-console
console.log(`Skip the tests of ${ruleId}.`)
return
}

new RuleTester({
languageOptions: { globals: { Iterator: "readonly" } },
}).run(ruleId, rule, {
valid: [
"find(n => n % 2)",
"foo.unknown(0)",
"foo.find(n => n % 2)",
{
code: "find(n => n % 2)",
settings: { "es-x": { aggressive: true } },
},
{ code: "foo.unknown(0)", settings: { "es-x": { aggressive: true } } },
{
code: "foo.find(n => n % 2)",
options: [{ aggressive: false }],
settings: { "es-x": { aggressive: true } },
},
`
function * foo(){};
function bar() {
if (baz) return foo();
else return "s"
};
bar().find(n => n % 2);
`,
`
function * foo(){};
function bar() {
switch (baz) {
case 1: return foo();
default: return "s"
}
};
bar().find(n => n % 2);
`,
`
function * foo(){};
function bar() {
try {
return foo();
} catch (e) {
return Iterator.from(x)
} finally {
return "s"
}
};
bar().find(n => n % 2);
`,
],
invalid: [
{
code: "foo.find(n => n % 2)",
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
settings: { "es-x": { aggressive: true } },
},
{
code: "foo.find(n => n % 2)",
options: [{ aggressive: true }],
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
settings: { "es-x": { aggressive: false } },
},
{
code: "foo().find(n => n % 2); function * foo() { }",
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
code: "Iterator.from(foo).find(n => n % 2);",
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
code: "Iterator.from(foo).drop(3).find(n => n % 2);",
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
code: "function * foo(){}; function bar() { return foo() }; bar().find(n => n % 2)",
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
code: `
function * foo(){};
function bar() {
if (baz) return foo();
else return Iterator.from(x)
};
bar().find(n => n % 2);
`,
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
code: `
function * foo(){};
function bar() {
while(true) return foo();
};
bar().find(n => n % 2);
`,
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
code: `
function * foo(){};
function bar() {
switch (baz) {
case 1: return foo();
default: return Iterator.from(x)
}
};
bar().find(n => n % 2);
`,
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
code: `
function * foo(){};
function bar() {
try {
return foo();
} catch (e) {
return Iterator.from(x)
} finally {
return Iterator.from(y)
}
};
bar().find(n => n % 2);
`,
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
code: `
function * foo(){};
const bar = () => foo();
bar().find(n => n % 2);
`,
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
],
})

// -----------------------------------------------------------------------------
// TypeScript
// -----------------------------------------------------------------------------
const parser = require("@typescript-eslint/parser")
const tsconfigRootDir = path.resolve(__dirname, "../../fixtures")
const project = "tsconfig.json"
const filename = path.join(tsconfigRootDir, "test.ts")

new RuleTester({
languageOptions: {
parser,
parserOptions: {
tsconfigRootDir,
project,
disallowAutomaticSingleRunInference: true,
},
},
}).run(`${ruleId} TS Full Type Information`, rule, {
valid: [
{ filename, code: "find(n => n % 2)" },
{ filename, code: "foo.unknown(0)" },
{ filename, code: "foo.find(n => n % 2)" },
{
filename,
code: "let foo = {}; foo.find(n => n % 2)",
},
{
filename,
code: "find(n => n % 2)",
settings: { "es-x": { aggressive: true } },
},
{
filename,
code: "foo.unknown(0)",
settings: { "es-x": { aggressive: true } },
},
],
invalid: [
{
filename,
code: "let foo = [][Symbol.iterator]; foo().find(n => n % 2)",
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
filename,
code: "function f(a: Iterator<any>) { a.find(n => n % 2) }",
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
filename,
code: "function * foo(){}; foo().find(n => n % 2)",
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
},
{
filename,
code: "foo.find(n => n % 2)",
errors: ["ES2025 'Iterator.prototype.find' method is forbidden."],
settings: { "es-x": { aggressive: true } },
},
],
})

0 comments on commit ac5e1c5

Please sign in to comment.