Skip to content

Commit 2c76624

Browse files
authored
Fix false positives for symbols in regexp/prefer-quantifier rule (#25)
1 parent 03bacf7 commit 2c76624

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

lib/rules/prefer-quantifier.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
getRegexpRange,
88
isDigit,
99
isLetter,
10+
isSymbol,
1011
} from "../utils"
1112

1213
class CharBuffer {
@@ -73,14 +74,16 @@ class CharBuffer {
7374
if (this.elements.length < 2) {
7475
return true
7576
}
76-
let charKind: "digit" | "letter" | null = null
77+
let charKind: "digit" | "letter" | "symbol" | null = null
7778
for (const element of this.elements) {
7879
if (element.type === "Character") {
7980
if (charKind == null) {
8081
if (isDigit(element.value)) {
8182
charKind = "digit"
8283
} else if (isLetter(element.value)) {
8384
charKind = "letter"
85+
} else if (isSymbol(element.value)) {
86+
charKind = "symbol"
8487
} else {
8588
return false
8689
}
@@ -93,7 +96,9 @@ class CharBuffer {
9396
// It is valid when the same numbers are consecutive.
9497
charKind === "digit" ||
9598
// It is valid when the same letter character continues twice.
96-
(charKind === "letter" && this.elements.length <= 2)
99+
(charKind === "letter" && this.elements.length <= 2) ||
100+
// It is valid when the same symbol character continues three times.
101+
(charKind === "symbol" && this.elements.length <= 3)
97102
) {
98103
return true
99104
}

lib/utils/unicode.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ export const CP_VT = 11
44
export const CP_FF = 12
55
export const CP_CR = 13
66
export const CP_SPACE = " ".codePointAt(0)!
7+
export const CP_BAN = "!".codePointAt(0)!
8+
export const CP_SLASH = "/".codePointAt(0)!
9+
export const CP_COLON = ":".codePointAt(0)!
10+
export const CP_AT = "@".codePointAt(0)!
11+
export const CP_OPENING_BRACE = "[".codePointAt(0)!
12+
export const CP_BACKTICK = "`".codePointAt(0)!
13+
export const CP_OPENING_BRACKET = "{".codePointAt(0)!
14+
export const CP_TILDE = "~".codePointAt(0)!
715
export const CP_NEL = "\u0085".codePointAt(0)!
816
export const CP_NBSP = "\u00a0".codePointAt(0)!
917
export const CP_OGHAM_SPACE_MARK = "\u1680".codePointAt(0)!
@@ -91,6 +99,19 @@ export function isLetter(codePoint: number): boolean {
9199
isCodePointInRange(codePoint, CP_RANGE_CAPITAL_LETTER)
92100
)
93101
}
102+
/**
103+
* Checks if the given code point is symbol.
104+
* @param codePoint The code point to check
105+
* @returns {boolean} `true` if the given code point is symbol.
106+
*/
107+
export function isSymbol(codePoint: number): boolean {
108+
return (
109+
isCodePointInRange(codePoint, [CP_BAN, CP_SLASH]) ||
110+
isCodePointInRange(codePoint, [CP_COLON, CP_AT]) ||
111+
isCodePointInRange(codePoint, [CP_OPENING_BRACE, CP_BACKTICK]) ||
112+
isCodePointInRange(codePoint, [CP_OPENING_BRACKET, CP_TILDE])
113+
)
114+
}
94115

95116
/**
96117
* Checks if the given code point is space.

tests/lib/rules/prefer-quantifier.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,15 @@ const tester = new RuleTester({
99
})
1010

1111
tester.run("prefer-quantifier", rule as any, {
12-
valid: [`/regexp/`, `/\\d_\\d/`, `/Google/`, `/2000/`],
12+
valid: [
13+
`/regexp/`,
14+
`/\\d_\\d/`,
15+
`/Google/`,
16+
`/2000/`,
17+
`/<!--/`,
18+
`/\`\`\`/`,
19+
`/---/`,
20+
],
1321
invalid: [
1422
{
1523
code: `/\\d\\d/`,
@@ -25,8 +33,8 @@ tester.run("prefer-quantifier", rule as any, {
2533
],
2634
},
2735
{
28-
code: `/__/`,
29-
output: `/_{2}/`,
36+
code: `/ /`,
37+
output: `/ {2}/`,
3038
errors: [
3139
{
3240
message:
@@ -73,10 +81,10 @@ tester.run("prefer-quantifier", rule as any, {
7381
],
7482
},
7583
{
76-
code: String.raw`/__..\s\s\S\S\p{ASCII}\p{ASCII}/u`,
77-
output: String.raw`/_{2}..\s{2}\S\S\p{ASCII}{2}/u`,
84+
code: String.raw`/aaa..\s\s\S\S\p{ASCII}\p{ASCII}/u`,
85+
output: String.raw`/a{3}..\s{2}\S\S\p{ASCII}{2}/u`,
7886
errors: [
79-
'Unexpected consecutive same characters. Use "{2}" instead.',
87+
'Unexpected consecutive same characters. Use "{3}" instead.',
8088
'Unexpected consecutive same character sets. Use "{2}" instead.',
8189
'Unexpected consecutive same character sets. Use "{2}" instead.',
8290
'Unexpected consecutive same character sets. Use "{2}" instead.',

0 commit comments

Comments
 (0)