Repository: eslint-community/eslint-plugin-es-x
Pull request #74 (2023-05-19 16:04:17)

Add new rule `no-string-prototype-iswellformed-towellformed`
[`String.prototype.isWellFormed` / `String.prototype.toWellFormed`](https://github.com/tc39/proposal-is-usv-string) is now stage 4.

So we should add new rule `no-string-prototype-iswellformed-towellformed`.


Patch:
diff --git a/docs/rules/index.md b/docs/rules/index.md
index 979018b..d368150 100644
--- a/docs/rules/index.md
+++ b/docs/rules/index.md
@@ -4,6 +4,14 @@ This plugin provides the following rules.
 
 - 🔧 mark means that the `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by the rule.
 
+## ES2024
+
+There is a config that enables the rules in this category: `plugin:es-x/no-new-in-esnext`
+
+| Rule ID | Description |    |
+|:--------|:------------|:--:|
+| [es-x/no-string-prototype-iswellformed-towellformed](./no-string-prototype-iswellformed-towellformed.md) | disallow the `String.prototype.{isWellFormed,toWellFormed}` methods. |  |
+
 ## ES2023
 
 There are multiple configs that enable all rules in this category: `plugin:es-x/no-new-in-es2023`, `plugin:es-x/restrict-to-es3`, `plugin:es-x/restrict-to-es5`, `plugin:es-x/restrict-to-es2015`, `plugin:es-x/restrict-to-es2016`, `plugin:es-x/restrict-to-es2017`, `plugin:es-x/restrict-to-es2018`, `plugin:es-x/restrict-to-es2019`, `plugin:es-x/restrict-to-es2020`, `plugin:es-x/restrict-to-es2021`, and `plugin:es-x/restrict-to-es2022`
diff --git a/docs/rules/no-string-prototype-iswellformed-towellformed.md b/docs/rules/no-string-prototype-iswellformed-towellformed.md
new file mode 100644
index 0000000..3239086
--- /dev/null
+++ b/docs/rules/no-string-prototype-iswellformed-towellformed.md
@@ -0,0 +1,43 @@
+---
+title: "es-x/no-string-prototype-iswellformed-towellformed"
+description: "disallow the `String.prototype.{isWellFormed,toWellFormed}` methods"
+---
+
+# es-x/no-string-prototype-iswellformed-towellformed
+> disallow the `String.prototype.{isWellFormed,toWellFormed}` methods
+
+- ❗ <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: `plugin:es-x/no-new-in-esnext`
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+<eslint-playground type="bad">
+
+```js
+/*eslint es-x/no-string-prototype-iswellformed-towellformed: [error, { aggressive: true }] */
+"str".isWellFormed()
+"str".toWellFormed()
+```
+
+</eslint-playground>a
+
+## 🔧 Options
+
+This rule has an option.
+
+```yaml
+rules:
+  es-x/no-string-prototype-iswellformed-towellformed: [error, { aggressive: false }]
+```
+
+### aggressive: boolean
+
+Configure the aggressive mode for only this rule.
+This is prior to the `settings['es-x'].aggressive` setting.
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-string-prototype-iswellformed-towellformed.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-string-prototype-iswellformed-towellformed.js)
diff --git a/lib/configs/no-new-in-esnext.js b/lib/configs/no-new-in-esnext.js
index f42c599..a3333de 100644
--- a/lib/configs/no-new-in-esnext.js
+++ b/lib/configs/no-new-in-esnext.js
@@ -4,4 +4,7 @@
  */
 "use strict"
 
-module.exports = { plugins: ["es-x"], rules: {} }
+module.exports = {
+    plugins: ["es-x"],
+    rules: { "es-x/no-string-prototype-iswellformed-towellformed": "error" },
+}
diff --git a/lib/index.js b/lib/index.js
index 91961c3..7e2d31b 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -244,6 +244,7 @@ module.exports = {
         "no-string-prototype-codepointat": require("./rules/no-string-prototype-codepointat"),
         "no-string-prototype-endswith": require("./rules/no-string-prototype-endswith"),
         "no-string-prototype-includes": require("./rules/no-string-prototype-includes"),
+        "no-string-prototype-iswellformed-towellformed": require("./rules/no-string-prototype-iswellformed-towellformed"),
         "no-string-prototype-matchall": require("./rules/no-string-prototype-matchall"),
         "no-string-prototype-normalize": require("./rules/no-string-prototype-normalize"),
         "no-string-prototype-padstart-padend": require("./rules/no-string-prototype-padstart-padend"),
diff --git a/lib/rules/no-string-prototype-iswellformed-towellformed.js b/lib/rules/no-string-prototype-iswellformed-towellformed.js
new file mode 100644
index 0000000..10c1041
--- /dev/null
+++ b/lib/rules/no-string-prototype-iswellformed-towellformed.js
@@ -0,0 +1,36 @@
+"use strict"
+
+const {
+    definePrototypeMethodHandler,
+} = require("../util/define-prototype-method-handler")
+
+module.exports = {
+    meta: {
+        docs: {
+            description:
+                "disallow the `String.prototype.{isWellFormed,toWellFormed}` methods.",
+            category: "ES2024",
+            recommended: false,
+            url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-string-prototype-iswellformed-towellformed.html",
+        },
+        fixable: null,
+        messages: {
+            forbidden: "ES2024 '{{name}}' method is forbidden.",
+        },
+        schema: [
+            {
+                type: "object",
+                properties: {
+                    aggressive: { type: "boolean" },
+                },
+                additionalProperties: false,
+            },
+        ],
+        type: "problem",
+    },
+    create(context) {
+        return definePrototypeMethodHandler(context, {
+            String: ["isWellFormed", "toWellFormed"],
+        })
+    },
+}


Test patch:
diff --git a/tests/lib/rules/no-string-prototype-iswellformed-towelformed.js b/tests/lib/rules/no-string-prototype-iswellformed-towelformed.js
new file mode 100644
index 0000000..0f2b009
--- /dev/null
+++ b/tests/lib/rules/no-string-prototype-iswellformed-towelformed.js
@@ -0,0 +1,245 @@
+"use strict"
+
+const path = require("path")
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-string-prototype-iswellformed-towellformed.js")
+const ruleId = "no-string-prototype-iswellformed-towellformed"
+
+new RuleTester().run(ruleId, rule, {
+    valid: [
+        "isWellFormed()",
+        "toWellFormed()",
+        "foo.isWellFormed()",
+        "foo.toWellFormed()",
+        { code: "isWellFormed()", settings: { "es-x": { aggressive: true } } },
+        { code: "toWellFormed()", settings: { "es-x": { aggressive: true } } },
+        {
+            code: "foo.isWellFormed()",
+            options: [{ aggressive: false }],
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            code: "foo.toWellFormed()",
+            options: [{ aggressive: false }],
+            settings: { "es-x": { aggressive: true } },
+        },
+    ],
+    invalid: [
+        {
+            code: "'foo'.isWellFormed()",
+            errors: [
+                "ES2024 'String.prototype.isWellFormed' method is forbidden.",
+            ],
+        },
+        {
+            code: "'foo'.toWellFormed()",
+            errors: [
+                "ES2024 'String.prototype.toWellFormed' method is forbidden.",
+            ],
+        },
+        {
+            code: "'foo'.isWellFormed()",
+            errors: [
+                "ES2024 'String.prototype.isWellFormed' method is forbidden.",
+            ],
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            code: "'foo'.toWellFormed()",
+            errors: [
+                "ES2024 'String.prototype.toWellFormed' method is forbidden.",
+            ],
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            code: "'foo'.isWellFormed()",
+            options: [{ aggressive: true }],
+            errors: [
+                "ES2024 'String.prototype.isWellFormed' method is forbidden.",
+            ],
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            code: "'foo'.toWellFormed()",
+            options: [{ aggressive: true }],
+            errors: [
+                "ES2024 'String.prototype.toWellFormed' method is forbidden.",
+            ],
+            settings: { "es-x": { aggressive: true } },
+        },
+    ],
+})
+
+// -----------------------------------------------------------------------------
+// TypeScript
+// -----------------------------------------------------------------------------
+const parser = require.resolve("@typescript-eslint/parser")
+const tsconfigRootDir = path.resolve(__dirname, "../../fixtures")
+const project = "tsconfig.json"
+const filename = path.join(tsconfigRootDir, "test.ts")
+
+new RuleTester({ parser }).run(ruleId, rule, {
+    valid: [
+        { filename, code: "isWellFormed()" },
+        { filename, code: "toWellFormed()" },
+        { filename, code: "foo.isWellFormed()" },
+        { filename, code: "foo.toWellFormed()" },
+        {
+            filename,
+            code: "isWellFormed()",
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            filename,
+            code: "toWellFormed()",
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            filename,
+            code: "foo.isWellFormed()",
+            options: [{ aggressive: false }],
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            filename,
+            code: "foo.toWellFormed()",
+            options: [{ aggressive: false }],
+            settings: { "es-x": { aggressive: true } },
+        },
+    ],
+    invalid: [
+        {
+            filename,
+            code: "'foo'.isWellFormed()",
+            errors: [
+                "ES2024 'String.prototype.isWellFormed' method is forbidden.",
+            ],
+        },
+        {
+            filename,
+            code: "'foo'.toWellFormed()",
+            errors: [
+                "ES2024 'String.prototype.toWellFormed' method is forbidden.",
+            ],
+        },
+        {
+            filename,
+            code: "'foo'.isWellFormed()",
+            errors: [
+                "ES2024 'String.prototype.isWellFormed' method is forbidden.",
+            ],
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            filename,
+            code: "'foo'.toWellFormed()",
+            errors: [
+                "ES2024 'String.prototype.toWellFormed' method is forbidden.",
+            ],
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            filename,
+            code: "'foo'.isWellFormed()",
+            options: [{ aggressive: true }],
+            errors: [
+                "ES2024 'String.prototype.isWellFormed' method is forbidden.",
+            ],
+            settings: { "es-x": { aggressive: true } },
+        },
+        {
+            filename,
+            code: "'foo'.toWellFormed()",
+            options: [{ aggressive: true }],
+            errors: [
+                "ES2024 'String.prototype.toWellFormed' method is forbidden.",
+            ],
+            settings: { "es-x": { aggressive: true } },
+        },
+    ],
+})
+
+new RuleTester({ parser, parserOptions: { tsconfigRootDir, project } }).run(
+    `${ruleId} TS Full Type Information`,
+    rule,
+    {
+        valid: [
+            { filename, code: "isWellFormed()" },
+            { filename, code: "toWellFormed()" },
+            { filename, code: "foo.isWellFormed()" },
+            { filename, code: "foo.toWellFormed()" },
+            {
+                filename,
+                code: "isWellFormed()",
+                settings: { "es-x": { aggressive: true } },
+            },
+            {
+                filename,
+                code: "toWellFormed()",
+                settings: { "es-x": { aggressive: true } },
+            },
+            {
+                filename,
+                code: "foo.isWellFormed()",
+                options: [{ aggressive: false }],
+                settings: { "es-x": { aggressive: true } },
+            },
+            {
+                filename,
+                code: "foo.toWellFormed()",
+                options: [{ aggressive: false }],
+                settings: { "es-x": { aggressive: true } },
+            },
+        ],
+        invalid: [
+            {
+                filename,
+                code: "'foo'.isWellFormed()",
+                errors: [
+                    "ES2024 'String.prototype.isWellFormed' method is forbidden.",
+                ],
+            },
+            {
+                filename,
+                code: "'foo'.toWellFormed()",
+                errors: [
+                    "ES2024 'String.prototype.toWellFormed' method is forbidden.",
+                ],
+            },
+            {
+                filename,
+                code: "'foo'.isWellFormed()",
+                errors: [
+                    "ES2024 'String.prototype.isWellFormed' method is forbidden.",
+                ],
+                settings: { "es-x": { aggressive: true } },
+            },
+            {
+                filename,
+                code: "'foo'.toWellFormed()",
+                errors: [
+                    "ES2024 'String.prototype.toWellFormed' method is forbidden.",
+                ],
+                settings: { "es-x": { aggressive: true } },
+            },
+            {
+                filename,
+                code: "'foo'.isWellFormed()",
+                options: [{ aggressive: true }],
+                errors: [
+                    "ES2024 'String.prototype.isWellFormed' method is forbidden.",
+                ],
+                settings: { "es-x": { aggressive: true } },
+            },
+            {
+                filename,
+                code: "'foo'.toWellFormed()",
+                options: [{ aggressive: true }],
+                errors: [
+                    "ES2024 'String.prototype.toWellFormed' method is forbidden.",
+                ],
+                settings: { "es-x": { aggressive: true } },
+            },
+        ],
+    },
+)