Skip to content

Commit 056a8dc

Browse files
committed
feature: @putout/plugin-regexp: remove-useless-group: transformRegExp
1 parent d3e9731 commit 056a8dc

File tree

5 files changed

+83
-66
lines changed

5 files changed

+83
-66
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/[a-zA-Z]/g

packages/plugin-regexp/lib/remove-duplicates-from-character-class/index.spec.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,8 @@ test('regexp: remove-duplicates-from-character-class: transform', (t) => {
1616
t.transform('remove-duplicates-from-character-class');
1717
t.end();
1818
});
19+
20+
test('regexp: remove-duplicates-from-character-class: no report: class-range', (t) => {
21+
t.noReport('class-range');
22+
t.end();
23+
});

packages/plugin-regexp/lib/remove-duplicates-from-character-class/regexp.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const isChar = ({type}) => type === 'Char';
2+
13
export const report = () => 'Remove duplicates from character class';
24
export const fix = ({path, j}) => delete path.node.expressions[j];
35
export const traverse = ({push}) => ({
@@ -12,6 +14,9 @@ export const traverse = ({push}) => ({
1214
if (!a || !b)
1315
continue;
1416

17+
if (!isChar(a) || !isChar(b))
18+
continue;
19+
1520
if (a.value === b.value)
1621
push({
1722
j,
Lines changed: 14 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import regexpTree from 'regexp-tree';
21
import {operator} from 'putout';
3-
import {
4-
isDisjunction,
5-
isParentDisjunction,
6-
} from '../types.js';
2+
import * as regexp from './regexp.js';
73

8-
const {compare} = operator;
4+
const {
5+
compare,
6+
transformRegExp,
7+
} = operator;
98

109
export const report = ({from, to}) => `Remove useless group from RegExp ${from}, use ${to}`;
1110

@@ -32,73 +31,22 @@ export const traverse = ({push}) => ({
3231
return;
3332

3433
const from = path.node.extra.raw;
35-
const [is, to] = removeUselessGroup(from);
34+
const [to, places] = transformRegExp(from, regexp);
3635

37-
if (is)
38-
push({
39-
path,
40-
from,
41-
to,
42-
});
36+
if (!places.length)
37+
return;
38+
39+
push({
40+
path,
41+
from,
42+
to,
43+
});
4344
},
4445
});
4546

46-
function removeUselessGroup(str) {
47-
const ast = regexpTree.parse(str);
48-
let is = false;
49-
50-
regexpTree.traverse(ast, {
51-
Group(path) {
52-
const {type} = path.parent;
53-
54-
if (!/RegExp|Alternative/.test(type))
55-
return;
56-
57-
const nextNode = getNextSibling(path);
58-
59-
if (nextNode?.type === 'Repetition')
60-
return;
61-
62-
const {node} = path;
63-
64-
if (node.name)
65-
return;
66-
67-
if (!node.expression)
68-
return;
69-
70-
if (isParentDisjunction(path))
71-
return;
72-
73-
if (isDisjunction(node.expression))
74-
return;
75-
76-
is = true;
77-
path.replace(node.expression);
78-
},
79-
});
80-
81-
return [is, regexpTree.generate(ast)];
82-
}
83-
8447
function includes({parentPath}) {
8548
if (compare(parentPath.parentPath, '/__a/.test(__b)'))
8649
return true;
8750

8851
return compare(parentPath, '__.search(/__a/)');
8952
}
90-
91-
function getNextSibling(path) {
92-
let found = false;
93-
const {expressions = []} = path.parent;
94-
95-
for (const current of expressions) {
96-
if (found)
97-
return current;
98-
99-
if (current === path.node)
100-
found = true;
101-
}
102-
103-
return null;
104-
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {
2+
isDisjunction,
3+
isParentDisjunction,
4+
} from '../types.js';
5+
6+
export const report = () => 'Remove useless group';
7+
8+
export const fix = ({path, node}) => {
9+
path.replace(node.expression);
10+
};
11+
12+
export const traverse = ({push}) => ({
13+
Group(path) {
14+
const {type} = path.parent;
15+
16+
if (!/RegExp|Alternative/.test(type))
17+
return;
18+
19+
const nextNode = getNextSibling(path);
20+
21+
if (nextNode?.type === 'Repetition')
22+
return;
23+
24+
const {node} = path;
25+
26+
if (node.name)
27+
return;
28+
29+
if (!node.expression)
30+
return;
31+
32+
if (isParentDisjunction(path))
33+
return;
34+
35+
if (isDisjunction(node.expression))
36+
return;
37+
38+
push({
39+
path,
40+
node,
41+
});
42+
},
43+
});
44+
45+
function getNextSibling(path) {
46+
let found = false;
47+
const {expressions = []} = path.parent;
48+
49+
for (const current of expressions) {
50+
if (found)
51+
return current;
52+
53+
if (current === path.node)
54+
found = true;
55+
}
56+
57+
return null;
58+
}

0 commit comments

Comments
 (0)