Skip to content

Commit 76f3ad8

Browse files
authored
Add regexp/prefer-regexp-exec and regexp/prefer-regexp-test rules (#32)
* Add `regexp/prefer-regexp-exec` rule * downgrade ts-node on node8 test * update * update * update * Use cache * Supports JSDoc * Update and add testcases * Add testcases * Supports Map and Set * Update * Update * update * fix and update * Update * update * Update * Support iterator * update * Add testcases * update * update * Add prefer-regexp-test rule * Update demo
1 parent cad7d1c commit 76f3ad8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+5894
-2
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module.exports = {
2222
"no-warning-comments": "warn",
2323
"no-lonely-if": "off",
2424
"@typescript-eslint/no-non-null-assertion": "off",
25+
"@typescript-eslint/no-duplicate-imports": "error",
2526
},
2627
overrides: [
2728
{

.github/workflows/NodeCI.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
node-version: 8.10.x
4545
- name: Install Target Packages
4646
run: |+
47-
npm i -D [email protected] mocha@7
47+
npm i -D [email protected] mocha@7 @typescript-eslint/parser@3
4848
npx rimraf node_modules
4949
npm install
5050
- name: Test

.nycrc.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"all": true,
3+
"include": [
4+
"lib/**/*.ts"
5+
],
6+
"exclude": [
7+
"tests/**/*.ts"
8+
]
9+
}

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ The rules with the following star :star: are included in the `plugin:regexp/reco
9696
| [regexp/prefer-plus-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-plus-quantifier.html) | enforce using `+` quantifier | :star::wrench: |
9797
| [regexp/prefer-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-quantifier.html) | enforce using quantifier | :wrench: |
9898
| [regexp/prefer-question-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-question-quantifier.html) | enforce using `?` quantifier | :star::wrench: |
99+
| [regexp/prefer-regexp-exec](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-regexp-exec.html) | enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided | |
100+
| [regexp/prefer-regexp-test](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-regexp-test.html) | enforce that `RegExp#test` is used instead of `String#match` and `RegExp#exec` | :wrench: |
99101
| [regexp/prefer-star-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-star-quantifier.html) | enforce using `*` quantifier | :star::wrench: |
100102
| [regexp/prefer-t](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-t.html) | enforce using `\t` | :star::wrench: |
101103
| [regexp/prefer-w](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-w.html) | enforce using `\w` | :star::wrench: |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
/eslint[-plugin-regexp]/u
2+
3+
const re = /[a-zA-Z_0-9][A-Z_\da-z]*\e{1,}/

docs/.vuepress/components/rules/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ for (const k of Object.keys(plugin.rules)) {
4545
category: rule.meta.docs.category,
4646
ruleId: rule.meta.docs.ruleId,
4747
url: rule.meta.docs.url,
48-
initChecked: CATEGORY_INDEX[rule.meta.docs.category] <= 3,
48+
initChecked: true, // CATEGORY_INDEX[rule.meta.docs.category] <= 3,
4949
})
5050
}
5151
for (const k of Object.keys(coreRules)) {

docs/rules/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ The rules with the following star :star: are included in the `plugin:regexp/reco
2828
| [regexp/prefer-plus-quantifier](./prefer-plus-quantifier.md) | enforce using `+` quantifier | :star::wrench: |
2929
| [regexp/prefer-quantifier](./prefer-quantifier.md) | enforce using quantifier | :wrench: |
3030
| [regexp/prefer-question-quantifier](./prefer-question-quantifier.md) | enforce using `?` quantifier | :star::wrench: |
31+
| [regexp/prefer-regexp-exec](./prefer-regexp-exec.md) | enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided | |
32+
| [regexp/prefer-regexp-test](./prefer-regexp-test.md) | enforce that `RegExp#test` is used instead of `String#match` and `RegExp#exec` | :wrench: |
3133
| [regexp/prefer-star-quantifier](./prefer-star-quantifier.md) | enforce using `*` quantifier | :star::wrench: |
3234
| [regexp/prefer-t](./prefer-t.md) | enforce using `\t` | :star::wrench: |
3335
| [regexp/prefer-w](./prefer-w.md) | enforce using `\w` | :star::wrench: |

docs/rules/prefer-regexp-exec.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
pageClass: "rule-details"
3+
sidebarDepth: 0
4+
title: "regexp/prefer-regexp-exec"
5+
description: "enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided"
6+
---
7+
---
8+
pageClass: "rule-details"
9+
sidebarDepth: 0
10+
title: "regexp/prefer-regexp-exec"
11+
description: "enforce that `RegExp# regexp/prefer-regexp-exec
12+
13+
> enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided
14+
15+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
16+
17+
# regexp/prefer-regexp-exec
18+
19+
> enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided
20+
21+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
22+
23+
`RegExp#exec` is faster than `String#match` and both work the same when not using the `/g` flag.
24+
25+
## :book: Rule Details
26+
27+
This rule is aimed at enforcing the more performant way of applying regular expressions on strings.
28+
29+
This rule inspired by [@typescript-eslint/prefer-regexp-exec rule](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md).
30+
31+
<eslint-code-block>
32+
33+
```js
34+
/* eslint regexp/prefer-regexp-exec: "error" */
35+
36+
/* ✓ GOOD */
37+
/thing/.exec('something');
38+
39+
'some things are just things'.match(/thing/g);
40+
41+
const text = 'something';
42+
const search = /thing/;
43+
search.exec(text);
44+
45+
/* ✗ BAD */
46+
'something'.match(/thing/);
47+
48+
'some things are just things'.match(/thing/);
49+
50+
text.match(search);
51+
```
52+
53+
</eslint-code-block>
54+
55+
## :wrench: Options
56+
57+
Nothing.
58+
59+
## :books: Further reading
60+
61+
- [@typescript-eslint/prefer-regexp-exec](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md)
62+
63+
## :mag: Implementation
64+
65+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/lib/rules/prefer-regexp-exec.ts)
66+
- [Test source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/tests/lib/rules/prefer-regexp-exec.ts)

docs/rules/prefer-regexp-test.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
pageClass: "rule-details"
3+
sidebarDepth: 0
4+
title: "regexp/prefer-regexp-test"
5+
description: "enforce that `RegExp#test` is used instead of `String#match` and `RegExp#exec`"
6+
---
7+
# regexp/prefer-regexp-test
8+
9+
> enforce that `RegExp#test` is used instead of `String#match` and `RegExp#exec`
10+
11+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
12+
- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
13+
14+
## :book: Rule Details
15+
16+
This rule is aimed to use `RegExp#test` to check if a pattern matches a string.
17+
18+
This rule inspired by [unicorn/prefer-regexp-test rule](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-regexp-test.md).
19+
20+
<eslint-code-block fix>
21+
22+
```js
23+
/* eslint regexp/prefer-regexp-test: "error" */
24+
25+
const text = 'something';
26+
const pattern = /thing/;
27+
28+
/* ✓ GOOD */
29+
if (pattern.test(text)) {}
30+
31+
/* ✗ BAD */
32+
if (pattern.exec(text)) {}
33+
if (text.match(pattern)) {}
34+
```
35+
36+
</eslint-code-block>
37+
38+
## :wrench: Options
39+
40+
Nothing.
41+
42+
## :books: Further reading
43+
44+
- [unicorn/prefer-regexp-test](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-regexp-test.md)
45+
46+
## :mag: Implementation
47+
48+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/lib/rules/prefer-regexp-test.ts)
49+
- [Test source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/tests/lib/rules/prefer-regexp-test.ts)

lib/rules/prefer-regexp-exec.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import type { CallExpression } from "estree"
2+
import { createRule } from "../utils"
3+
import { createTypeTracker } from "../utils/type-tracker"
4+
import { getStaticValue } from "eslint-utils"
5+
6+
// Inspired by https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md
7+
export default createRule("prefer-regexp-exec", {
8+
meta: {
9+
docs: {
10+
description:
11+
"enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided",
12+
recommended: false,
13+
},
14+
schema: [],
15+
messages: {
16+
disallow: "Use the `RegExp#exec()` method instead.",
17+
},
18+
type: "suggestion", // "problem",
19+
},
20+
create(context) {
21+
const typeTracer = createTypeTracker(context)
22+
23+
return {
24+
CallExpression(node: CallExpression) {
25+
if (node.arguments.length !== 1) {
26+
return
27+
}
28+
if (
29+
node.callee.type !== "MemberExpression" ||
30+
node.callee.computed ||
31+
node.callee.property.type !== "Identifier" ||
32+
node.callee.property.name !== "match" ||
33+
node.callee.object.type === "Super"
34+
) {
35+
return
36+
}
37+
const arg = node.arguments[0]
38+
const evaluated = getStaticValue(arg, context.getScope())
39+
if (
40+
evaluated &&
41+
evaluated.value instanceof RegExp &&
42+
evaluated.value.flags.includes("g")
43+
) {
44+
return
45+
}
46+
if (!typeTracer.isString(node.callee.object)) {
47+
return
48+
}
49+
context.report({
50+
node,
51+
messageId: "disallow",
52+
})
53+
},
54+
}
55+
},
56+
})

0 commit comments

Comments
 (0)