Skip to content

Commit 736dc54

Browse files
authored
Fix false positives for greedy flags in regexp/prefer-quantifier rule (#30)
1 parent 61ed114 commit 736dc54

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

lib/rules/prefer-quantifier.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class CharBuffer {
2121

2222
public equalChar: (element: CharacterSet | Character) => boolean
2323

24+
public greedy: boolean | null = null
25+
2426
public constructor(
2527
element: CharacterSet | Character | Quantifier,
2628
target: CharacterSet | Character,
@@ -31,6 +33,9 @@ class CharBuffer {
3133
if (element.type === "Quantifier") {
3234
this.min = element.min
3335
this.max = element.max
36+
if (element.min < element.max) {
37+
this.greedy = element.greedy
38+
}
3439
} else {
3540
this.min = 1
3641
this.max = 1
@@ -64,6 +69,9 @@ class CharBuffer {
6469
if (element.type === "Quantifier") {
6570
this.min += element.min
6671
this.max += element.max
72+
if (element.min < element.max) {
73+
this.greedy ||= element.greedy
74+
}
6775
} else {
6876
this.min += 1
6977
this.max += 1
@@ -106,18 +114,19 @@ class CharBuffer {
106114
}
107115

108116
public getQuantifier(): string {
117+
const greedy = this.greedy === false ? "?" : ""
109118
if (this.min === 0 && this.max === Number.POSITIVE_INFINITY) {
110-
return "*"
119+
return `*${greedy}`
111120
} else if (this.min === 1 && this.max === Number.POSITIVE_INFINITY) {
112-
return "+"
121+
return `+${greedy}`
113122
} else if (this.min === 0 && this.max === 1) {
114-
return "?"
123+
return `?${greedy}`
115124
} else if (this.min === this.max) {
116125
return `{${this.min}}`
117126
} else if (this.max === Number.POSITIVE_INFINITY) {
118-
return `{${this.min},}`
127+
return `{${this.min},}${greedy}`
119128
}
120-
return `{${this.min},${this.max}}`
129+
return `{${this.min},${this.max}}${greedy}`
121130
}
122131
}
123132

@@ -156,17 +165,25 @@ export default createRule("prefer-quantifier", {
156165
target = element
157166
} else if (element.type === "Quantifier") {
158167
if (
159-
element.element.type === "CharacterSet" ||
160-
element.element.type === "Character"
168+
element.element.type !== "CharacterSet" &&
169+
element.element.type !== "Character"
161170
) {
162-
target = element.element
163-
} else {
164171
if (charBuffer) {
165172
validateBuffer(charBuffer)
166173
charBuffer = null
167174
}
168175
continue
169176
}
177+
if (
178+
charBuffer &&
179+
charBuffer.greedy != null &&
180+
charBuffer.greedy !== element.greedy
181+
) {
182+
// greedy flags do not match.
183+
validateBuffer(charBuffer)
184+
charBuffer = null
185+
}
186+
target = element.element
170187
} else {
171188
if (charBuffer) {
172189
validateBuffer(charBuffer)

tests/lib/rules/prefer-quantifier.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ tester.run("prefer-quantifier", rule as any, {
1717
`/<!--/`,
1818
`/\`\`\`/`,
1919
`/---/`,
20+
`/a.{1,3}?.{2,4}c/`,
21+
`/a.{1,3}.{2,4}?c/`,
2022
],
2123
invalid: [
2224
{
@@ -137,5 +139,19 @@ tester.run("prefer-quantifier", rule as any, {
137139
'Unexpected consecutive same characters. Use "{0,3}" instead.',
138140
],
139141
},
142+
{
143+
code: `/a.{1,3}?.{2,4}?c/`,
144+
output: `/a.{3,7}?c/`,
145+
errors: [
146+
'Unexpected consecutive same character sets. Use "{3,7}?" instead.',
147+
],
148+
},
149+
{
150+
code: `/a.{1,3}.{2,4}c/`,
151+
output: `/a.{3,7}c/`,
152+
errors: [
153+
'Unexpected consecutive same character sets. Use "{3,7}" instead.',
154+
],
155+
},
140156
],
141157
})

0 commit comments

Comments
 (0)