Skip to content

Commit 6d18a6c

Browse files
authored
Add no-regexp-unicode-property-escapes-(2020 - 2022) rule (#26)
* Add no-regexp-unicode-property-escapes-2020 rule * Add no-regexp-unicode-property-escapes-2021 rule * Fix test cases * WIP: Add no-regexp-unicode-property-escapes-2022 rule * update * Remove places where CLIEngine is used
1 parent 721c5cb commit 6d18a6c

25 files changed

+1129
-212
lines changed

.github/workflows/cron.yml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: cron
2+
on:
3+
schedule:
4+
- cron: 0 0 * * 0
5+
6+
jobs:
7+
check-resource-update:
8+
name: check-resource-update
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout
12+
uses: actions/checkout@v3
13+
- name: Install Node.js
14+
uses: actions/setup-node@v3
15+
with:
16+
node-version: 14
17+
- name: Install Packages
18+
run: npm install
19+
- name: Update
20+
run: npm run resource-update:unicode-properties
21+
- name: Check changes
22+
run: |
23+
git add --all && \
24+
git diff-index --cached HEAD --stat --exit-code

docs/rules/index.md

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ There are multiple configs that enable all rules in this category: `plugin:es-x/
2727
| [es-x/no-object-hasown](./no-object-hasown.md) | disallow the `Object.hasOwn` method. | |
2828
| [es-x/no-private-in](./no-private-in.md) | disallow `#x in obj`. | |
2929
| [es-x/no-regexp-d-flag](./no-regexp-d-flag.md) | disallow RegExp `d` flag. | |
30+
| [es-x/no-regexp-unicode-property-escapes-2022](./no-regexp-unicode-property-escapes-2022.md) | disallow the new values of RegExp Unicode property escape sequences in ES2022. | |
3031
| [es-x/no-top-level-await](./no-top-level-await.md) | disallow top-level `await`. | |
3132

3233
## ES2021
@@ -38,6 +39,7 @@ There are multiple configs that enable all rules in this category: `plugin:es-x/
3839
| [es-x/no-logical-assignment-operators](./no-logical-assignment-operators.md) | disallow logical assignment operators. | 🔧 |
3940
| [es-x/no-numeric-separators](./no-numeric-separators.md) | disallow numeric separators. | 🔧 |
4041
| [es-x/no-promise-any](./no-promise-any.md) | disallow `Promise.any` function and `AggregateError` class. | |
42+
| [es-x/no-regexp-unicode-property-escapes-2021](./no-regexp-unicode-property-escapes-2021.md) | disallow the new values of RegExp Unicode property escape sequences in ES2021. | |
4143
| [es-x/no-string-prototype-replaceall](./no-string-prototype-replaceall.md) | disallow the `String.prototype.replaceAll` method. | |
4244
| [es-x/no-weakrefs](./no-weakrefs.md) | disallow the `WeakRef` and `FinalizationRegistry` class. | |
4345

@@ -55,6 +57,7 @@ There are multiple configs that enable all rules in this category: `plugin:es-x/
5557
| [es-x/no-nullish-coalescing-operators](./no-nullish-coalescing-operators.md) | disallow nullish coalescing operators. | |
5658
| [es-x/no-optional-chaining](./no-optional-chaining.md) | disallow optional chaining. | |
5759
| [es-x/no-promise-all-settled](./no-promise-all-settled.md) | disallow `Promise.allSettled` function. | |
60+
| [es-x/no-regexp-unicode-property-escapes-2020](./no-regexp-unicode-property-escapes-2020.md) | disallow the new values of RegExp Unicode property escape sequences in ES2020. | |
5861
| [es-x/no-string-prototype-matchall](./no-string-prototype-matchall.md) | disallow the `String.prototype.matchAll` method. | |
5962

6063
## ES2019
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: "es-x/no-regexp-unicode-property-escapes-2020"
3+
description: "disallow the new values of RegExp Unicode property escape sequences in ES2020"
4+
---
5+
6+
# es-x/no-regexp-unicode-property-escapes-2020
7+
> disallow the new values of RegExp Unicode property escape sequences in ES2020
8+
9+
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
10+
- ✅ The following configurations enable this rule: `plugin:es-x/no-new-in-es2020`, `plugin:es-x/restrict-to-es3`, `plugin:es-x/restrict-to-es5`, `plugin:es-x/restrict-to-es2015`, `plugin:es-x/restrict-to-es2016`, `plugin:es-x/restrict-to-es2017`, `plugin:es-x/restrict-to-es2018`, and `plugin:es-x/restrict-to-es2019`
11+
12+
This rule reports the new values of ES2018 [RegExp Unicode property escape sequences](https://github.com/tc39/proposal-regexp-unicode-property-escapes#readme) which were added in ES2020.
13+
14+
For example, the following patterns are valid in ES2020, but syntax error in ES2019 environments:
15+
16+
- `\p{Script=Elym}`
17+
- `\p{Script=Elymaic}`
18+
- `\p{Script=Hmnp}`
19+
- `\p{Script=Nand}`
20+
- `\p{Script=Nandinagari}`
21+
- `\p{Script=Nyiakeng_Puachue_Hmong}`
22+
- `\p{Script=Wancho}`
23+
- `\p{Script=Wcho}`
24+
25+
## 💡 Examples
26+
27+
⛔ Examples of **incorrect** code for this rule:
28+
29+
<eslint-playground type="bad">
30+
31+
```js
32+
/*eslint es-x/no-regexp-unicode-property-escapes-2020: error */
33+
const r1 = /\p{Script=Elym}/u
34+
const r2 = /\p{Script=Elymaic}/u
35+
```
36+
37+
</eslint-playground>
38+
39+
## 📚 References
40+
41+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-es-x/blob/master/lib/rules/no-regexp-unicode-property-escapes-2020.js)
42+
- [Test source](https://github.com/ota-meshi/eslint-plugin-es-x/blob/master/tests/lib/rules/no-regexp-unicode-property-escapes-2020.js)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
title: "es-x/no-regexp-unicode-property-escapes-2021"
3+
description: "disallow the new values of RegExp Unicode property escape sequences in ES2021"
4+
---
5+
6+
# es-x/no-regexp-unicode-property-escapes-2021
7+
> disallow the new values of RegExp Unicode property escape sequences in ES2021
8+
9+
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
10+
- ✅ The following configurations enable this rule: `plugin:es-x/no-new-in-es2021`, `plugin:es-x/restrict-to-es3`, `plugin:es-x/restrict-to-es5`, `plugin:es-x/restrict-to-es2015`, `plugin:es-x/restrict-to-es2016`, `plugin:es-x/restrict-to-es2017`, `plugin:es-x/restrict-to-es2018`, `plugin:es-x/restrict-to-es2019`, and `plugin:es-x/restrict-to-es2020`
11+
12+
This rule reports the new values of ES2018 [RegExp Unicode property escape sequences](https://github.com/tc39/proposal-regexp-unicode-property-escapes#readme) which were added in ES2021.
13+
14+
For example, the following patterns are valid in ES2021, but syntax error in ES2020 environments:
15+
16+
- `\p{EBase}`
17+
- `\p{EComp}`
18+
- `\p{EMod}`
19+
- `\p{EPres}`
20+
- `\p{ExtPict}`
21+
- `\p{Script=Chorasmian}`
22+
- `\p{Script=Chrs}`
23+
- `\p{Script=Diak}`
24+
- `\p{Script=Dives_Akuru}`
25+
- `\p{Script=Khitan_Small_Script}`
26+
- `\p{Script=Kits}`
27+
- `\p{Script=Yezi}`
28+
- `\p{Script=Yezidi}`
29+
30+
## 💡 Examples
31+
32+
⛔ Examples of **incorrect** code for this rule:
33+
34+
<eslint-playground type="bad">
35+
36+
```js
37+
/*eslint es-x/no-regexp-unicode-property-escapes-2021: error */
38+
const r1 = /\p{EBase}/u
39+
const r2 = /\p{Script=Chorasmian}/u
40+
```
41+
42+
</eslint-playground>
43+
44+
## 📚 References
45+
46+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-es-x/blob/master/lib/rules/no-regexp-unicode-property-escapes-2021.js)
47+
- [Test source](https://github.com/ota-meshi/eslint-plugin-es-x/blob/master/tests/lib/rules/no-regexp-unicode-property-escapes-2021.js)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
title: "es-x/no-regexp-unicode-property-escapes-2022"
3+
description: "disallow the new values of RegExp Unicode property escape sequences in ES2022"
4+
---
5+
6+
# es-x/no-regexp-unicode-property-escapes-2022
7+
> disallow the new values of RegExp Unicode property escape sequences in ES2022
8+
9+
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
10+
- ✅ The following configurations enable this rule: `plugin:es-x/no-new-in-es2022`, `plugin:es-x/restrict-to-es3`, `plugin:es-x/restrict-to-es5`, `plugin:es-x/restrict-to-es2015`, `plugin:es-x/restrict-to-es2016`, `plugin:es-x/restrict-to-es2017`, `plugin:es-x/restrict-to-es2018`, `plugin:es-x/restrict-to-es2019`, `plugin:es-x/restrict-to-es2020`, and `plugin:es-x/restrict-to-es2021`
11+
12+
This rule reports the new values of ES2018 [RegExp Unicode property escape sequences](https://github.com/tc39/proposal-regexp-unicode-property-escapes#readme) which were added in ES2022.
13+
14+
For example, the following patterns are valid in ES2022, but syntax error in ES2020 environments:
15+
16+
- `\p{Script=Cpmn}`
17+
- `\p{Script=Cypro_Minoan}`
18+
- `\p{Script=Old_Uyghur}`
19+
- `\p{Script=Ougr}`
20+
- `\p{Script=Tangsa}`
21+
- `\p{Script=Tnsa}`
22+
- `\p{Script=Toto}`
23+
- `\p{Script=Vith}`
24+
- `\p{Script=Vithkuqi}`
25+
26+
## 💡 Examples
27+
28+
⛔ Examples of **incorrect** code for this rule:
29+
30+
<eslint-playground type="bad">
31+
32+
```js
33+
/*eslint es-x/no-regexp-unicode-property-escapes-2022: error */
34+
const r1 = /\p{Script=Cpmn}/u
35+
const r2 = /\p{Script=Cypro_Minoan}/u
36+
```
37+
38+
</eslint-playground>
39+
40+
## 📚 References
41+
42+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-es-x/blob/master/lib/rules/no-regexp-unicode-property-escapes-2022.js)
43+
- [Test source](https://github.com/ota-meshi/eslint-plugin-es-x/blob/master/tests/lib/rules/no-regexp-unicode-property-escapes-2022.js)

lib/configs/no-new-in-es2020.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module.exports = {
1515
"es-x/no-nullish-coalescing-operators": "error",
1616
"es-x/no-optional-chaining": "error",
1717
"es-x/no-promise-all-settled": "error",
18+
"es-x/no-regexp-unicode-property-escapes-2020": "error",
1819
"es-x/no-string-prototype-matchall": "error",
1920
},
2021
}

lib/configs/no-new-in-es2021.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module.exports = {
1010
"es-x/no-logical-assignment-operators": "error",
1111
"es-x/no-numeric-separators": "error",
1212
"es-x/no-promise-any": "error",
13+
"es-x/no-regexp-unicode-property-escapes-2021": "error",
1314
"es-x/no-string-prototype-replaceall": "error",
1415
"es-x/no-weakrefs": "error",
1516
},

lib/configs/no-new-in-es2022.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module.exports = {
1515
"es-x/no-object-hasown": "error",
1616
"es-x/no-private-in": "error",
1717
"es-x/no-regexp-d-flag": "error",
18+
"es-x/no-regexp-unicode-property-escapes-2022": "error",
1819
"es-x/no-top-level-await": "error",
1920
},
2021
}

lib/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ module.exports = {
189189
"no-regexp-u-flag": require("./rules/no-regexp-u-flag"),
190190
"no-regexp-unicode-property-escapes": require("./rules/no-regexp-unicode-property-escapes"),
191191
"no-regexp-unicode-property-escapes-2019": require("./rules/no-regexp-unicode-property-escapes-2019"),
192+
"no-regexp-unicode-property-escapes-2020": require("./rules/no-regexp-unicode-property-escapes-2020"),
193+
"no-regexp-unicode-property-escapes-2021": require("./rules/no-regexp-unicode-property-escapes-2021"),
194+
"no-regexp-unicode-property-escapes-2022": require("./rules/no-regexp-unicode-property-escapes-2022"),
192195
"no-regexp-y-flag": require("./rules/no-regexp-y-flag"),
193196
"no-rest-parameters": require("./rules/no-rest-parameters"),
194197
"no-rest-spread-properties": require("./rules/no-rest-spread-properties"),

lib/rules/no-regexp-lookbehind-assertions.js

+16-48
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,7 @@
44
*/
55
"use strict"
66

7-
const { RegExpValidator } = require("@eslint-community/regexpp")
8-
const { getRegExpCalls } = require("../utils")
9-
10-
/**
11-
* Verify a given regular expression.
12-
* @param {RuleContext} context The rule context to report.
13-
* @param {Node} node The AST node to report.
14-
* @param {string} pattern The pattern part of a RegExp.
15-
* @param {string} flags The flags part of a RegExp.
16-
* @returns {void}
17-
*/
18-
function verify(context, node, pattern, flags) {
19-
try {
20-
let found = false
21-
22-
new RegExpValidator({
23-
onLookaroundAssertionEnter(_start, kind) {
24-
if (kind === "lookbehind") {
25-
found = true
26-
}
27-
},
28-
}).validatePattern(pattern, 0, pattern.length, flags.includes("u"))
29-
30-
if (found) {
31-
context.report({ node, messageId: "forbidden" })
32-
}
33-
} catch (error) {
34-
//istanbul ignore else
35-
if (error.message.startsWith("Invalid regular expression:")) {
36-
return
37-
}
38-
//istanbul ignore next
39-
throw error
40-
}
41-
}
7+
const { defineRegExpHandler } = require("../util/define-regexp-handler")
428

439
module.exports = {
4410
meta: {
@@ -56,18 +22,20 @@ module.exports = {
5622
type: "problem",
5723
},
5824
create(context) {
59-
return {
60-
"Literal[regex]"(node) {
61-
const { pattern, flags } = node.regex
62-
verify(context, node, pattern || "", flags || "")
63-
},
64-
65-
"Program:exit"() {
66-
const scope = context.getScope()
67-
for (const { node, pattern, flags } of getRegExpCalls(scope)) {
68-
verify(context, node, pattern || "", flags || "")
69-
}
70-
},
71-
}
25+
return defineRegExpHandler(context, (node) => {
26+
let found = false
27+
return {
28+
onLookaroundAssertionEnter(_start, kind) {
29+
if (kind === "lookbehind") {
30+
found = true
31+
}
32+
},
33+
onExit() {
34+
if (found) {
35+
context.report({ node, messageId: "forbidden" })
36+
}
37+
},
38+
}
39+
})
7240
},
7341
}

lib/rules/no-regexp-named-capture-groups.js

+21-53
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,7 @@
44
*/
55
"use strict"
66

7-
const { RegExpValidator } = require("@eslint-community/regexpp")
8-
const { getRegExpCalls } = require("../utils")
9-
10-
/**
11-
* Verify a given regular expression.
12-
* @param {RuleContext} context The rule context to report.
13-
* @param {Node} node The AST node to report.
14-
* @param {string} pattern The pattern part of a RegExp.
15-
* @param {string} flags The flags part of a RegExp.
16-
* @returns {void}
17-
*/
18-
function verify(context, node, pattern, flags) {
19-
try {
20-
let found = false
21-
22-
new RegExpValidator({
23-
onCapturingGroupEnter(_start, name) {
24-
if (name) {
25-
found = true
26-
}
27-
},
28-
onBackreference(_start, _end, ref) {
29-
if (typeof ref === "string") {
30-
found = true
31-
}
32-
},
33-
}).validatePattern(pattern, 0, pattern.length, flags.includes("u"))
34-
35-
if (found) {
36-
context.report({ node, messageId: "forbidden" })
37-
}
38-
} catch (error) {
39-
//istanbul ignore else
40-
if (error.message.startsWith("Invalid regular expression:")) {
41-
return
42-
}
43-
//istanbul ignore next
44-
throw error
45-
}
46-
}
7+
const { defineRegExpHandler } = require("../util/define-regexp-handler")
478

489
module.exports = {
4910
meta: {
@@ -61,18 +22,25 @@ module.exports = {
6122
type: "problem",
6223
},
6324
create(context) {
64-
return {
65-
"Literal[regex]"(node) {
66-
const { pattern, flags } = node.regex
67-
verify(context, node, pattern || "", flags || "")
68-
},
69-
70-
"Program:exit"() {
71-
const scope = context.getScope()
72-
for (const { node, pattern, flags } of getRegExpCalls(scope)) {
73-
verify(context, node, pattern || "", flags || "")
74-
}
75-
},
76-
}
25+
return defineRegExpHandler(context, (node) => {
26+
let found = false
27+
return {
28+
onCapturingGroupEnter(_start, name) {
29+
if (name) {
30+
found = true
31+
}
32+
},
33+
onBackreference(_start, _end, ref) {
34+
if (typeof ref === "string") {
35+
found = true
36+
}
37+
},
38+
onExit() {
39+
if (found) {
40+
context.report({ node, messageId: "forbidden" })
41+
}
42+
},
43+
}
44+
})
7745
},
7846
}

0 commit comments

Comments
 (0)