Skip to content

Commit c533146

Browse files
committed
feature: @putout/plugin-regexp: apply-global-regexp-to-replace-all
1 parent 2860cb9 commit c533146

File tree

12 files changed

+94
-0
lines changed

12 files changed

+94
-0
lines changed

docs/syntax-errors.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,12 @@ export const {
360360
```
361361

362362
</details>
363+
364+
<details><summary><code>replaceAll()</code> called with a non-global <code>RegExp</code>argument</summary>
365+
366+
```diff
367+
-'hello'.replaceAll(/hello/, 'world')
368+
+'hello'.replaceAll(/hello/g, 'world')
369+
```
370+
371+
</details>

packages/plugin-regexp/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ npm i @putout/plugin-regexp -D
1818
## Rules
1919

2020
-[apply-ends-with](#apply-ends-with);
21+
-[apply-global-regexp-to-replace-al](#apply-global-regexp-to-replace-all);
2122
-[apply-literal-notation](#apply-literal-notation);
2223
-[apply-starts-with](#apply-starts-with);
2324
-[convert-replace-to-replace-all](#convert-replace-to-replace-all);
@@ -32,6 +33,7 @@ npm i @putout/plugin-regexp -D
3233
```json
3334
{
3435
"rules": {
36+
"regexp/apply-global-regexp-to-replace-all": "on",
3537
"regexp/apply-literal-notation": "on",
3638
"regexp/apply-starts-with": "on",
3739
"regexp/apply-ends-with": "on",
@@ -58,6 +60,28 @@ const a = /(ab|ab)/;
5860
const a = /(ab)/;
5961
```
6062

63+
## apply-global-regexp-to-replace-all
64+
65+
> `Uncaught TypeError: String.prototype.replaceAll called with a non-global RegExp argument`
66+
>
67+
> (c) [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Requires_global_RegExp)
68+
69+
Checkout in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/8c759e3c8d19d660ddb01bda04d75c8b/f1d0f3a6d491f034308f5f3a375900b0a620a3b3).
70+
71+
### ❌ Example of incorrect code
72+
73+
```js
74+
's'.replaceAll(/hello/, 's');
75+
'abc'.matchAll(/./);
76+
```
77+
78+
### ✅ Example of correct code
79+
80+
```js
81+
's'.replaceAll(/hello/g, 's');
82+
'abc'.matchAll(/./g);
83+
```
84+
6185
## apply-literal-notation
6286

6387
### ❌ Example of incorrect code
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
's'.replaceAll(/hello/g, 's');
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
's'.replaceAll(/hello/, 's')
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
'abc'.matchAll(/./g);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"abc".matchAll(/./);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const check = ({__a}) => !__a.raw.endsWith('g');
2+
const transform = ({__a}, path) => {
3+
__a.raw += 'g';
4+
return path;
5+
};
6+
7+
export const report = (path) => {
8+
const name = path.get('callee.property');
9+
return `Call '${name.node.name}()' with global 'RegExp'`;
10+
};
11+
12+
export const match = () => ({
13+
'__.replaceAll(/__a/, __b)': check,
14+
'__.matchAll(/__a/)': check,
15+
});
16+
17+
export const replace = () => ({
18+
'__.replaceAll(/__a/, __b)': transform,
19+
'__.matchAll(/__a/)': transform,
20+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {createTest} from '@putout/test';
2+
import * as plugin from './index.js';
3+
4+
const test = createTest(import.meta.url, {
5+
plugins: [
6+
['apply-global-regexp-to-replace-all', plugin],
7+
],
8+
});
9+
10+
test('regexp: apply-global-regexp-to-replace-all: report', (t) => {
11+
t.report('apply-global-regexp-to-replace-all', `Call 'replaceAll()' with global 'RegExp'`);
12+
t.end();
13+
});
14+
15+
test('regexp: apply-global-regexp-to-replace-all: report: match-all', (t) => {
16+
t.report('match-all', `Call 'matchAll()' with global 'RegExp'`);
17+
t.end();
18+
});
19+
20+
test('regexp: apply-global-regexp-to-replace-all: transform', (t) => {
21+
t.transform('apply-global-regexp-to-replace-all');
22+
t.end();
23+
});
24+
25+
test('regexp: apply-global-regexp-to-replace-all: transform: match-all', (t) => {
26+
t.transform('match-all');
27+
t.end();
28+
});

packages/plugin-regexp/lib/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as applyGlobalRegexpToReplaceAll from './apply-global-regexp-to-replace-all/index.js';
12
import * as applyLiteralNotation from './apply-literal-notation/index.js';
23
import * as applyStartsWith from './apply-starts-with/index.js';
34
import * as applyEndsWith from './apply-ends-with/index.js';
@@ -16,4 +17,5 @@ export const rules = {
1617
'convert-replace-to-replace-all': convertReplaceToReplaceAll,
1718
'remove-useless-group': removeUselessGroup,
1819
'remove-useless-regexp': removeUselessRegexp,
20+
'apply-global-regexp-to-replace-all': applyGlobalRegexpToReplaceAll,
1921
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
's'.replaceAll(/hello/g, 's');

0 commit comments

Comments
 (0)