Skip to content

Commit 775bbe4

Browse files
authored
Add regexp/no-empty-capturing-group rule that same regexp/no-assertion-capturing-group rule (#221)
1 parent 96f922c commit 775bbe4

9 files changed

+174
-105
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,10 @@ The rules with the following star :star: are included in the `plugin:regexp/reco
9999

100100
| Rule ID | Description | |
101101
|:--------|:------------|:---|
102-
| [regexp/no-assertion-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-assertion-capturing-group.html) | disallow capturing group that captures assertions. | :star: |
102+
| [regexp/no-assertion-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-assertion-capturing-group.html) | disallow capturing group that captures empty. | :star: |
103103
| [regexp/no-dupe-disjunctions](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-dupe-disjunctions.html) | disallow duplicate disjunctions | |
104104
| [regexp/no-empty-alternative](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-alternative.html) | disallow alternatives without elements | |
105+
| [regexp/no-empty-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-capturing-group.html) | disallow capturing group that captures empty. | |
105106
| [regexp/no-empty-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-group.html) | disallow empty group | :star: |
106107
| [regexp/no-empty-lookarounds-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-lookarounds-assertion.html) | disallow empty lookahead assertion or empty lookbehind assertion | :star: |
107108
| [regexp/no-escape-backspace](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-escape-backspace.html) | disallow escape backspace (`[\b]`) | :star: |

docs/rules/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ The rules with the following star :star: are included in the `plugin:regexp/reco
1313

1414
| Rule ID | Description | |
1515
|:--------|:------------|:---|
16-
| [regexp/no-assertion-capturing-group](./no-assertion-capturing-group.md) | disallow capturing group that captures assertions. | :star: |
16+
| [regexp/no-assertion-capturing-group](./no-assertion-capturing-group.md) | disallow capturing group that captures empty. | :star: |
1717
| [regexp/no-dupe-disjunctions](./no-dupe-disjunctions.md) | disallow duplicate disjunctions | |
1818
| [regexp/no-empty-alternative](./no-empty-alternative.md) | disallow alternatives without elements | |
19+
| [regexp/no-empty-capturing-group](./no-empty-capturing-group.md) | disallow capturing group that captures empty. | |
1920
| [regexp/no-empty-group](./no-empty-group.md) | disallow empty group | :star: |
2021
| [regexp/no-empty-lookarounds-assertion](./no-empty-lookarounds-assertion.md) | disallow empty lookahead assertion or empty lookbehind assertion | :star: |
2122
| [regexp/no-escape-backspace](./no-escape-backspace.md) | disallow escape backspace (`[\b]`) | :star: |

docs/rules/no-assertion-capturing-group.md

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,21 @@
22
pageClass: "rule-details"
33
sidebarDepth: 0
44
title: "regexp/no-assertion-capturing-group"
5-
description: "disallow capturing group that captures assertions."
5+
description: "disallow capturing group that captures empty."
66
since: "v0.1.0"
77
---
88
# regexp/no-assertion-capturing-group
99

10-
> disallow capturing group that captures assertions.
10+
> disallow capturing group that captures empty.
1111
1212
- :gear: This rule is included in `"plugin:regexp/recommended"`.
1313

1414
## :book: Rule Details
1515

16-
This rule reports capturing group that captures assertions.
16+
This rule is the same as the [regexp/no-empty-capturing-group] rule. Use [regexp/no-empty-capturing-group] instead.
17+
Replaced by [regexp/no-empty-capturing-group] in v1.0.0, this rule will be marked as **deprecated**.
1718

18-
<eslint-code-block>
19-
20-
```js
21-
/* eslint regexp/no-assertion-capturing-group: "error" */
22-
23-
/* ✓ GOOD */
24-
var foo = /(a)/;
25-
var foo = /a(?:\b)/;
26-
var foo = /a(?:$)/;
27-
var foo = /(?:^)a/;
28-
var foo = /(?:^|b)a/;
29-
30-
/* ✗ BAD */
31-
var foo = /a(\b)/;
32-
var foo = /a($)/;
33-
var foo = /(^)a/;
34-
```
35-
36-
</eslint-code-block>
37-
38-
## :wrench: Options
39-
40-
Nothing.
19+
[regexp/no-empty-capturing-group]: no-empty-capturing-group.md
4120

4221
## :rocket: Version
4322

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
pageClass: "rule-details"
3+
sidebarDepth: 0
4+
title: "regexp/no-empty-capturing-group"
5+
description: "disallow capturing group that captures empty."
6+
---
7+
# regexp/no-empty-capturing-group
8+
9+
> disallow capturing group that captures empty.
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 group that captures assertions.
16+
17+
<eslint-code-block>
18+
19+
```js
20+
/* eslint regexp/no-empty-capturing-group: "error" */
21+
22+
/* ✓ GOOD */
23+
var foo = /(a)/;
24+
var foo = /a(?:\b)/;
25+
var foo = /a(?:$)/;
26+
var foo = /(?:^)a/;
27+
var foo = /(?:^|b)a/;
28+
29+
/* ✗ BAD */
30+
var foo = /a(\b)/;
31+
var foo = /a($)/;
32+
var foo = /(^)a/;
33+
```
34+
35+
</eslint-code-block>
36+
37+
## :wrench: Options
38+
39+
Nothing.
40+
41+
## :mag: Implementation
42+
43+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/lib/rules/no-empty-capturing-group.ts)
44+
- [Test source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/tests/lib/rules/no-empty-capturing-group.ts)
Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,21 @@
1-
import { isZeroLength } from "regexp-ast-analysis"
2-
import type { RegExpVisitor } from "regexpp/visitor"
3-
import type { RegExpContext } from "../utils"
4-
import { createRule, defineRegexpVisitor } from "../utils"
1+
import { createRule } from "../utils"
2+
3+
import noEmptyCapturingGroup from "./no-empty-capturing-group"
54

65
export default createRule("no-assertion-capturing-group", {
76
meta: {
7+
...noEmptyCapturingGroup.meta,
88
docs: {
9-
description: "disallow capturing group that captures assertions.",
10-
category: "Possible Errors",
9+
...noEmptyCapturingGroup.meta.docs,
10+
// TODO Switch to recommended in the major version.
11+
// recommended: false,
1112
recommended: true,
13+
replacedBy: ["no-empty-capturing-group"],
1214
},
13-
schema: [],
14-
messages: {
15-
unexpected: "Unexpected capture assertions.",
16-
},
17-
type: "suggestion",
15+
// TODO Switch to deprecated in the major version.
16+
// deprecated: true,
1817
},
1918
create(context) {
20-
/**
21-
* Create visitor
22-
*/
23-
function createVisitor({
24-
node,
25-
getRegexpLocation,
26-
}: RegExpContext): RegExpVisitor.Handlers {
27-
return {
28-
onCapturingGroupEnter(cgNode) {
29-
if (isZeroLength(cgNode)) {
30-
context.report({
31-
node,
32-
loc: getRegexpLocation(cgNode),
33-
messageId: "unexpected",
34-
})
35-
}
36-
},
37-
}
38-
}
39-
40-
return defineRegexpVisitor(context, {
41-
createVisitor,
42-
})
19+
return noEmptyCapturingGroup.create(context)
4320
},
4421
})

lib/rules/no-empty-capturing-group.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { isZeroLength } from "regexp-ast-analysis"
2+
import type { RegExpVisitor } from "regexpp/visitor"
3+
import type { RegExpContext } from "../utils"
4+
import { createRule, defineRegexpVisitor } from "../utils"
5+
6+
export default createRule("no-empty-capturing-group", {
7+
meta: {
8+
docs: {
9+
description: "disallow capturing group that captures empty.",
10+
category: "Possible Errors",
11+
// TODO Switch to recommended in the major version.
12+
// recommended: true,
13+
recommended: false,
14+
},
15+
schema: [],
16+
messages: {
17+
unexpected: "Unexpected capture empty.",
18+
},
19+
type: "suggestion",
20+
},
21+
create(context) {
22+
/**
23+
* Create visitor
24+
*/
25+
function createVisitor({
26+
node,
27+
getRegexpLocation,
28+
}: RegExpContext): RegExpVisitor.Handlers {
29+
return {
30+
onCapturingGroupEnter(cgNode) {
31+
if (isZeroLength(cgNode)) {
32+
context.report({
33+
node,
34+
loc: getRegexpLocation(cgNode),
35+
messageId: "unexpected",
36+
})
37+
}
38+
},
39+
}
40+
}
41+
42+
return defineRegexpVisitor(context, {
43+
createVisitor,
44+
})
45+
},
46+
})

lib/utils/rules.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import noAssertionCapturingGroup from "../rules/no-assertion-capturing-group"
99
import noDupeCharactersCharacterClass from "../rules/no-dupe-characters-character-class"
1010
import noDupeDisjunctions from "../rules/no-dupe-disjunctions"
1111
import noEmptyAlternative from "../rules/no-empty-alternative"
12+
import noEmptyCapturingGroup from "../rules/no-empty-capturing-group"
1213
import noEmptyGroup from "../rules/no-empty-group"
1314
import noEmptyLookaroundsAssertion from "../rules/no-empty-lookarounds-assertion"
1415
import noEscapeBackspace from "../rules/no-escape-backspace"
@@ -70,6 +71,7 @@ export const rules = [
7071
noDupeCharactersCharacterClass,
7172
noDupeDisjunctions,
7273
noEmptyAlternative,
74+
noEmptyCapturingGroup,
7375
noEmptyGroup,
7476
noEmptyLookaroundsAssertion,
7577
noEscapeBackspace,

tests/lib/rules/no-assertion-capturing-group.ts

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,51 +9,11 @@ const tester = new RuleTester({
99
})
1010

1111
tester.run("no-assertion-capturing-group", rule as any, {
12-
valid: ["/(a)/", "/a(\\bb)/", "/a(\\b|b)/"],
12+
valid: ["/(a)/"],
1313
invalid: [
1414
{
15-
code: "/a(\\b)/",
16-
errors: [
17-
{
18-
message: "Unexpected capture assertions.",
19-
column: 3,
20-
endColumn: 7,
21-
},
22-
],
23-
},
24-
{
25-
code: "/a($)/",
26-
errors: [
27-
{
28-
message: "Unexpected capture assertions.",
29-
column: 3,
30-
endColumn: 6,
31-
},
32-
],
33-
},
34-
{
35-
code: "/(^)a/",
36-
errors: [
37-
{
38-
message: "Unexpected capture assertions.",
39-
column: 2,
40-
endColumn: 5,
41-
},
42-
],
43-
},
44-
{
45-
code: "/()a/",
46-
errors: [
47-
{
48-
message: "Unexpected capture assertions.",
49-
column: 2,
50-
endColumn: 4,
51-
},
52-
],
53-
},
54-
{
55-
code: "/(\\b\\b|(?:\\B|$))a/",
56-
errors: ["Unexpected capture assertions."],
15+
code: String.raw`/(\b)a/`,
16+
errors: ["Unexpected capture empty."],
5717
},
5818
],
5919
})
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { RuleTester } from "eslint"
2+
import rule from "../../../lib/rules/no-empty-capturing-group"
3+
4+
const tester = new RuleTester({
5+
parserOptions: {
6+
ecmaVersion: 2020,
7+
sourceType: "module",
8+
},
9+
})
10+
11+
tester.run("no-empty-capturing-group", rule as any, {
12+
valid: ["/(a)/", "/a(\\bb)/", "/a(\\b|b)/"],
13+
invalid: [
14+
{
15+
code: "/a(\\b)/",
16+
errors: [
17+
{
18+
message: "Unexpected capture empty.",
19+
column: 3,
20+
endColumn: 7,
21+
},
22+
],
23+
},
24+
{
25+
code: "/a($)/",
26+
errors: [
27+
{
28+
message: "Unexpected capture empty.",
29+
column: 3,
30+
endColumn: 6,
31+
},
32+
],
33+
},
34+
{
35+
code: "/(^)a/",
36+
errors: [
37+
{
38+
message: "Unexpected capture empty.",
39+
column: 2,
40+
endColumn: 5,
41+
},
42+
],
43+
},
44+
{
45+
code: "/()a/",
46+
errors: [
47+
{
48+
message: "Unexpected capture empty.",
49+
column: 2,
50+
endColumn: 4,
51+
},
52+
],
53+
},
54+
{
55+
code: "/(\\b\\b|(?:\\B|$))a/",
56+
errors: ["Unexpected capture empty."],
57+
},
58+
],
59+
})

0 commit comments

Comments
 (0)