Skip to content

Commit a8c9407

Browse files
Add options related to reporting partial patterns to regexp/no-dupe-disjunctions rule (#204)
Co-authored-by: RunDevelopment <[email protected]>
1 parent eb38995 commit a8c9407

File tree

11 files changed

+1296
-94
lines changed

11 files changed

+1296
-94
lines changed

docs/rules/no-dupe-disjunctions.md

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ var foo = /.|a|b|c/
4444
"error",
4545
{
4646
"report": "trivial",
47-
"alwaysReportExponentialBacktracking": true
47+
"reportExponentialBacktracking": "potential",
48+
"reportUnreachable": "certain"
4849
}
4950
]
5051
}
@@ -87,11 +88,78 @@ This option control what types of duplications will be reported. The possible va
8788

8889
If your codebase contained many such partial regexes, then reporting all cases might yield cases that could not be identified as causing exponential backtracking.
8990

90-
### `alwaysReportExponentialBacktracking: boolean`
91+
### `reportExponentialBacktracking`
9192

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+
Partial duplications (overlaps) are only reported by `report: "all"` even though they sometimes cause exponential backtracking. This option will force the other `report` modes to also report partial duplications if the partial duplications are likely to cause exponential backtracking.
9394

94-
Only set this option to `false` if you have some other mean to reliably detect exponential backtracking.
95+
- `reportExponentialBacktracking: "potential"` (_default_)
96+
97+
In this case, this rule will always report partial duplications that _might_ cause exponential backtracking.
98+
99+
If the plugin cannot prove that a partial duplication is safe (= does not cause exponential backtracking), then the partial duplication will be reported. This might cause some false positives.
100+
101+
- `reportExponentialBacktracking: "certain"`
102+
103+
In this case, this rule will report partial duplication that _can_ cause exponential backtracking.
104+
105+
If the plugin can prove that a partial duplication is unsafe (= causes exponential backtracking), then the partial duplication will be reported. This might cause some false negatives.
106+
107+
- `reportExponentialBacktracking: "none"`
108+
109+
In this case, no extra cases of partial duplication will be reported.
110+
111+
The `"potential"` and `"certain"` modes differ only in how they handle uncertainty. The rule might be unable to prove that partial duplication is safe or unsafe with 100% certainty. This typically happens around fragment regexes (regexes that are used as fragments to build more complex regexes). Because the rule might not be able to track how a regex fragment is used, it has to make assumptions:
112+
113+
- `"potential"` assumes that fragments might be used inside a (logical) star quantifier and reports all partial duplication.
114+
- `"certain"` assumes that fragments will not be used inside a (logical) star quantifier and will only report partial duplication that is certain to cause exponential backtracking.
115+
116+
_Note:_ This option only affects `report` modes other than `"all"`.
117+
118+
### `reportUnreachable`
119+
120+
All `report` modes report unreachable alternatives. These are alternatives that can _never_ be reached because a previous alternative always accepts before them. I.e. in `/int|integer/.exec("integer")`, the `integer` alternative is unreachable because the `int` alternative will always accept before the `integer` alternative has a chance to.
121+
122+
However, some regexes are used as fragments to build more complex regexes. Example:
123+
124+
```js
125+
const int = /int|integer/.source;
126+
const pattern = RegExp(`\\b(${int}|\\d+)\\b`, "g");
127+
128+
"integer int".match(pattern)
129+
// => [ 'integer', 'int' ]
130+
```
131+
132+
In these fragments, seemingly unreachable alternatives might not actually be unreachable depending on how the fragment is used.
133+
134+
This option controls how this rule reports unreachable alternatives in fragments.
135+
136+
- `reportUnreachable: "potential"`
137+
138+
In this case, this rule will always report unreachable alternatives, even in fragments.
139+
140+
```js
141+
const int = /int|integer/.source; // report (false positive)
142+
const pattern = RegExp(`\\b(${int}|\\d+)\\b`);
143+
```
144+
145+
```js
146+
const int = /int|integer/.source; // report (true positive)
147+
const pattern = RegExp(`is (${int})`);
148+
```
149+
150+
- `reportUnreachable: "certain"` (_default_)
151+
152+
In this case, this rule will only report unreachable alternatives in non-fragment regexes.
153+
154+
```js
155+
const int = /int|integer/.source; // no report (true negative)
156+
const pattern = RegExp(`\\b(${int}|\\d+)\\b`);
157+
```
158+
159+
```js
160+
const int = /int|integer/.source; // no report (false negative)
161+
const pattern = RegExp(`is (${int})`);
162+
```
95163

96164
## :rocket: Version
97165

0 commit comments

Comments
 (0)