Skip to content

Commit 9d3893e

Browse files
committed
feature: @putout/engine-runner: replace: couple: run fix only after match
1 parent 08ce83b commit 9d3893e

File tree

4 files changed

+131
-22
lines changed

4 files changed

+131
-22
lines changed

packages/engine-runner/lib/replace/find-path.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ module.exports = (parentPath) => {
1616

1717
return path.join('.');
1818
};
19+
1920
function findKey(path, parent) {
2021
const {node} = path;
22+
let key;
23+
let value;
2124

22-
for (const [key, value] of entries(parent)) {
25+
for ([key, value] of entries(parent)) {
2326
if (isArray(value)) {
2427
const index = value.indexOf(node);
2528

@@ -30,6 +33,8 @@ function findKey(path, parent) {
3033
}
3134

3235
if (value === node)
33-
return key;
36+
break;
3437
}
38+
39+
return key;
3540
}

packages/engine-runner/lib/replace/index.js

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ module.exports = ({rule, plugin, msg, options}) => {
5959
options,
6060
});
6161

62-
const fix = getFix(replaceItems);
62+
const fix = getFix(replaceItems, plugin.match, options);
6363
const include = packKeys(replaceItems);
6464

6565
return {
@@ -96,9 +96,6 @@ const fix = (from, to, path) => {
9696
if (mark.has())
9797
return;
9898

99-
if (!compare(path, nodeFrom, {findUp: false}))
100-
return;
101-
10299
const waysFrom = findVarsWays(nodeFrom);
103100
const {node} = path;
104101

@@ -138,9 +135,21 @@ const fix = (from, to, path) => {
138135
log(from, newPath);
139136
};
140137

141-
const getFix = (items) => (path) => {
142-
for (const [from, to] of entries(items))
143-
fix(from, to, path);
138+
const getFix = (items, match = stubMatch, options) => (path) => {
139+
const initedMatch = match({
140+
options,
141+
});
142+
143+
for (const [from, to] of entries(items)) {
144+
const nodeFrom = template.ast(from);
145+
146+
if (compare(path, nodeFrom, {findUp: false})) {
147+
const matchFn = initedMatch[from];
148+
149+
if (!matchFn || runMatch(path, nodeFrom, matchFn))
150+
fix(from, to, path);
151+
}
152+
}
144153
};
145154

146155
const getFilter = (match = stubMatch, options) => (path) => {
@@ -151,25 +160,29 @@ const getFilter = (match = stubMatch, options) => (path) => {
151160
for (const [from, matchProperty] of all) {
152161
const nodeFrom = template.ast(from);
153162

154-
if (!compare(path.node, nodeFrom))
163+
if (!compare(path.node, nodeFrom, {findUp: false}))
155164
continue;
156165

157-
const waysFrom = findVarsWays(nodeFrom);
158-
const {node} = path;
159-
160-
const values = getValues({
161-
waysFrom,
162-
node,
163-
});
164-
165-
validateMatchProperty(matchProperty);
166-
167-
return matchProperty(values, path);
166+
return runMatch(path, nodeFrom, matchProperty);
168167
}
169168

170169
return true;
171170
};
172171

172+
function runMatch(path, nodeFrom, matchProperty) {
173+
const waysFrom = findVarsWays(nodeFrom);
174+
const {node} = path;
175+
176+
const values = getValues({
177+
waysFrom,
178+
node,
179+
});
180+
181+
validateMatchProperty(matchProperty);
182+
183+
return matchProperty(values, path);
184+
}
185+
173186
function parseTo(to, values, path) {
174187
const toStr = isFn(to) ? to(values, path) : to;
175188

packages/engine-runner/lib/replace/watermark.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const hasWatermark = (watermark) => (path) => path.node?.[name]?.has(watermark);
1111

1212
module.exports = (from, to, path) => {
1313
const {watermark, highWatermark} = create(from, to, path);
14-
const program = path.findParent(isProgram) || path;
14+
const program = path.findParent(isProgram);
1515
const options = {
1616
watermark,
1717
highWatermark,

packages/engine-runner/test/replace.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const {print, types} = putout;
1616
const {
1717
StringLiteral,
1818
ReturnStatement,
19+
isStringLiteral,
1920
} = types;
2021

2122
const readFixture = (a) => readFileSync(join(__dirname, 'fixture', `${a}.js`), 'utf8');
@@ -1006,3 +1007,93 @@ test('putout: runner: replace: callstack', (t) => {
10061007
t.equal(code, expected);
10071008
t.end();
10081009
});
1010+
1011+
test('putout: runner: replace: match: double', (t) => {
1012+
const convert = {
1013+
report: noop,
1014+
match: () => ({
1015+
'createDirectory(__a, __b)': ({__b}) => {
1016+
if (!isStringLiteral(__b))
1017+
return false;
1018+
1019+
return __b.value.includes('/');
1020+
},
1021+
'createNestedDirectory(__a, __b)': ({__b}) => {
1022+
if (!isStringLiteral(__b))
1023+
return false;
1024+
1025+
return !__b.value.includes('/');
1026+
},
1027+
}),
1028+
replace: () => ({
1029+
'createDirectory(__a, __b)': 'createNestedDirectory(__a, __b)',
1030+
'createNestedDirectory(__a, __b)': 'createDirectory(__a, __b)',
1031+
}),
1032+
};
1033+
1034+
const source = montag`
1035+
const dirPath = createDirectory(path, '/hello/world');
1036+
`;
1037+
1038+
const {code} = putout(source, {
1039+
runPlugins,
1040+
plugins: [
1041+
['convert', convert],
1042+
],
1043+
});
1044+
1045+
const expected = montag`
1046+
const dirPath = createNestedDirectory(path, '/hello/world');\n
1047+
`;
1048+
1049+
t.equal(code, expected);
1050+
t.end();
1051+
});
1052+
1053+
test('putout: runner: replace: match: couple checks', (t) => {
1054+
const convert = {
1055+
report: noop,
1056+
match: () => ({
1057+
'createDirectory(__a, __b)': ({__b}) => {
1058+
if (!isStringLiteral(__b))
1059+
return false;
1060+
1061+
return __b.value.includes('/');
1062+
},
1063+
'createNestedDirectory(__a, __b)': ({__b}) => {
1064+
if (!isStringLiteral(__b))
1065+
return false;
1066+
1067+
return !__b.value.includes('/');
1068+
},
1069+
}),
1070+
replace: () => ({
1071+
'!__a in __b': '!(__a in __b)',
1072+
'__a in !__b': '!(__a in __b)',
1073+
'!__a in !__b': '!(__a in __b)',
1074+
}),
1075+
};
1076+
1077+
const source = montag`
1078+
!a in b;
1079+
a in !b;
1080+
!a in !b;
1081+
`;
1082+
1083+
const {code} = putout(source, {
1084+
runPlugins,
1085+
plugins: [
1086+
['convert', convert],
1087+
],
1088+
});
1089+
1090+
const expected = montag`
1091+
!(a in b);
1092+
!(a in b);
1093+
!(a in b);
1094+
1095+
`;
1096+
1097+
t.equal(code, expected);
1098+
t.end();
1099+
});

0 commit comments

Comments
 (0)