Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(deps): bump eslint-plugin-regexp from 1.11.0 to 1.12.0 #1183

Merged

Conversation

dependabot[bot]
Copy link
Contributor

@dependabot dependabot bot commented on behalf of github Feb 2, 2023

Bumps eslint-plugin-regexp from 1.11.0 to 1.12.0.

Release notes

Sourced from eslint-plugin-regexp's releases.

v1.12.0

✨ Enhancements

Full Changelog: ota-meshi/eslint-plugin-regexp@v1.11.0...v1.12.0

Commits
  • b65f644 1.12.0
  • 1736113 Bump json5 from 2.2.1 to 2.2.3 (#500)
  • d900ae9 run update
  • d3dbbfd Automate docs with eslint-doc-generator (#493)
  • 05b6475 Added lookbehind option for prefer-lookaround (#499)
  • 5ab1acb Add no-misleading-capturing-group rule and improve `optimal-quantifier-conc...
  • fd1da8b Bump decode-uri-component from 0.2.0 to 0.2.2 (#496)
  • c87db44 Docs: Add markdownlint and convert trailing spaces for newlines backslashes (...
  • 81dda6d Update dependency eslint-plugin-regexp to ~1.11.0
  • See full diff in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot merge will merge this PR after your CI passes on it
  • @dependabot squash and merge will squash and merge this PR after your CI passes on it
  • @dependabot cancel merge will cancel a previously requested merge and block automerging
  • @dependabot reopen will reopen this PR if it is closed
  • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [eslint-plugin-regexp](https://github.com/ota-meshi/eslint-plugin-regexp) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/ota-meshi/eslint-plugin-regexp/releases)
- [Commits](ota-meshi/eslint-plugin-regexp@v1.11.0...v1.12.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-regexp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot bot added dependencies Pull requests that update a dependency file javascript Pull requests that update Javascript code labels Feb 2, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2023

Diff between eslint-plugin-regexp 1.11.0 and 1.12.0
diff --git a/dist/utils/mention.js b/dist/utils/mention.js
index v1.11.0..v1.12.0 100644
--- a/dist/utils/mention.js
+++ b/dist/utils/mention.js
@@ -1,5 +1,5 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.mention = exports.mentionChar = void 0;
+exports.joinEnglishList = exports.mention = exports.mentionChar = void 0;
 function formatCodePoint(value) {
     return `U+${value.toString(16).padStart(4, "0")}`;
@@ -41,2 +41,17 @@
     return `\\x${control.charCodeAt(0).toString(16).padStart(2, "0")}`;
 }
+function joinEnglishList(list) {
+    if (list.length === 0)
+        return "none";
+    if (list.length === 1)
+        return list[0];
+    if (list.length === 2)
+        return `${list[0]} and ${list[1]}`;
+    let result = list[0];
+    for (let i = 1; i < list.length - 1; i++) {
+        result += `, ${list[i]}`;
+    }
+    result += `, and ${list[list.length - 1]}`;
+    return result;
+}
+exports.joinEnglishList = joinEnglishList;
diff --git a/dist/rules/no-assertion-capturing-group.js b/dist/rules/no-assertion-capturing-group.js
index v1.11.0..v1.12.0 100644
--- a/dist/rules/no-assertion-capturing-group.js
+++ b/dist/rules/no-assertion-capturing-group.js
@@ -7,5 +7,5 @@
 const no_empty_capturing_group_1 = __importDefault(require("./no-empty-capturing-group"));
 exports.default = (0, utils_1.createRule)("no-assertion-capturing-group", {
-    meta: Object.assign(Object.assign({}, no_empty_capturing_group_1.default.meta), { docs: Object.assign(Object.assign({}, no_empty_capturing_group_1.default.meta.docs), { recommended: false, replacedBy: ["no-empty-capturing-group"] }), deprecated: true }),
+    meta: Object.assign(Object.assign({}, no_empty_capturing_group_1.default.meta), { docs: Object.assign(Object.assign({}, no_empty_capturing_group_1.default.meta.docs), { recommended: false }), deprecated: true, replacedBy: ["no-empty-capturing-group"] }),
     create(context) {
         return no_empty_capturing_group_1.default.create(context);
diff --git a/dist/rules/no-useless-exactly-quantifier.js b/dist/rules/no-useless-exactly-quantifier.js
index v1.11.0..v1.12.0 100644
--- a/dist/rules/no-useless-exactly-quantifier.js
+++ b/dist/rules/no-useless-exactly-quantifier.js
@@ -8,5 +8,4 @@
             category: "Best Practices",
             recommended: false,
-            replacedBy: ["no-useless-quantifier", "no-zero-quantifier"],
         },
         schema: [],
@@ -16,4 +15,5 @@
         type: "suggestion",
         deprecated: true,
+        replacedBy: ["no-useless-quantifier", "no-zero-quantifier"],
     },
     create(context) {
diff --git a/dist/rules/no-useless-non-greedy.js b/dist/rules/no-useless-non-greedy.js
index v1.11.0..v1.12.0 100644
--- a/dist/rules/no-useless-non-greedy.js
+++ b/dist/rules/no-useless-non-greedy.js
@@ -7,5 +7,5 @@
 const no_useless_lazy_1 = __importDefault(require("./no-useless-lazy"));
 exports.default = (0, utils_1.createRule)("no-useless-non-greedy", {
-    meta: Object.assign(Object.assign({}, no_useless_lazy_1.default.meta), { docs: Object.assign(Object.assign({}, no_useless_lazy_1.default.meta.docs), { recommended: false, replacedBy: ["no-useless-lazy"] }), deprecated: true }),
+    meta: Object.assign(Object.assign({}, no_useless_lazy_1.default.meta), { docs: Object.assign(Object.assign({}, no_useless_lazy_1.default.meta.docs), { recommended: false }), deprecated: true, replacedBy: ["no-useless-lazy"] }),
     create(context) {
         return no_useless_lazy_1.default.create(context);
diff --git a/dist/rules/optimal-quantifier-concatenation.js b/dist/rules/optimal-quantifier-concatenation.js
index v1.11.0..v1.12.0 100644
--- a/dist/rules/optimal-quantifier-concatenation.js
+++ b/dist/rules/optimal-quantifier-concatenation.js
@@ -5,4 +5,6 @@
 const regexp_ast_1 = require("../utils/regexp-ast");
 const mention_1 = require("../utils/mention");
+const simplify_quantifier_1 = require("../utils/regexp-ast/simplify-quantifier");
+const fix_simplify_quantifier_1 = require("../utils/fix-simplify-quantifier");
 function hasCapturingGroup(node) {
     return (0, regexp_ast_analysis_1.hasSomeDescendant)(node, (d) => d.type === "CapturingGroup");
@@ -301,4 +303,14 @@
     });
 }
+function getCapturingGroupStack(element) {
+    let result = "";
+    for (let p = element.parent; p.type !== "Pattern"; p = p.parent) {
+        if (p.type === "CapturingGroup") {
+            const id = p.start;
+            result += String.fromCodePoint(32 + id);
+        }
+    }
+    return result;
+}
 exports.default = (0, utils_1.createRule)("optimal-quantifier-concatenation", {
     meta: {
@@ -327,4 +339,6 @@
             nestedRemove: "{{nested}} can be removed because of {{dominate}}.{{cap}}",
             nestedReplace: "{{nested}} can be replaced with {{fix}} because of {{dominate}}.{{cap}}",
+            removeQuant: "{{quant}} can be removed because it is already included by {{cause}}.{{cap}}",
+            replaceQuant: "{{quant}} can be replaced with {{fix}} because of {{cause}}.{{cap}}",
         },
         type: "suggestion",
@@ -335,9 +349,71 @@
         function createVisitor(regexpContext) {
             const { node, flags, getRegexpLocation, fixReplaceNode } = regexpContext;
+            const parser = (0, regexp_ast_1.getParser)(regexpContext);
+            const simplifiedAlready = [];
+            function isSimplifiedAlready(element) {
+                return simplifiedAlready.some((q) => {
+                    return (0, regexp_ast_analysis_1.hasSomeDescendant)(q, element);
+                });
+            }
             return {
-                onAlternativeEnter(aNode) {
+                onQuantifierEnter(quantifier) {
+                    const result = (0, simplify_quantifier_1.canSimplifyQuantifier)(quantifier, flags, parser);
+                    if (!result.canSimplify)
+                        return;
+                    const quantStack = getCapturingGroupStack(quantifier);
+                    const crossesCapturingGroup = result.dependencies.some((e) => getCapturingGroupStack(e) !== quantStack);
+                    const removesCapturingGroup = quantifier.min === 0 && hasCapturingGroup(quantifier);
+                    const involvesCapturingGroup = removesCapturingGroup || crossesCapturingGroup;
+                    if (involvesCapturingGroup &&
+                        cgReporting === "ignore") {
+                        return;
+                    }
+                    simplifiedAlready.push(quantifier, ...result.dependencies);
+                    const cause = (0, mention_1.joinEnglishList)(result.dependencies.map((d) => (0, mention_1.mention)(d)));
+                    const [replacement, fix] = (0, fix_simplify_quantifier_1.fixSimplifyQuantifier)(quantifier, result, regexpContext);
+                    if (quantifier.min === 0) {
+                        const cap = involvesCapturingGroup
+                            ? removesCapturingGroup
+                                ? " This cannot be fixed automatically because it removes a capturing group."
+                                : " This cannot be fixed automatically because it involves a capturing group."
+                            : "";
+                        context.report({
+                            node,
+                            loc: getRegexpLocation(quantifier),
+                            messageId: "removeQuant",
+                            data: {
+                                quant: (0, mention_1.mention)(quantifier),
+                                cause,
+                                cap,
+                            },
+                            fix: involvesCapturingGroup ? undefined : fix,
+                        });
+                    }
+                    else {
+                        const cap = involvesCapturingGroup
+                            ? " This cannot be fixed automatically because it involves a capturing group."
+                            : "";
+                        context.report({
+                            node,
+                            loc: getRegexpLocation(quantifier),
+                            messageId: "replaceQuant",
+                            data: {
+                                quant: (0, mention_1.mention)(quantifier),
+                                fix: (0, mention_1.mention)(replacement),
+                                cause,
+                                cap,
+                            },
+                            fix: involvesCapturingGroup ? undefined : fix,
+                        });
+                    }
+                },
+                onAlternativeLeave(aNode) {
                     for (let i = 0; i < aNode.elements.length - 1; i++) {
                         const left = aNode.elements[i];
                         const right = aNode.elements[i + 1];
+                        if (isSimplifiedAlready(left) ||
+                            isSimplifiedAlready(right)) {
+                            continue;
+                        }
                         const replacement = getReplacement(left, right, flags);
                         if (!replacement) {
diff --git a/dist/rules/order-in-character-class.js b/dist/rules/order-in-character-class.js
index v1.11.0..v1.12.0 100644
--- a/dist/rules/order-in-character-class.js
+++ b/dist/rules/order-in-character-class.js
@@ -7,5 +7,5 @@
 const sort_character_class_elements_1 = __importDefault(require("./sort-character-class-elements"));
 exports.default = (0, utils_1.createRule)("order-in-character-class", {
-    meta: Object.assign(Object.assign({}, sort_character_class_elements_1.default.meta), { docs: Object.assign(Object.assign({}, sort_character_class_elements_1.default.meta.docs), { recommended: false, replacedBy: ["sort-character-class-elements"] }), deprecated: true }),
+    meta: Object.assign(Object.assign({}, sort_character_class_elements_1.default.meta), { docs: Object.assign(Object.assign({}, sort_character_class_elements_1.default.meta.docs), { recommended: false }), deprecated: true, replacedBy: ["sort-character-class-elements"] }),
     create(context) {
         return sort_character_class_elements_1.default.create(context);
diff --git a/dist/rules/prefer-lookaround.js b/dist/rules/prefer-lookaround.js
index v1.11.0..v1.12.0 100644
--- a/dist/rules/prefer-lookaround.js
+++ b/dist/rules/prefer-lookaround.js
@@ -173,12 +173,8 @@
 }
 function parseOption(userOption) {
-    let strictTypes = true;
-    if (userOption) {
-        if (userOption.strictTypes != null) {
-            strictTypes = userOption.strictTypes;
-        }
-    }
+    var _a, _b;
     return {
-        strictTypes,
+        lookbehind: (_a = userOption === null || userOption === void 0 ? void 0 : userOption.lookbehind) !== null && _a !== void 0 ? _a : true,
+        strictTypes: (_b = userOption === null || userOption === void 0 ? void 0 : userOption.strictTypes) !== null && _b !== void 0 ? _b : true,
     };
 }
@@ -195,4 +191,5 @@
                 type: "object",
                 properties: {
+                    lookbehind: { type: "boolean" },
                     strictTypes: { type: "boolean" },
                 },
@@ -207,5 +204,5 @@
     },
     create(context) {
-        const { strictTypes } = parseOption(context.options[0]);
+        const { lookbehind, strictTypes } = parseOption(context.options[0]);
         const typeTracer = (0, type_tracker_1.createTypeTracker)(context);
         function createVisitor(regexpContext) {
@@ -376,4 +373,7 @@
                         reportEnd = null;
                     }
+                    if (!lookbehind) {
+                        reportStart = null;
+                    }
                     if (reportStart && reportEnd) {
                         const fix = buildFixer(regexpContext, [reportStart, reportEnd], replaceReferenceList, (target) => {
diff --git a/dist/rules/prefer-t.js b/dist/rules/prefer-t.js
index v1.11.0..v1.12.0 100644
--- a/dist/rules/prefer-t.js
+++ b/dist/rules/prefer-t.js
@@ -9,5 +9,4 @@
             category: "Stylistic Issues",
             recommended: false,
-            replacedBy: ["control-character-escape"],
         },
         fixable: "code",
@@ -18,4 +17,5 @@
         type: "suggestion",
         deprecated: true,
+        replacedBy: ["control-character-escape"],
     },
     create(context) {
diff --git a/dist/utils/rules.js b/dist/utils/rules.js
index v1.11.0..v1.12.0 100644
--- a/dist/utils/rules.js
+++ b/dist/utils/rules.js
@@ -27,4 +27,5 @@
 const no_lazy_ends_1 = __importDefault(require("../rules/no-lazy-ends"));
 const no_legacy_features_1 = __importDefault(require("../rules/no-legacy-features"));
+const no_misleading_capturing_group_1 = __importDefault(require("../rules/no-misleading-capturing-group"));
 const no_misleading_unicode_character_1 = __importDefault(require("../rules/no-misleading-unicode-character"));
 const no_missing_g_flag_1 = __importDefault(require("../rules/no-missing-g-flag"));
@@ -106,4 +107,5 @@
     no_lazy_ends_1.default,
     no_legacy_features_1.default,
+    no_misleading_capturing_group_1.default,
     no_misleading_unicode_character_1.default,
     no_missing_g_flag_1.default,
diff --git a/package.json b/package.json
index v1.11.0..v1.12.0 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
 {
     "name": "eslint-plugin-regexp",
-    "version": "1.11.0",
+    "version": "1.12.0",
     "description": "ESLint plugin for finding RegExp mistakes and RegExp style guide violations.",
     "engines": {
@@ -14,5 +14,7 @@
         "build": "tsc --project ./tsconfig.build.json",
         "clean": "rimraf .nyc_output dist coverage",
-        "lint": "eslint . --ext .js,.vue,.ts,.json,.yaml,.yml",
+        "lint": "npm-run-all \"lint:*\"",
+        "lint:js": "eslint . --ext .js,.vue,.ts,.json,.yaml,.yml",
+        "lint:docs": "markdownlint \"**/*.md\"",
         "eslint-fix": "eslint . --ext .js,.vue,.ts,.json,.yaml,.yml --fix",
         "pretest": "npm run build",
@@ -22,5 +24,6 @@
         "test:debug": "mocha --require ts-node/register/transpile-only \"tests/**/*.ts\" --reporter dot --timeout 60000",
         "test:watch": "npm run test:base -- --watch",
-        "update": "ts-node --transpile-only ./tools/update.ts && npm run eslint-fix",
+        "update": "ts-node --transpile-only ./tools/update.ts && npm run eslint-fix && npm run update:eslint-docs",
+        "update:eslint-docs": "npm run build && eslint-doc-generator",
         "new": "ts-node ./tools/new-rule.ts",
         "docs:watch": "vitepress dev docs",
@@ -69,4 +72,5 @@
         "eslint": "^8.0.0",
         "eslint-config-prettier": "^8.3.0",
+        "eslint-doc-generator": "^1.4.1",
         "eslint-plugin-eslint-comments": "^3.2.0",
         "eslint-plugin-eslint-plugin": "^5.0.0",
@@ -75,9 +79,11 @@
         "eslint-plugin-node": "^11.1.0",
         "eslint-plugin-prettier": "^4.0.0",
-        "eslint-plugin-regexp": "~1.10.0",
+        "eslint-plugin-regexp": "~1.11.0",
         "eslint-plugin-vue": "^9.0.0",
         "eslint-plugin-yml": "^1.0.0",
+        "markdownlint-cli": "^0.32.2",
         "mocha": "^10.0.0",
         "mocha-chai-jest-snapshot": "^1.1.3",
+        "npm-run-all": "^4.1.5",
         "nyc": "^15.1.0",
         "pako": "^2.1.0",
diff --git a/README.md b/README.md
index v1.11.0..v1.12.0 100644
--- a/README.md
+++ b/README.md
@@ -98,115 +98,113 @@
 ## :white_check_mark: Rules
 
-<!--RULES_SECTION_START-->
+<!-- begin auto-generated rules list -->
 
-The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) automatically fixes problems reported by rules which have a wrench :wrench: below.
-The rules with the following star :star: are included in the `plugin:regexp/recommended` config.
+💼 Configurations enabled in.\
+⚠️ Configurations set to warn in.\
+✅ Set in the `plugin:regexp/recommended` configuration.\
+🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
+💡 Manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
 
-<!--RULES_TABLE_START-->
-
 ### Possible Errors
 
-| Rule ID | Description |    |
-|:--------|:------------|:---|
-| [regexp/no-contradiction-with-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-contradiction-with-assertion.html) | disallow elements that contradict assertions |  |
-| [regexp/no-control-character](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-control-character.html) | disallow control characters |  |
-| [regexp/no-dupe-disjunctions](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-dupe-disjunctions.html) | disallow duplicate disjunctions | :star: |
-| [regexp/no-empty-alternative](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-alternative.html) | disallow alternatives without elements | :star: |
-| [regexp/no-empty-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-capturing-group.html) | disallow capturing group that captures empty. | :star: |
-| [regexp/no-empty-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-character-class.html) | disallow character classes that match no characters |  |
-| [regexp/no-empty-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-group.html) | disallow empty group | :star: |
-| [regexp/no-empty-lookarounds-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-lookarounds-assertion.html) | disallow empty lookahead assertion or empty lookbehind assertion | :star: |
-| [regexp/no-escape-backspace](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-escape-backspace.html) | disallow escape backspace (`[\b]`) | :star: |
-| [regexp/no-invalid-regexp](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-invalid-regexp.html) | disallow invalid regular expression strings in `RegExp` constructors | :star: |
-| [regexp/no-lazy-ends](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-lazy-ends.html) | disallow lazy quantifiers at the end of an expression | :star: |
-| [regexp/no-misleading-unicode-character](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-misleading-unicode-character.html) | disallow multi-code-point characters in character classes and quantifiers | :wrench: |
-| [regexp/no-missing-g-flag](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-missing-g-flag.html) | disallow missing `g` flag in patterns used in `String#matchAll` and `String#replaceAll` | :wrench: |
-| [regexp/no-optional-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-optional-assertion.html) | disallow optional assertions | :star: |
-| [regexp/no-potentially-useless-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-potentially-useless-backreference.html) | disallow backreferences that reference a group that might not be matched | :star: |
-| [regexp/no-super-linear-backtracking](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-super-linear-backtracking.html) | disallow exponential and polynomial backtracking | :star::wrench: |
-| [regexp/no-super-linear-move](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-super-linear-move.html) | disallow quantifiers that cause quadratic moves |  |
-| [regexp/no-useless-assertions](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-assertions.html) | disallow assertions that are known to always accept (or reject) | :star: |
-| [regexp/no-useless-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-backreference.html) | disallow useless backreferences in regular expressions | :star: |
-| [regexp/no-useless-dollar-replacements](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-dollar-replacements.html) | disallow useless `$` replacements in replacement string | :star: |
-| [regexp/strict](https://ota-meshi.github.io/eslint-plugin-regexp/rules/strict.html) | disallow not strictly valid regular expressions | :star::wrench: |
+| Name                                                                                                                                     | Description                                                                             | 💼 | ⚠️ | 🔧 | 💡 |
+| :--------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------- | :- | :- | :- | :- |
+| [no-contradiction-with-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-contradiction-with-assertion.html)           | disallow elements that contradict assertions                                            |    |    |    | 💡 |
+| [no-control-character](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-control-character.html)                                 | disallow control characters                                                             |    |    |    | 💡 |
+| [no-dupe-disjunctions](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-dupe-disjunctions.html)                                 | disallow duplicate disjunctions                                                         | ✅  |    |    | 💡 |
+| [no-empty-alternative](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-alternative.html)                                 | disallow alternatives without elements                                                  |    | ✅  |    |    |
+| [no-empty-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-capturing-group.html)                         | disallow capturing group that captures empty.                                           | ✅  |    |    |    |
+| [no-empty-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-character-class.html)                         | disallow character classes that match no characters                                     |    |    |    |    |
+| [no-empty-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-group.html)                                             | disallow empty group                                                                    | ✅  |    |    |    |
+| [no-empty-lookarounds-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-lookarounds-assertion.html)             | disallow empty lookahead assertion or empty lookbehind assertion                        | ✅  |    |    |    |
+| [no-escape-backspace](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-escape-backspace.html)                                   | disallow escape backspace (`[\b]`)                                                      | ✅  |    |    |    |
+| [no-invalid-regexp](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-invalid-regexp.html)                                       | disallow invalid regular expression strings in `RegExp` constructors                    | ✅  |    |    |    |
+| [no-lazy-ends](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-lazy-ends.html)                                                 | disallow lazy quantifiers at the end of an expression                                   |    | ✅  |    |    |
+| [no-misleading-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-misleading-capturing-group.html)               | disallow capturing groups that do not behave as one would expect                        |    |    |    | 💡 |
+| [no-misleading-unicode-character](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-misleading-unicode-character.html)           | disallow multi-code-point characters in character classes and quantifiers               |    |    | 🔧 | 💡 |
+| [no-missing-g-flag](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-missing-g-flag.html)                                       | disallow missing `g` flag in patterns used in `String#matchAll` and `String#replaceAll` |    |    | 🔧 |    |
+| [no-optional-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-optional-assertion.html)                               | disallow optional assertions                                                            | ✅  |    |    |    |
+| [no-potentially-useless-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-potentially-useless-backreference.html) | disallow backreferences that reference a group that might not be matched                |    | ✅  |    |    |
+| [no-super-linear-backtracking](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-super-linear-backtracking.html)                 | disallow exponential and polynomial backtracking                                        | ✅  |    | 🔧 |    |
+| [no-super-linear-move](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-super-linear-move.html)                                 | disallow quantifiers that cause quadratic moves                                         |    |    |    |    |
+| [no-useless-assertions](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-assertions.html)                               | disallow assertions that are known to always accept (or reject)                         | ✅  |    |    |    |
+| [no-useless-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-backreference.html)                         | disallow useless backreferences in regular expressions                                  | ✅  |    |    |    |
+| [no-useless-dollar-replacements](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-dollar-replacements.html)             | disallow useless `$` replacements in replacement string                                 | ✅  |    |    |    |
+| [strict](https://ota-meshi.github.io/eslint-plugin-regexp/rules/strict.html)                                                             | disallow not strictly valid regular expressions                                         | ✅  |    | 🔧 | 💡 |
 
 ### Best Practices
 
-| Rule ID | Description |    |
-|:--------|:------------|:---|
-| [regexp/confusing-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/confusing-quantifier.html) | disallow confusing quantifiers | :star: |
-| [regexp/control-character-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/control-character-escape.html) | enforce consistent escaping of control characters | :star::wrench: |
-| [regexp/negation](https://ota-meshi.github.io/eslint-plugin-regexp/rules/negation.html) | enforce use of escapes on negation | :star::wrench: |
-| [regexp/no-dupe-characters-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-dupe-characters-character-class.html) | disallow duplicate characters in the RegExp character class | :star::wrench: |
-| [regexp/no-extra-lookaround-assertions](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-extra-lookaround-assertions.html) | disallow unnecessary nested lookaround assertions | :wrench: |
-| [regexp/no-invisible-character](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-invisible-character.html) | disallow invisible raw character | :star::wrench: |
-| [regexp/no-legacy-features](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-legacy-features.html) | disallow legacy RegExp features | :star: |
-| [regexp/no-non-standard-flag](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-non-standard-flag.html) | disallow non-standard flags | :star: |
-| [regexp/no-obscure-range](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-obscure-range.html) | disallow obscure character ranges | :star: |
-| [regexp/no-octal](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-octal.html) | disallow octal escape sequence |  |
-| [regexp/no-standalone-backslash](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-standalone-backslash.html) | disallow standalone backslashes (`\`) |  |
-| [regexp/no-trivially-nested-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-trivially-nested-assertion.html) | disallow trivially nested assertions | :star::wrench: |
-| [regexp/no-trivially-nested-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-trivially-nested-quantifier.html) | disallow nested quantifiers that can be rewritten as one quantifier | :star::wrench: |
-| [regexp/no-unused-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-unused-capturing-group.html) | disallow unused capturing group | :star::wrench: |
-| [regexp/no-useless-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-character-class.html) | disallow character class with one character | :star::wrench: |
-| [regexp/no-useless-flag](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-flag.html) | disallow unnecessary regex flags | :star::wrench: |
-| [regexp/no-useless-lazy](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-lazy.html) | disallow unnecessarily non-greedy quantifiers | :star::wrench: |
-| [regexp/no-useless-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-quantifier.html) | disallow quantifiers that can be removed | :star::wrench: |
-| [regexp/no-useless-range](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-range.html) | disallow unnecessary range of characters by using a hyphen | :star::wrench: |
-| [regexp/no-useless-two-nums-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-two-nums-quantifier.html) | disallow unnecessary `{n,m}` quantifier | :star::wrench: |
-| [regexp/no-zero-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-zero-quantifier.html) | disallow quantifiers with a maximum of zero | :star: |
-| [regexp/optimal-lookaround-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/optimal-lookaround-quantifier.html) | disallow the alternatives of lookarounds that end with a non-constant quantifier | :star: |
-| [regexp/optimal-quantifier-concatenation](https://ota-meshi.github.io/eslint-plugin-regexp/rules/optimal-quantifier-concatenation.html) | require optimal quantifiers for concatenated quantifiers | :star::wrench: |
-| [regexp/prefer-escape-replacement-dollar-char](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-escape-replacement-dollar-char.html) | enforces escape of replacement `$` character (`$$`). |  |
-| [regexp/prefer-predefined-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-predefined-assertion.html) | prefer predefined assertion over equivalent lookarounds | :star::wrench: |
-| [regexp/prefer-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-quantifier.html) | enforce using quantifier | :wrench: |
-| [regexp/prefer-range](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-range.html) | enforce using character class range | :star::wrench: |
-| [regexp/prefer-regexp-exec](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-regexp-exec.html) | enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided |  |
-| [regexp/prefer-regexp-test](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-regexp-test.html) | enforce that `RegExp#test` is used instead of `String#match` and `RegExp#exec` | :wrench: |
-| [regexp/require-unicode-regexp](https://ota-meshi.github.io/eslint-plugin-regexp/rules/require-unicode-regexp.html) | enforce the use of the `u` flag | :wrench: |
-| [regexp/sort-alternatives](https://ota-meshi.github.io/eslint-plugin-regexp/rules/sort-alternatives.html) | sort alternatives if order doesn't matter | :wrench: |
-| [regexp/use-ignore-case](https://ota-meshi.github.io/eslint-plugin-regexp/rules/use-ignore-case.html) | use the `i` flag if it simplifies the pattern | :wrench: |
+| Name                                                                                                                                       | Description                                                                                | 💼 | ⚠️ | 🔧 | 💡 |
+| :----------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | :- | :- | :- | :- |
+| [confusing-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/confusing-quantifier.html)                                   | disallow confusing quantifiers                                                             |    | ✅  |    |    |
+| [control-character-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/control-character-escape.html)                           | enforce consistent escaping of control characters                                          | ✅  |    | 🔧 |    |
+| [negation](https://ota-meshi.github.io/eslint-plugin-regexp/rules/negation.html)                                                           | enforce use of escapes on negation                                                         | ✅  |    | 🔧 |    |
+| [no-dupe-characters-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-dupe-characters-character-class.html)       | disallow duplicate characters in the RegExp character class                                | ✅  |    | 🔧 |    |
+| [no-extra-lookaround-assertions](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-extra-lookaround-assertions.html)               | disallow unnecessary nested lookaround assertions                                          |    |    | 🔧 |    |
+| [no-invisible-character](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-invisible-character.html)                               | disallow invisible raw character                                                           | ✅  |    | 🔧 |    |
+| [no-legacy-features](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-legacy-features.html)                                       | disallow legacy RegExp features                                                            | ✅  |    |    |    |
+| [no-non-standard-flag](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-non-standard-flag.html)                                   | disallow non-standard flags                                                                | ✅  |    |    |    |
+| [no-obscure-range](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-obscure-range.html)                                           | disallow obscure character ranges                                                          | ✅  |    |    |    |
+| [no-octal](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-octal.html)                                                           | disallow octal escape sequence                                                             |    |    |    | 💡 |
+| [no-standalone-backslash](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-standalone-backslash.html)                             | disallow standalone backslashes (`\`)                                                      |    |    |    |    |
+| [no-trivially-nested-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-trivially-nested-assertion.html)                 | disallow trivially nested assertions                                                       | ✅  |    | 🔧 |    |
+| [no-trivially-nested-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-trivially-nested-quantifier.html)               | disallow nested quantifiers that can be rewritten as one quantifier                        | ✅  |    | 🔧 |    |
+| [no-unused-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-unused-capturing-group.html)                         | disallow unused capturing group                                                            | ✅  |    | 🔧 | 💡 |
+| [no-useless-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-character-class.html)                       | disallow character class with one character                                                | ✅  |    | 🔧 |    |
+| [no-useless-flag](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-flag.html)                                             | disallow unnecessary regex flags                                                           |    | ✅  | 🔧 |    |
+| [no-useless-lazy](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-lazy.html)                                             | disallow unnecessarily non-greedy quantifiers                                              | ✅  |    | 🔧 |    |
+| [no-useless-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-quantifier.html)                                 | disallow quantifiers that can be removed                                                   | ✅  |    | 🔧 | 💡 |
+| [no-useless-range](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-range.html)                                           | disallow unnecessary range of characters by using a hyphen                                 | ✅  |    | 🔧 |    |
+| [no-useless-two-nums-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-two-nums-quantifier.html)               | disallow unnecessary `{n,m}` quantifier                                                    | ✅  |    | 🔧 |    |
+| [no-zero-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-zero-quantifier.html)                                       | disallow quantifiers with a maximum of zero                                                | ✅  |    |    | 💡 |
+| [optimal-lookaround-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/optimal-lookaround-quantifier.html)                 | disallow the alternatives of lookarounds that end with a non-constant quantifier           |    | ✅  |    |    |
+| [optimal-quantifier-concatenation](https://ota-meshi.github.io/eslint-plugin-regexp/rules/optimal-quantifier-concatenation.html)           | require optimal quantifiers for concatenated quantifiers                                   | ✅  |    | 🔧 |    |
+| [prefer-escape-replacement-dollar-char](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-escape-replacement-dollar-char.html) | enforces escape of replacement `$` character (`$$`).                                       |    |    |    |    |
+| [prefer-predefined-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-predefined-assertion.html)                     | prefer predefined assertion over equivalent lookarounds                                    | ✅  |    | 🔧 |    |
+| [prefer-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-quantifier.html)                                         | enforce using quantifier                                                                   |    |    | 🔧 |    |
+| [prefer-range](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-range.html)                                                   | enforce using character class range                                                        | ✅  |    | 🔧 |    |
+| [prefer-regexp-exec](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-regexp-exec.html)                                       | enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided |    |    |    |    |
+| [prefer-regexp-test](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-regexp-test.html)                                       | enforce that `RegExp#test` is used instead of `String#match` and `RegExp#exec`             |    |    | 🔧 |    |
+| [require-unicode-regexp](https://ota-meshi.github.io/eslint-plugin-regexp/rules/require-unicode-regexp.html)                               | enforce the use of the `u` flag                                                            |    |    | 🔧 |    |
+| [sort-alternatives](https://ota-meshi.github.io/eslint-plugin-regexp/rules/sort-alternatives.html)                                         | sort alternatives if order doesn't matter                                                  |    |    | 🔧 |    |
+| [use-ignore-case](https://ota-meshi.github.io/eslint-plugin-regexp/rules/use-ignore-case.html)                                             | use the `i` flag if it simplifies the pattern                                              |    |    | 🔧 |    |
 
 ### Stylistic Issues
 
-| Rule ID | Description |    |
-|:--------|:------------|:---|
-| [regexp/hexadecimal-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/hexadecimal-escape.html) | enforce consistent usage of hexadecimal escape | :wrench: |
-| [regexp/letter-case](https://ota-meshi.github.io/eslint-plugin-regexp/rules/letter-case.html) | enforce into your favorite case | :wrench: |
-| [regexp/match-any](https://ota-meshi.github.io/eslint-plugin-regexp/rules/match-any.html) | enforce match any character style | :star::wrench: |
-| [regexp/no-useless-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-escape.html) | disallow unnecessary escape characters in RegExp | :star::wrench: |
-| [regexp/no-useless-non-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-non-capturing-group.html) | disallow unnecessary Non-capturing group | :star::wrench: |
-| [regexp/prefer-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-character-class.html) | enforce using character class | :star::wrench: |
-| [regexp/prefer-d](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-d.html) | enforce using `\d` | :star::wrench: |
-| [regexp/prefer-lookaround](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-lookaround.html) | prefer lookarounds over capturing group that do not replace | :wrench: |
-| [regexp/prefer-named-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-backreference.html) | enforce using named backreferences | :wrench: |
-| [regexp/prefer-named-capture-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-capture-group.html) | enforce using named capture groups |  |
-| [regexp/prefer-named-replacement](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-replacement.html) | enforce using named replacement | :wrench: |
-| [regexp/prefer-plus-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-plus-quantifier.html) | enforce using `+` quantifier | :star::wrench: |
-| [regexp/prefer-question-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-question-quantifier.html) | enforce using `?` quantifier | :star::wrench: |
-| [regexp/prefer-result-array-groups](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-result-array-groups.html) | enforce using result array `groups` | :wrench: |
-| [regexp/prefer-star-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-star-quantifier.html) | enforce using `*` quantifier | :star::wrench: |
-| [regexp/prefer-unicode-codepoint-escapes](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-unicode-codepoint-escapes.html) | enforce use of unicode codepoint escapes | :star::wrench: |
-| [regexp/prefer-w](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-w.html) | enforce using `\w` | :star::wrench: |
-| [regexp/sort-character-class-elements](https://ota-meshi.github.io/eslint-plugin-regexp/rules/sort-character-class-elements.html) | enforces elements order in character class | :wrench: |
-| [regexp/sort-flags](https://ota-meshi.github.io/eslint-plugin-regexp/rules/sort-flags.html) | require regex flags to be sorted | :star::wrench: |
-| [regexp/unicode-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/unicode-escape.html) | enforce consistent usage of unicode escape or unicode codepoint escape | :wrench: |
+| Name                                                                                                                             | Description                                                            | 💼 | ⚠️ | 🔧 | 💡 |
+| :------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------- | :- | :- | :- | :- |
+| [hexadecimal-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/hexadecimal-escape.html)                             | enforce consistent usage of hexadecimal escape                         |    |    | 🔧 |    |
+| [letter-case](https://ota-meshi.github.io/eslint-plugin-regexp/rules/letter-case.html)                                           | enforce into your favorite case                                        |    |    | 🔧 |    |
+| [match-any](https://ota-meshi.github.io/eslint-plugin-regexp/rules/match-any.html)                                               | enforce match any character style                                      | ✅  |    | 🔧 |    |
+| [no-useless-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-escape.html)                               | disallow unnecessary escape characters in RegExp                       | ✅  |    | 🔧 |    |
+| [no-useless-non-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-non-capturing-group.html)     | disallow unnecessary Non-capturing group                               | ✅  |    | 🔧 |    |
+| [prefer-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-character-class.html)                     | enforce using character class                                          | ✅  |    | 🔧 |    |
+| [prefer-d](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-d.html)                                                 | enforce using `\d`                                                     | ✅  |    | 🔧 |    |
+| [prefer-lookaround](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-lookaround.html)                               | prefer lookarounds over capturing group that do not replace            |    |    | 🔧 |    |
+| [prefer-named-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-backreference.html)             | enforce using named backreferences                                     |    |    | 🔧 |    |
+| [prefer-named-capture-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-capture-group.html)             | enforce using named capture groups                                     |    |    |    |    |
+| [prefer-named-replacement](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-replacement.html)                 | enforce using named replacement                                        |    |    | 🔧 |    |
+| [prefer-plus-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-plus-quantifier.html)                     | enforce using `+` quantifier                                           | ✅  |    | 🔧 |    |
+| [prefer-question-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-question-quantifier.html)             | enforce using `?` quantifier                                           | ✅  |    | 🔧 |    |
+| [prefer-result-array-groups](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-result-array-groups.html)             | enforce using result array `groups`                                    |    |    | 🔧 |    |
+| [prefer-star-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-star-quantifier.html)                     | enforce using `*` quantifier                                           | ✅  |    | 🔧 |    |
+| [prefer-unicode-codepoint-escapes](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-unicode-codepoint-escapes.html) | enforce use of unicode codepoint escapes                               | ✅  |    | 🔧 |    |
+| [prefer-w](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-w.html)                                                 | enforce using `\w`                                                     | ✅  |    | 🔧 |    |
+| [sort-character-class-elements](https://ota-meshi.github.io/eslint-plugin-regexp/rules/sort-character-class-elements.html)       | enforces elements order in character class                             |    |    | 🔧 |    |
+| [sort-flags](https://ota-meshi.github.io/eslint-plugin-regexp/rules/sort-flags.html)                                             | require regex flags to be sorted                                       | ✅  |    | 🔧 |    |
+| [unicode-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/unicode-escape.html)                                     | enforce consistent usage of unicode escape or unicode codepoint escape |    |    | 🔧 |    |
 
 ### Deprecated
 
-- :warning: We're going to remove deprecated rules in the next major release. Please migrate to successor/new rules.
-- :innocent: We don't fix bugs which are in deprecated rules since we don't have enough resources.
+| Name                                                                                                                       | Description                                   | 💼 | ⚠️ | 🔧 | 💡 |
+| :------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------- | :- | :- | :- | :- |
+| [no-assertion-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-assertion-capturing-group.html)   | disallow capturing group that captures empty. |    |    |    |    |
+| [no-useless-exactly-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-exactly-quantifier.html) | disallow unnecessary exactly quantifier       |    |    |    |    |
+| [no-useless-non-greedy](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-non-greedy.html)                 | disallow unnecessarily non-greedy quantifiers |    |    | 🔧 |    |
+| [order-in-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/order-in-character-class.html)           | enforces elements order in character class    |    |    | 🔧 |    |
+| [prefer-t](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-t.html)                                           | enforce using `\t`                            |    |    | 🔧 |    |
 
-| Rule ID | Replaced by |
-|:--------|:------------|
-| [regexp/no-assertion-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-assertion-capturing-group.html) | [regexp/no-empty-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-capturing-group.html) |
-| [regexp/no-useless-exactly-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-exactly-quantifier.html) | [regexp/no-useless-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-quantifier.html), [regexp/no-zero-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-zero-quantifier.html) |
-| [regexp/no-useless-non-greedy](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-non-greedy.html) | [regexp/no-useless-lazy](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-lazy.html) |
-| [regexp/order-in-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/order-in-character-class.html) | [regexp/sort-character-class-elements](https://ota-meshi.github.io/eslint-plugin-regexp/rules/sort-character-class-elements.html) |
-| [regexp/prefer-t](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-t.html) | [regexp/control-character-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/control-character-escape.html) |
+<!-- end auto-generated rules list -->
 
-<!--RULES_TABLE_END-->
-<!--RULES_SECTION_END-->
-
 ## :gear: Settings
 
diff --git a/dist/utils/fix-simplify-quantifier.js b/dist/utils/fix-simplify-quantifier.js
new file mode 100644
index v1.11.0..v1.12.0 
--- a/dist/utils/fix-simplify-quantifier.js
+++ b/dist/utils/fix-simplify-quantifier.js
@@ -0,0 +1,47 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.fixSimplifyQuantifier = void 0;
+const regexp_ast_analysis_1 = require("regexp-ast-analysis");
+const _1 = require(".");
+function fixSimplifyQuantifier(quantifier, result, { fixReplaceNode }) {
+    const ancestor = getClosestAncestorOfAll([
+        quantifier,
+        ...result.dependencies,
+    ]);
+    let replacement;
+    if (quantifier.min === 0) {
+        replacement = "";
+    }
+    else if (quantifier.min === 1) {
+        replacement = quantifier.element.raw;
+    }
+    else {
+        replacement =
+            quantifier.element.raw +
+                (0, _1.quantToString)({
+                    min: quantifier.min,
+                    max: quantifier.min,
+                    greedy: true,
+                });
+    }
+    return [
+        replacement,
+        fixReplaceNode(ancestor, () => {
+            return (ancestor.raw.slice(0, quantifier.start - ancestor.start) +
+                replacement +
+                ancestor.raw.slice(quantifier.end - ancestor.start));
+        }),
+    ];
+}
+exports.fixSimplifyQuantifier = fixSimplifyQuantifier;
+function getClosestAncestorOfAll(elements) {
+    let leftMost = elements[0];
+    let rightMost = elements[0];
+    for (const e of elements) {
+        if (e.start < leftMost.start)
+            leftMost = e;
+        if (e.end > rightMost.end)
+            rightMost = e;
+    }
+    return (0, regexp_ast_analysis_1.getClosestAncestor)(leftMost, rightMost);
+}
diff --git a/dist/rules/no-misleading-capturing-group.js b/dist/rules/no-misleading-capturing-group.js
new file mode 100644
index v1.11.0..v1.12.0 
--- a/dist/rules/no-misleading-capturing-group.js
+++ b/dist/rules/no-misleading-capturing-group.js
@@ -0,0 +1,300 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const utils_1 = require("../utils");
+const regexp_ast_analysis_1 = require("regexp-ast-analysis");
+const simplify_quantifier_1 = require("../utils/regexp-ast/simplify-quantifier");
+const fix_simplify_quantifier_1 = require("../utils/fix-simplify-quantifier");
+const mention_1 = require("../utils/mention");
+const regexp_ast_1 = require("../utils/regexp-ast");
+const refa_1 = require("refa");
+function assertNever(value) {
+    throw new Error(`Invalid value: ${value}`);
+}
+function* iterReverse(array) {
+    for (let i = array.length - 1; i >= 0; i--) {
+        yield array[i];
+    }
+}
+function* getStartQuantifiers(root, direction) {
+    if (Array.isArray(root)) {
+        for (const a of root) {
+            yield* getStartQuantifiers(a, direction);
+        }
+        return;
+    }
+    switch (root.type) {
+        case "Character":
+        case "CharacterClass":
+        case "CharacterSet":
+        case "Backreference":
+            break;
+        case "Assertion":
+            break;
+        case "Alternative": {
+            const elements = direction === "ltr" ? root.elements : iterReverse(root.elements);
+            for (const e of elements) {
+                if ((0, regexp_ast_analysis_1.isEmpty)(e))
+                    continue;
+                yield* getStartQuantifiers(e, direction);
+                break;
+            }
+            break;
+        }
+        case "CapturingGroup":
+            break;
+        case "Group":
+            yield* getStartQuantifiers(root.alternatives, direction);
+            break;
+        case "Quantifier":
+            yield root;
+            if (root.max === 1) {
+                yield* getStartQuantifiers(root.element, direction);
+            }
+            break;
+        default:
+            yield assertNever(root);
+    }
+}
+function hasCapturingGroup(node) {
+    return (0, regexp_ast_analysis_1.hasSomeDescendant)(node, (d) => d.type === "CapturingGroup");
+}
+const caches = new WeakMap();
+function getCache(flags) {
+    let cache = caches.get(flags);
+    if (cache === undefined) {
+        cache = new WeakMap();
+        caches.set(flags, cache);
+    }
+    return cache;
+}
+function getSingleRepeatedChar(element, flags, cache = getCache(flags)) {
+    let value = cache.get(element);
+    if (value === undefined) {
+        value = uncachedGetSingleRepeatedChar(element, flags, cache);
+        cache.set(element, value);
+    }
+    return value;
+}
+function uncachedGetSingleRepeatedChar(element, flags, cache) {
+    switch (element.type) {
+        case "Alternative": {
+            let total = undefined;
+            for (const e of element.elements) {
+                const c = getSingleRepeatedChar(e, flags, cache);
+                if (total === undefined) {
+                    total = c;
+                }
+                else {
+                    total = total.intersect(c);
+                }
+                if (total.isEmpty)
+                    return total;
+            }
+            return total !== null && total !== void 0 ? total : regexp_ast_analysis_1.Chars.empty(flags);
+        }
+        case "Assertion":
+            return regexp_ast_analysis_1.Chars.empty(flags);
+        case "Backreference":
+            return regexp_ast_analysis_1.Chars.empty(flags);
+        case "Character":
+        case "CharacterClass":
+        case "CharacterSet":
+            return (0, regexp_ast_analysis_1.toCharSet)(element, flags);
+        case "CapturingGroup":
+        case "Group":
+            return element.alternatives
+                .map((a) => getSingleRepeatedChar(a, flags, cache))
+                .reduce((a, b) => a.union(b));
+        case "Quantifier":
+            if (element.max === 0)
+                return regexp_ast_analysis_1.Chars.empty(flags);
+            return getSingleRepeatedChar(element.element, flags, cache);
+        default:
+            return assertNever(element);
+    }
+}
+function getTradingQuantifiersAfter(start, startChar, direction, flags) {
+    const results = [];
+    (0, regexp_ast_analysis_1.followPaths)(start, "next", startChar, {
+        join(states) {
+            return refa_1.CharSet.empty(startChar.maximum).union(...states);
+        },
+        continueAfter(_, state) {
+            return !state.isEmpty;
+        },
+        continueInto(element, state) {
+            return element.type !== "Assertion" && !state.isEmpty;
+        },
+        leave(element, state) {
+            switch (element.type) {
+                case "Assertion":
+                case "Backreference":
+                case "Character":
+                case "CharacterClass":
+                case "CharacterSet":
+                    return state.intersect(getSingleRepeatedChar(element, flags));
+                case "CapturingGroup":
+                case "Group":
+                case "Quantifier":
+                    return state;
+                default:
+                    return assertNever(element);
+            }
+        },
+        enter(element, state) {
+            if (element.type === "Quantifier" &&
+                element.min !== element.max) {
+                const qChar = getSingleRepeatedChar(element, flags);
+                const intersection = qChar.intersect(state);
+                if (!intersection.isEmpty) {
+                    results.push({
+                        quant: element,
+                        quantRepeatedChar: qChar,
+                        intersection,
+                    });
+                }
+            }
+            return state;
+        },
+    }, direction);
+    return results;
+}
+exports.default = (0, utils_1.createRule)("no-misleading-capturing-group", {
+    meta: {
+        docs: {
+            description: "disallow capturing groups that do not behave as one would expect",
+            category: "Possible Errors",
+            recommended: false,
+        },
+        hasSuggestions: true,
+        schema: [
+            {
+                type: "object",
+                properties: {
+                    reportBacktrackingEnds: { type: "boolean" },
+                },
+                additionalProperties: false,
+            },
+        ],
+        messages: {
+            removeQuant: "{{quant}} can be removed because it is already included by {{cause}}." +
+                " This makes the capturing group misleading, because it actually captures less text than its pattern suggests.",
+            replaceQuant: "{{quant}} can be replaced with {{fix}} because of {{cause}}." +
+                " This makes the capturing group misleading, because it actually captures less text than its pattern suggests.",
+            suggestionRemove: "Remove {{quant}}.",
+            suggestionReplace: "Replace {{quant}} with {{fix}}.",
+            nonAtomic: "The quantifier {{quant}} is not atomic for the characters {{chars}}, so it might capture fewer characters than expected. This makes the capturing group misleading, because the quantifier will capture fewer characters than its pattern suggests in some edge cases.",
+            suggestionNonAtomic: "Make the quantifier atomic by adding {{fix}}. Careful! This is going to change the behavior of the regex in some edge cases.",
+            trading: "The quantifier {{quant}} can exchange characters ({{chars}}) with {{other}}. This makes the capturing group misleading, because the quantifier will capture fewer characters than its pattern suggests.",
+        },
+        type: "problem",
+    },
+    create(context) {
+        var _a, _b;
+        const reportBacktrackingEnds = (_b = (_a = context.options[0]) === null || _a === void 0 ? void 0 : _a.reportBacktrackingEnds) !== null && _b !== void 0 ? _b : true;
+        function createVisitor(regexpContext) {
+            const { node, flags, getRegexpLocation } = regexpContext;
+            const parser = (0, regexp_ast_1.getParser)(regexpContext);
+            function reportStartQuantifiers(capturingGroup) {
+                const direction = (0, regexp_ast_analysis_1.getMatchingDirection)(capturingGroup);
+                const startQuantifiers = getStartQuantifiers(capturingGroup.alternatives, direction);
+                for (const quantifier of startQuantifiers) {
+                    const result = (0, simplify_quantifier_1.canSimplifyQuantifier)(quantifier, flags, parser);
+                    if (!result.canSimplify)
+                        return;
+                    const cause = (0, mention_1.joinEnglishList)(result.dependencies.map((d) => (0, mention_1.mention)(d)));
+                    const [replacement, fix] = (0, fix_simplify_quantifier_1.fixSimplifyQuantifier)(quantifier, result, regexpContext);
+                    if (quantifier.min === 0) {
+                        const removesCapturingGroup = hasCapturingGroup(quantifier);
+                        context.report({
+                            node,
+                            loc: getRegexpLocation(quantifier),
+                            messageId: "removeQuant",
+                            data: {
+                                quant: (0, mention_1.mention)(quantifier),
+                                cause,
+                            },
+                            suggest: removesCapturingGroup
+                                ? undefined
+                                : [
+                                    {
+                                        messageId: "suggestionRemove",
+                                        data: {
+                                            quant: (0, mention_1.mention)(quantifier),
+                                        },
+                                        fix,
+                                    },
+                                ],
+                        });
+                    }
+                    else {
+                        context.report({
+                            node,
+                            loc: getRegexpLocation(quantifier),
+                            messageId: "replaceQuant",
+                            data: {
+                                quant: (0, mention_1.mention)(quantifier),
+                                fix: (0, mention_1.mention)(replacement),
+                                cause,
+                            },
+                            suggest: [
+                                {
+                                    messageId: "suggestionReplace",
+                                    data: {
+                                        quant: (0, mention_1.mention)(quantifier),
+                                        fix: (0, mention_1.mention)(replacement),
+                                    },
+                                    fix,
+                                },
+                            ],
+                        });
+                    }
+                }
+            }
+            function reportTradingEndQuantifiers(capturingGroup) {
+                const direction = (0, regexp_ast_analysis_1.getMatchingDirection)(capturingGroup);
+                const endQuantifiers = getStartQuantifiers(capturingGroup.alternatives, (0, regexp_ast_analysis_1.invertMatchingDirection)(direction));
+                for (const quantifier of endQuantifiers) {
+                    if (!quantifier.greedy) {
+                        continue;
+                    }
+                    if (quantifier.min === quantifier.max) {
+                        continue;
+                    }
+                    const qChar = getSingleRepeatedChar(quantifier, flags);
+                    if (qChar.isEmpty) {
+                        continue;
+                    }
+                    for (const trader of getTradingQuantifiersAfter(quantifier, qChar, direction, flags)) {
+                        if ((0, regexp_ast_analysis_1.hasSomeDescendant)(capturingGroup, trader.quant)) {
+                            continue;
+                        }
+                        if (trader.quant.min >= 1 &&
+                            !(0, regexp_ast_analysis_1.isPotentiallyZeroLength)(trader.quant.element))
+                            context.report({
+                                node,
+                                loc: getRegexpLocation(quantifier),
+                                messageId: "trading",
+                                data: {
+                                    quant: (0, mention_1.mention)(quantifier),
+                                    other: (0, mention_1.mention)(trader.quant),
+                                    chars: (0, utils_1.toCharSetSource)(trader.intersection, flags),
+                                },
+                            });
+                    }
+                }
+            }
+            return {
+                onCapturingGroupLeave(capturingGroup) {
+                    reportStartQuantifiers(capturingGroup);
+                    if (reportBacktrackingEnds) {
+                        reportTradingEndQuantifiers(capturingGroup);
+                    }
+                },
+            };
+        }
+        return (0, utils_1.defineRegexpVisitor)(context, {
+            createVisitor,
+        });
+    },
+});
diff --git a/dist/utils/regexp-ast/simplify-quantifier.js b/dist/utils/regexp-ast/simplify-quantifier.js
new file mode 100644
index v1.11.0..v1.12.0 
--- a/dist/utils/regexp-ast/simplify-quantifier.js
+++ b/dist/utils/regexp-ast/simplify-quantifier.js
@@ -0,0 +1,264 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.canSimplifyQuantifier = void 0;
+const refa_1 = require("refa");
+const regexp_ast_analysis_1 = require("regexp-ast-analysis");
+const _1 = require(".");
+function weakCachedFn(fn) {
+    const cache = new WeakMap();
+    return (value) => {
+        let result = cache.get(value);
+        if (result === undefined) {
+            result = fn(value);
+            cache.set(value, result);
+        }
+        return result;
+    };
+}
+const containsAssertions = weakCachedFn((node) => {
+    return (0, regexp_ast_analysis_1.hasSomeDescendant)(node, (n) => n.type === "Assertion");
+});
+const cachedGetPossiblyConsumedChar = weakCachedFn((flags) => {
+    return weakCachedFn((element) => (0, _1.getPossiblyConsumedChar)(element, flags));
+});
+const CANNOT_SIMPLIFY = { canSimplify: false };
+function canSimplifyQuantifier(quantifier, flags, parser) {
+    if (quantifier.min === quantifier.max) {
+        return CANNOT_SIMPLIFY;
+    }
+    if ((0, regexp_ast_analysis_1.isZeroLength)(quantifier)) {
+        return CANNOT_SIMPLIFY;
+    }
+    if (containsAssertions(quantifier)) {
+        return CANNOT_SIMPLIFY;
+    }
+    const direction = (0, regexp_ast_analysis_1.getMatchingDirection)(quantifier);
+    const preceding = getPrecedingQuantifiers(quantifier, direction);
+    if (!preceding) {
+        return CANNOT_SIMPLIFY;
+    }
+    return canAbsorb(preceding, { direction, flags, parser, quantifier });
+}
+exports.canSimplifyQuantifier = canSimplifyQuantifier;
+function canAbsorb(initialPreceding, options) {
+    const { direction, flags, parser, quantifier } = options;
+    const preceding = removeTargetQuantifier(initialPreceding, quantifier, direction);
+    if (!preceding) {
+        return CANNOT_SIMPLIFY;
+    }
+    const dependencies = [...preceding];
+    const CAN_SIMPLIFY = {
+        canSimplify: true,
+        dependencies,
+    };
+    const fast = everyMaybe(preceding, (q) => canAbsorbElementFast(q, quantifier.element, flags));
+    if (typeof fast === "boolean") {
+        return fast ? CAN_SIMPLIFY : CANNOT_SIMPLIFY;
+    }
+    const formal = everyMaybe(fast, (q) => canAbsorbElementFormal(q, quantifier.element, parser));
+    if (typeof formal === "boolean") {
+        return formal ? CAN_SIMPLIFY : CANNOT_SIMPLIFY;
+    }
+    return formal.every((q) => {
+        const parts = splitQuantifierIntoTails(q, direction);
+        if (!parts)
+            return false;
+        const result = canAbsorb(parts, options);
+        if (result.canSimplify)
+            dependencies.push(...result.dependencies);
+        return result.canSimplify;
+    })
+        ? CAN_SIMPLIFY
+        : CANNOT_SIMPLIFY;
+}
+function everyMaybe(array, fn) {
+    const maybe = [];
+    for (const item of array) {
+        const result = fn(item);
+        if (result === false)
+            return false;
+        if (result === undefined)
+            maybe.push(item);
+    }
+    if (maybe.length === 0)
+        return true;
+    return maybe;
+}
+function canAbsorbElementFast(quantifier, element, flags) {
+    if (!quantifier.greedy) {
+        return false;
+    }
+    if (!isNonFinite(quantifier)) {
+        return false;
+    }
+    const qChar = cachedGetPossiblyConsumedChar(flags)(quantifier.element);
+    const eChar = cachedGetPossiblyConsumedChar(flags)(element);
+    if (qChar.char.isDisjointWith(eChar.char)) {
+        return false;
+    }
+    if (eChar.exact && !eChar.char.without(qChar.char).isEmpty) {
+        return false;
+    }
+    if (containsAssertions(quantifier) || containsAssertions(element)) {
+        return undefined;
+    }
+    if (quantifier.element.type === "Character" ||
+        quantifier.element.type === "CharacterClass" ||
+        quantifier.element.type === "CharacterSet") {
+        if (quantifier.max !== Infinity) {
+            return false;
+        }
+        if (qChar.exact && qChar.char.isSupersetOf(eChar.char)) {
+            return true;
+        }
+    }
+    return undefined;
+}
+function isNonFinite(node) {
+    return (0, regexp_ast_analysis_1.hasSomeDescendant)(node, (n) => n.type === "Quantifier" &&
+        n.max === Infinity &&
+        !(0, regexp_ast_analysis_1.isZeroLength)(n.element), (n) => n.type !== "Assertion");
+}
+function toNfa(element, parser) {
+    const { expression, maxCharacter } = parser.parseElement(element, {
+        maxNodes: 1000,
+        assertions: "throw",
+        backreferences: "throw",
+    });
+    return refa_1.NFA.fromRegex(expression, { maxCharacter }, { maxNodes: 1000 });
+}
+function canAbsorbElementFormal(quantifier, element, parser) {
+    if (containsAssertions(quantifier) || containsAssertions(element)) {
+        return undefined;
+    }
+    try {
+        const qNfa = toNfa(quantifier, parser);
+        const qDfa = refa_1.DFA.fromFA(qNfa, { maxNodes: 1000 });
+        const eNfa = toNfa(element, parser);
+        eNfa.quantify(0, 1);
+        qNfa.append(eNfa);
+        const qeDfa = refa_1.DFA.fromFA(qNfa, { maxNodes: 1000 });
+        qDfa.minimize();
+        qeDfa.minimize();
+        const equal = qDfa.structurallyEqual(qeDfa);
+        return equal;
+    }
+    catch (_a) {
+    }
+    return undefined;
+}
+function splitQuantifierIntoTails(quantifier, direction) {
+    if ((0, regexp_ast_analysis_1.isPotentiallyZeroLength)(quantifier)) {
+        return undefined;
+    }
+    return getTailQuantifiers(quantifier.element, direction);
+}
+function removeTargetQuantifier(quantifiers, target, direction) {
+    const result = [];
+    for (const q of quantifiers) {
+        if ((0, regexp_ast_analysis_1.hasSomeDescendant)(q, target)) {
+            const inner = splitQuantifierIntoTails(q, direction);
+            if (inner === undefined) {
+                return undefined;
+            }
+            const mapped = removeTargetQuantifier(inner, target, direction);
+            if (mapped === undefined) {
+                return undefined;
+            }
+            result.push(...mapped);
+        }
+        else {
+            result.push(q);
+        }
+    }
+    return result;
+}
+function assertNever(value) {
+    throw new Error(`Invalid value: ${value}`);
+}
+function* iterReverse(array) {
+    for (let i = array.length - 1; i >= 0; i--) {
+        yield array[i];
+    }
+}
+function unionQuantifiers(sets) {
+    const result = [];
+    for (const set of sets) {
+        if (set === undefined) {
+            return undefined;
+        }
+        result.push(...set);
+    }
+    if (result.length === 0)
+        return undefined;
+    return [...new Set(result)];
+}
+function getTailQuantifiers(element, direction) {
+    switch (element.type) {
+        case "Assertion":
+        case "Backreference":
+        case "Character":
+        case "CharacterClass":
+        case "CharacterSet":
+            return undefined;
+        case "Quantifier":
+            return [element];
+        case "Group":
+        case "CapturingGroup":
+            return unionQuantifiers(element.alternatives.map((a) => getTailQuantifiers(a, direction)));
+        case "Alternative": {
+            const elements = direction === "ltr"
+                ? iterReverse(element.elements)
+                : element.elements;
+            for (const e of elements) {
+                if ((0, regexp_ast_analysis_1.isEmpty)(e))
+                    continue;
+                if (e.type === "Quantifier") {
+                    return [e];
+                }
+                return undefined;
+            }
+            const { parent } = element;
+            if (parent.type === "Pattern") {
+                return undefined;
+            }
+            if (parent.type === "Assertion") {
+                return undefined;
+            }
+            return getPrecedingQuantifiers(parent, direction);
+        }
+        default:
+            return assertNever(element);
+    }
+}
+function getPrecedingQuantifiers(element, direction) {
+    const parent = element.parent;
+    if (parent.type === "Quantifier") {
+        if (parent.max === 0) {
+            return undefined;
+        }
+        if (parent.max === 1) {
+            return getPrecedingQuantifiers(parent, direction);
+        }
+        return unionQuantifiers([
+            getPrecedingQuantifiers(parent, direction),
+            getTailQuantifiers(parent.element, direction),
+        ]);
+    }
+    if (parent.type !== "Alternative") {
+        return undefined;
+    }
+    const inc = direction === "ltr" ? -1 : +1;
+    const { elements } = parent;
+    const elementIndex = elements.indexOf(element);
+    for (let precedingIndex = elementIndex + inc; precedingIndex >= 0 && precedingIndex < elements.length; precedingIndex += inc) {
+        const preceding = parent.elements[precedingIndex];
+        if ((0, regexp_ast_analysis_1.isEmpty)(preceding))
+            continue;
+        return getTailQuantifiers(preceding, direction);
+    }
+    if (parent.parent.type === "Pattern") {
+        return undefined;
+    }
+    return getPrecedingQuantifiers(parent.parent, direction);
+}
Size Files
625.7 KB → 660.4 KB (+34.7 KB 🟡) 128 → 131 (+3 🟡)
Command details
npm diff --diff=eslint-plugin-regexp@1.11.0 --diff=eslint-plugin-regexp@1.12.0 --diff-unified=2

See also the npm diff document.

Reported by ybiquitous/npm-diff-action@v1.4.1 (Node.js 18.13.0 and npm 9.4.1)

@ybiquitous ybiquitous changed the title chore(deps): bump eslint-plugin-regexp from 1.11.0 to 1.12.0 feat(deps): bump eslint-plugin-regexp from 1.11.0 to 1.12.0 Feb 2, 2023
@ybiquitous ybiquitous merged commit b60d40e into main Feb 2, 2023
@ybiquitous ybiquitous deleted the dependabot/npm_and_yarn/eslint-plugin-regexp-1.12.0 branch February 2, 2023 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file javascript Pull requests that update Javascript code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant