Skip to content

Commit

Permalink
Add support for string literal to regexp/no-empty-alternative (#633)
Browse files Browse the repository at this point in the history
  • Loading branch information
ota-meshi authored Oct 2, 2023
1 parent 1ae35e6 commit 0e61e73
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/cold-nails-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-regexp": minor
---

Add support for string literal to `regexp/no-empty-alternative`
1 change: 1 addition & 0 deletions docs/rules/no-empty-alternative.md
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
31 changes: 25 additions & 6 deletions lib/rules/no-empty-alternative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { RegExpVisitor } from "@eslint-community/regexpp/visitor"
import type {
Alternative,
CapturingGroup,
ClassStringDisjunction,
Group,
Pattern,
} from "@eslint-community/regexpp/ast"
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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),
}
}

Expand Down
34 changes: 32 additions & 2 deletions tests/lib/rules/no-empty-alternative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: `/|||||/`,
Expand Down Expand Up @@ -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: [],
},
],
},
],
})

0 comments on commit 0e61e73

Please sign in to comment.