You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|[regexp/no-unused-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-unused-capturing-group.html)| disallow unused capturing group ||
103
-
|[regexp/no-useless-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-backreference.html)| disallow useless backreferences in regular expressions ||
103
+
|[regexp/no-useless-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-backreference.html)| disallow useless backreferences in regular expressions |:star:|
104
104
|[regexp/no-useless-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-character-class.html)| disallow character class with one character |:wrench:|
105
105
|[regexp/no-useless-dollar-replacements](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-dollar-replacements.html)| disallow useless `$` replacements in replacement string ||
106
106
|[regexp/no-useless-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-escape.html)| disallow unnecessary escape characters in RegExp ||
Copy file name to clipboardExpand all lines: docs/rules/no-useless-backreference.md
+69-4Lines changed: 69 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,15 +9,80 @@ since: "v0.1.0"
9
9
10
10
> disallow useless backreferences in regular expressions
11
11
12
+
-:gear: This rule is included in `"plugin:regexp/recommended"`.
13
+
12
14
## :book: Rule Details
13
15
14
-
This rule is a copy of the ESLint core [no-useless-backreference] rule.
15
-
The [no-useless-backreference] rule was added in ESLint 7.x, but this plugin supports ESLint 6.x.
16
-
Copied to this plugin to allow the same [no-useless-backreference] rules to be used in ESLint 6.x.
16
+
Backreferences that will always trivially accept serve no function and can be removed.
17
+
18
+
This rule is a based on the ESLint core [no-useless-backreference] rule. It reports all the ESLint core rule reports and some more.
19
+
20
+
### Causes
21
+
22
+
Backreferences can be useless for multiple reasons.
23
+
24
+
#### Empty capturing groups
25
+
26
+
The is the easiest reason. The references capturing group does not consume any characters (e.g. `/(\b)a\1/`). Since the capturing group can only capture the empty string, the backreference is guaranteed to accept any input.
27
+
28
+
#### Nested backreferences
29
+
30
+
If a backreference is inside the group it references (e.g. `/(a\1)/`), then it is guaranteed to trivially accept.
31
+
32
+
This is because the regex engine only sets the text of a capturing group **after** the group has been matched. Since the regex engine is still in the process of matching the group, its capture text is undefined.
33
+
34
+
#### Different alternatives
35
+
36
+
If a backreference and its referenced capturing group are in different alternatives (e.g. `/(a)|\1/`), then the backreference will always trivially accept because the captured text of the referenced group is undefined.
37
+
38
+
#### Forward references and backward references
39
+
40
+
Backreferences are supposed to be matched **after** their referenced capturing group. Since regular expressions are matched from left to right, backreferences usually appear to the right of to their referenced capturing groups (e.g. `/(a)\1/`). However, backreferences can also be placed before (to the left of) their referenced capturing group (e.g. `/\1(a)/`). These backreferences are to trivially accept because the captured text of their referenced groups is undefined. We call these backreferences _forward references_.
41
+
42
+
Inside **lookbehind assertions**, regular expressions are matched from right to left and not from left to right. This means that only backreferences now have to appear to the left of their respective capturing group to be matched after them (e.g. `/(?<=\1(a))/`). Backreferences placed to before (to the right of) their referenced capturing group inside lookbehinds are guaranteed to trivially accept. We call these backreferences _backward references_.
43
+
44
+
#### Negated lookaround assertions
45
+
46
+
If the referenced capturing group of a backreference is inside a negated lookaround assertion the backreference is also part of, then the backreference will be guaranteed to trivially accept.
47
+
48
+
To understand why this is the case, let's look at the example `/(?!(a))\w\1/y`.
49
+
50
+
1. Let's assume the input string is `ab`. <br>
51
+
Since `(a)` accepts the character `a`, `(?!(a))` will reject. So the input is reject before the backreference `\1` can be reached.
52
+
53
+
The result of `/(?!(a))\w\1/y.exec("ab")` is `null`.
54
+
2. Let's assume the input string is `bc`. <br>
55
+
Since `(a)` rejects the character `b`, its captured text will be undefined and `(?!(a))` will accept. Then `\w` will accept and consume the character `b`. Since the captured text of `(a)` is undefined, the backreference `\1` will trivially accept without consuming characters.
56
+
57
+
The result of `/(?!(a))\w\1/y.exec("bc")` is `[ 'b', undefined, index: 0, input: 'bc' ]`.
58
+
59
+
Note that this is only a problem if the backreference is not part of the negated lookaround assertion. I.e. `/(?!(a)\1)\w/` is okay.
0 commit comments