Skip to content

Commit a3bda3e

Browse files
Updated no-dupe-disjunctions (#179)
* WIP * Increased DFA node limit * WIP * Better error messages * Fixed partial subset relation * Improved partial subset relation * Updated tests * Re-enable AST approach * Simplified how partials are detected * Updated docs * Made ReportOption enum const * Re-added `disallowNeverMatch` * Re-enabled AST approach
1 parent dbe5556 commit a3bda3e

File tree

4 files changed

+1001
-304
lines changed

4 files changed

+1001
-304
lines changed

docs/rules/no-dupe-disjunctions.md

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ var foo = /(a|a)/
2929
var foo = /(?:a|a)/
3030
var foo = /abc|abc/
3131
var foo = /[ab]|[ba]/
32+
var foo = /a|abc/
33+
var foo = /.|abc/
34+
var foo = /.|a|b|c/
3235
```
3336

3437
</eslint-code-block>
@@ -40,38 +43,55 @@ var foo = /[ab]|[ba]/
4043
"regexp/no-dupe-disjunctions": [
4144
"error",
4245
{
43-
"disallowNeverMatch": false
46+
"report": "trivial",
47+
"alwaysReportExponentialBacktracking": true
4448
}
4549
]
4650
}
4751
```
4852

49-
- `disallowNeverMatch` ... If `true`, it reports a pattern that does not match as a result of a partial duplication of the previous pattern.
53+
### `report`
5054

51-
### `"disallowNeverMatch": true`
55+
This option control what types of duplications will be reported. The possible values are:
5256

53-
<eslint-code-block>
57+
- `report: "trivial"` (_default_)
5458

55-
```js
56-
/* eslint regexp/no-dupe-disjunctions: ["error", { "disallowNeverMatch": true }] */
59+
With this option, only trivial cases will be reported. This means that the reported alternative can be removed without affecting the pattern.
5760

58-
/* ✓ GOOD */
59-
var foo = /a|b/
60-
var foo = /(a|b)/
61-
var foo = /(?:a|b)/
61+
Trivial cases include duplicates (e.g. `a|a`) and subsets (e.g. `\w|a`).
6262

63-
/* ✗ BAD */
63+
- `report: "interesting"`
6464

65-
// Duplication
66-
var foo = /a|a/
65+
All trivial cases and superset cases will be reported.
6766

68-
// A string that matches the pattern on the right also matches the pattern on the left, so it doesn't make sense to process the pattern on the right.
69-
var foo = /a|abc/
70-
var foo = /.|abc/
71-
var foo = /.|a|b|c/
72-
```
67+
In superset cases, an alternative _might_ be removable. Whether a reported alternative is removable cannot trivially be decided and depends on the pattern.
7368

74-
</eslint-code-block>
69+
E.g. `Foo|\w+` is a superset case because `\w+` is a superset of `Foo`. In the regex `/\b(?:Foo|\w+)\b/`, the `Foo` alternative can be removed. However in the regex `/Foo|\w+/`, the `Foo` alternative cannot be removed without affecting the pattern.
70+
71+
Whether a reported alternative is removable has to be decided by the developer.
72+
73+
- `report: "all"`
74+
75+
All cases of duplication and partial duplication (overlap) will be reported.
76+
77+
Partial duplication (overlap) is typically not harmful and difficult to remove. E.g. the harmless overlap of `a.*|.*b` is `a.*b`.
78+
79+
Partial duplication is only harmful if it occurs within a quantifier because then it can cause exponential backtracking. By default, this rule will try to report all cases of potential exponential backtracking.
80+
81+
However, the rule might not be able to detect that overlap happens within a quantifier if the regex was constructed at runtime. Example:
82+
83+
```javascript
84+
const partial = /a.*|.*b/;
85+
const pattern = new RegExp("(?:" + partial.source + ")+\nfoo");
86+
```
87+
88+
If your codebase contained many such partial regexes, then reporting all cases might yield cases that could not be identified as causing exponential backtracking.
89+
90+
### `alwaysReportExponentialBacktracking: boolean`
91+
92+
If set to `true`, then this rule will always report partial duplications that can cause exponential backtracking. This option is set to `true` by default.
93+
94+
Only set this option to `false` if you have some other mean to reliably detect exponential backtracking.
7595

7696
## :rocket: Version
7797

0 commit comments

Comments
 (0)