Skip to content

Commit 4960281

Browse files
Add regexp/prefer-named-capture-group rule (#330)
* Add `regexp/prefer-named-capture-group` rule * Improved grammar
1 parent f221d81 commit 4960281

File tree

6 files changed

+126
-0
lines changed

6 files changed

+126
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ The rules with the following star :star: are included in the `plugin:regexp/reco
170170
| [regexp/prefer-d](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-d.html) | enforce using `\d` | :star::wrench: |
171171
| [regexp/prefer-lookaround](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-lookaround.html) | prefer lookarounds over capturing group that do not replace | :wrench: |
172172
| [regexp/prefer-named-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-backreference.html) | enforce using named backreferences | :wrench: |
173+
| [regexp/prefer-named-capture-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-capture-group.html) | enforce using named capture groups | |
173174
| [regexp/prefer-plus-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-plus-quantifier.html) | enforce using `+` quantifier | :star::wrench: |
174175
| [regexp/prefer-question-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-question-quantifier.html) | enforce using `?` quantifier | :star::wrench: |
175176
| [regexp/prefer-star-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-star-quantifier.html) | enforce using `*` quantifier | :star::wrench: |

docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ The rules with the following star :star: are included in the `plugin:regexp/reco
7979
| [regexp/prefer-d](./prefer-d.md) | enforce using `\d` | :star::wrench: |
8080
| [regexp/prefer-lookaround](./prefer-lookaround.md) | prefer lookarounds over capturing group that do not replace | :wrench: |
8181
| [regexp/prefer-named-backreference](./prefer-named-backreference.md) | enforce using named backreferences | :wrench: |
82+
| [regexp/prefer-named-capture-group](./prefer-named-capture-group.md) | enforce using named capture groups | |
8283
| [regexp/prefer-plus-quantifier](./prefer-plus-quantifier.md) | enforce using `+` quantifier | :star::wrench: |
8384
| [regexp/prefer-question-quantifier](./prefer-question-quantifier.md) | enforce using `?` quantifier | :star::wrench: |
8485
| [regexp/prefer-star-quantifier](./prefer-star-quantifier.md) | enforce using `*` quantifier | :star::wrench: |
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
pageClass: "rule-details"
3+
sidebarDepth: 0
4+
title: "regexp/prefer-named-capture-group"
5+
description: "enforce using named capture groups"
6+
---
7+
# regexp/prefer-named-capture-group
8+
9+
> enforce using named capture groups
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+
13+
## :book: Rule Details
14+
15+
This rule reports capturing groups without a name.
16+
17+
This rule is inspired by the [prefer-named-capture-group] rule. The positions of reports are improved over the core rule and arguments of `new RegExp()` are also checked.
18+
19+
<eslint-code-block>
20+
21+
```js
22+
/* eslint regexp/prefer-named-capture-group: "error" */
23+
24+
/* ✓ GOOD */
25+
var foo = /(?<foo>ba+r)/;
26+
var foo = /\b(?:foo)+\b/;
27+
28+
/* ✗ BAD */
29+
var foo = /\b(foo)+\b/;
30+
```
31+
32+
</eslint-code-block>
33+
34+
## :wrench: Options
35+
36+
Nothing.
37+
38+
## :books: Further reading
39+
40+
- [prefer-named-capture-group]
41+
42+
[prefer-named-capture-group]: https://eslint.org/docs/rules/prefer-named-capture-group
43+
44+
## :mag: Implementation
45+
46+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/lib/rules/prefer-named-capture-group.ts)
47+
- [Test source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/tests/lib/rules/prefer-named-capture-group.ts)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import type { RegExpVisitor } from "regexpp/visitor"
2+
import type { RegExpContext } from "../utils"
3+
import { createRule, defineRegexpVisitor } from "../utils"
4+
import { mention } from "../utils/mention"
5+
6+
export default createRule("prefer-named-capture-group", {
7+
meta: {
8+
docs: {
9+
description: "enforce using named capture groups",
10+
category: "Stylistic Issues",
11+
recommended: false,
12+
},
13+
schema: [],
14+
messages: {
15+
required:
16+
"Capture group {{group}} should be converted to a named or non-capturing group.",
17+
},
18+
type: "suggestion",
19+
},
20+
create(context) {
21+
/**
22+
* Create visitor
23+
*/
24+
function createVisitor(
25+
regexpContext: RegExpContext,
26+
): RegExpVisitor.Handlers {
27+
const { node, getRegexpLocation } = regexpContext
28+
29+
return {
30+
onCapturingGroupEnter(cgNode) {
31+
if (cgNode.name === null) {
32+
context.report({
33+
node,
34+
loc: getRegexpLocation(cgNode),
35+
messageId: "required",
36+
data: {
37+
group: mention(cgNode),
38+
},
39+
})
40+
}
41+
},
42+
}
43+
}
44+
45+
return defineRegexpVisitor(context, {
46+
createVisitor,
47+
})
48+
},
49+
})

lib/utils/rules.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import preferD from "../rules/prefer-d"
5252
import preferEscapeReplacementDollarChar from "../rules/prefer-escape-replacement-dollar-char"
5353
import preferLookaround from "../rules/prefer-lookaround"
5454
import preferNamedBackreference from "../rules/prefer-named-backreference"
55+
import preferNamedCaptureGroup from "../rules/prefer-named-capture-group"
5556
import preferPlusQuantifier from "../rules/prefer-plus-quantifier"
5657
import preferPredefinedAssertion from "../rules/prefer-predefined-assertion"
5758
import preferQuantifier from "../rules/prefer-quantifier"
@@ -123,6 +124,7 @@ export const rules = [
123124
preferEscapeReplacementDollarChar,
124125
preferLookaround,
125126
preferNamedBackreference,
127+
preferNamedCaptureGroup,
126128
preferPlusQuantifier,
127129
preferPredefinedAssertion,
128130
preferQuantifier,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { RuleTester } from "eslint"
2+
import rule from "../../../lib/rules/prefer-named-capture-group"
3+
4+
const tester = new RuleTester({
5+
parserOptions: {
6+
ecmaVersion: 2020,
7+
sourceType: "module",
8+
},
9+
})
10+
11+
tester.run("prefer-named-capture-group", rule as any, {
12+
valid: [
13+
String.raw`/foo/`,
14+
String.raw`/b(?:a(?:r))/`,
15+
String.raw`/(?<foo>bar)/`,
16+
String.raw`/(?=a)(?<=b)/`,
17+
],
18+
invalid: [
19+
{
20+
code: String.raw`/(foo)/`,
21+
errors: [
22+
"Capture group '(foo)' should be converted to a named or non-capturing group.",
23+
],
24+
},
25+
],
26+
})

0 commit comments

Comments
 (0)