Repository: ota-meshi/eslint-plugin-regexp
Pull request #633 (2023-10-02 00:15:44)

Add support for string literal to `regexp/no-empty-alternative`
related to #545

changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: df76cd91b8700d2920e5e34a152d05b8ea0c1dbe

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/ota-meshi/eslint-plugin-regexp/new/no-empty-alternative-string?filename=.changeset/cold-nails-teach.md&value=---%0A%22eslint-plugin-regexp%22%3A%20patch%0A---%0A%0AAdd%20support%20for%20string%20literal%20to%20%60regexp%2Fno-empty-alternative%60%0A)



Patch:
diff --git a/.changeset/cold-nails-teach.md b/.changeset/cold-nails-teach.md
new file mode 100644
index 0000000..f46eec0
--- /dev/null
+++ b/.changeset/cold-nails-teach.md
@@ -0,0 +1,5 @@
+---
+"eslint-plugin-regexp": minor
+---
+
+Add support for string literal to `regexp/no-empty-alternative`
diff --git a/docs/rules/no-empty-alternative.md b/docs/rules/no-empty-alternative.md
index eb4b10c..ab77a2c 100644
--- a/docs/rules/no-empty-alternative.md
+++ b/docs/rules/no-empty-alternative.md
@@ -37,6 +37,7 @@ var foo = /a+|b*/
 var foo = /a+|b+|/
 var foo = /\|\||\|||\|\|\|/
 var foo = /a(?:a|bc|def|h||ij|k)/
+var foo = /[abc\q{def|}]/v
 ```
 
 </eslint-code-block>
diff --git a/lib/rules/no-empty-alternative.ts b/lib/rules/no-empty-alternative.ts
index 67c794f..f831b53 100644
--- a/lib/rules/no-empty-alternative.ts
+++ b/lib/rules/no-empty-alternative.ts
@@ -2,6 +2,7 @@ import type { RegExpVisitor } from "@eslint-community/regexpp/visitor"
 import type {
     Alternative,
     CapturingGroup,
+    ClassStringDisjunction,
     Group,
     Pattern,
 } from "@eslint-community/regexpp/ast"
@@ -73,8 +74,15 @@ export default createRule("no-empty-alternative", {
             getRegexpLocation,
             fixReplaceNode,
         }: RegExpContext): RegExpVisitor.Handlers {
-            function verifyAlternatives(
-                regexpNode: CapturingGroup | Group | Pattern,
+            function verifyAlternatives<
+                N extends
+                    | CapturingGroup
+                    | Group
+                    | Pattern
+                    | ClassStringDisjunction,
+            >(
+                regexpNode: N,
+                suggestFixer: (alt: N["alternatives"][number]) => string | null,
             ) {
                 if (regexpNode.alternatives.length >= 2) {
                     // We want to have at least two alternatives because the zero alternatives isn't possible because of
@@ -96,7 +104,7 @@ export default createRule("no-empty-alternative", {
                                       end: index + 1,
                                   })
 
-                            const fixed = getFixedNode(regexpNode, alt)
+                            const fixed = suggestFixer(alt)
 
                             context.report({
                                 node,
@@ -122,9 +130,20 @@ export default createRule("no-empty-alternative", {
             }
 
             return {
-                onGroupEnter: verifyAlternatives,
-                onCapturingGroupEnter: verifyAlternatives,
-                onPatternEnter: verifyAlternatives,
+                onGroupEnter: (gNode) =>
+                    verifyAlternatives(gNode, (alt) =>
+                        getFixedNode(gNode, alt),
+                    ),
+                onCapturingGroupEnter: (cgNode) =>
+                    verifyAlternatives(cgNode, (alt) =>
+                        getFixedNode(cgNode, alt),
+                    ),
+                onPatternEnter: (pNode) =>
+                    verifyAlternatives(pNode, (alt) =>
+                        getFixedNode(pNode, alt),
+                    ),
+                onClassStringDisjunctionEnter: (csdNode) =>
+                    verifyAlternatives(csdNode, () => null),
             }
         }
 


Test patch:
diff --git a/tests/lib/rules/no-empty-alternative.ts b/tests/lib/rules/no-empty-alternative.ts
index 010d8e7..7cfc9b2 100644
--- a/tests/lib/rules/no-empty-alternative.ts
+++ b/tests/lib/rules/no-empty-alternative.ts
@@ -3,13 +3,13 @@ import rule from "../../../lib/rules/no-empty-alternative"
 
 const tester = new RuleTester({
     parserOptions: {
-        ecmaVersion: 2020,
+        ecmaVersion: "latest",
         sourceType: "module",
     },
 })
 
 tester.run("no-empty-alternative", rule as any, {
-    valid: [`/()|(?:)|(?=)/`, `/(?:)/`, `/a*|b+/`],
+    valid: [`/()|(?:)|(?=)/`, `/(?:)/`, `/a*|b+/`, String.raw`/[\q{a|b}]/v`],
     invalid: [
         {
             code: `/|||||/`,
@@ -68,5 +68,35 @@ tester.run("no-empty-alternative", rule as any, {
                 },
             ],
         },
+        {
+            code: String.raw`/[\q{a|}]/v`,
+            errors: [
+                {
+                    messageId: "empty",
+                    column: 7,
+                    suggestions: [],
+                },
+            ],
+        },
+        {
+            code: String.raw`/[\q{|a}]/v`,
+            errors: [
+                {
+                    messageId: "empty",
+                    column: 6,
+                    suggestions: [],
+                },
+            ],
+        },
+        {
+            code: String.raw`/[\q{a||b}]/v`,
+            errors: [
+                {
+                    messageId: "empty",
+                    column: 8,
+                    suggestions: [],
+                },
+            ],
+        },
     ],
 })