@putout/engine-runner 12.3.0 → 12.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -63
- package/lib/index.js +9 -9
- package/lib/replace/index.js +32 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,6 +13,15 @@ npm i @putout/engine-runner
|
|
|
13
13
|
|
|
14
14
|
## Supported Plugin Types
|
|
15
15
|
|
|
16
|
+
There is a couple plugin types supported by 🐊`Putout`:
|
|
17
|
+
|
|
18
|
+
- ✅[`Replacer`](#replacer)
|
|
19
|
+
- ✅[`Includer`](#includer)
|
|
20
|
+
- ✅[`Traverser`](#traverser)
|
|
21
|
+
- ✅[`Finder`](#finder)
|
|
22
|
+
|
|
23
|
+
They goes from simplest to hardest. Let's start from `Replacer`.
|
|
24
|
+
|
|
16
25
|
### Replacer
|
|
17
26
|
|
|
18
27
|
`Replacer` converts code in declarative way. Simplest possible form, no need to use `fix`. Just `from` and `to` parts
|
|
@@ -171,14 +180,70 @@ module.exports.traverse = ({push}) => ({
|
|
|
171
180
|
});
|
|
172
181
|
```
|
|
173
182
|
|
|
174
|
-
|
|
183
|
+
### Finder
|
|
184
|
+
|
|
185
|
+
`Find plugins` gives you all the control over traversing, but it's the slowest format.
|
|
186
|
+
Because `traversers` not merged in contrast with other plugin formats.
|
|
187
|
+
|
|
188
|
+
```js
|
|
189
|
+
module.exports.report = () => 'debugger statement should not be used';
|
|
190
|
+
|
|
191
|
+
module.exports.fix = (path) => {
|
|
192
|
+
path.remove();
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
module.exports.find = (ast, {push, traverse}) => {
|
|
196
|
+
traverse(ast, {
|
|
197
|
+
'debugger'(path) {
|
|
198
|
+
push(path);
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
};
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Example
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
const {runPlugins} = require('@putout/engine-runner');
|
|
208
|
+
const {parse} = require('@putout/engin-parser');
|
|
209
|
+
|
|
210
|
+
const plugins = [{
|
|
211
|
+
rule: "remove-debugger",
|
|
212
|
+
msg: "", // optional
|
|
213
|
+
options: {}, // optional
|
|
214
|
+
plugin: {
|
|
215
|
+
include: () => ['debugger'],
|
|
216
|
+
fix: (path) => path.remove(),
|
|
217
|
+
report: () => `debugger should not be used`,
|
|
218
|
+
},
|
|
219
|
+
}];
|
|
220
|
+
|
|
221
|
+
const ast = parse('const m = "hi"; debugger');
|
|
222
|
+
const places = runPlugins({
|
|
223
|
+
ast,
|
|
224
|
+
shebang: false, // default
|
|
225
|
+
fix: true, // default
|
|
226
|
+
fixCount: 1, // default
|
|
227
|
+
plugins,
|
|
228
|
+
parser: 'babel', // default
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Stores
|
|
233
|
+
|
|
234
|
+
Stores is preferred way of keeping 🐊`Putout` data, `traverse` init function called only once, and any other way
|
|
235
|
+
of handling variables will most likely will lead to bugs. There is 3 store types:
|
|
175
236
|
|
|
176
|
-
|
|
177
|
-
|
|
237
|
+
- ✅`listStore`;
|
|
238
|
+
- ✅`store`;
|
|
239
|
+
- ✅`upstore`;
|
|
178
240
|
|
|
179
|
-
|
|
241
|
+
Let's talk about each of them.
|
|
180
242
|
|
|
181
|
-
|
|
243
|
+
### `listStore`
|
|
244
|
+
|
|
245
|
+
To save things as a list use `listStore`.
|
|
246
|
+
Let's suppose you have such code:
|
|
182
247
|
|
|
183
248
|
```js
|
|
184
249
|
debugger;
|
|
@@ -187,6 +252,8 @@ debugger;
|
|
|
187
252
|
const world = '';
|
|
188
253
|
```
|
|
189
254
|
|
|
255
|
+
Let's process it!
|
|
256
|
+
|
|
190
257
|
```js
|
|
191
258
|
module.exports.traverse = ({listStore}) => ({
|
|
192
259
|
'debugger'(path) {
|
|
@@ -205,7 +272,9 @@ module.exports.traverse = ({listStore}) => ({
|
|
|
205
272
|
});
|
|
206
273
|
```
|
|
207
274
|
|
|
208
|
-
|
|
275
|
+
### `store`
|
|
276
|
+
|
|
277
|
+
When you need `key-value` use `store`:
|
|
209
278
|
|
|
210
279
|
```js
|
|
211
280
|
module.exports.traverse = ({push, store}) => ({
|
|
@@ -232,9 +301,9 @@ module.exports.traverse = ({push, store}) => ({
|
|
|
232
301
|
});
|
|
233
302
|
```
|
|
234
303
|
|
|
235
|
-
|
|
304
|
+
### `upstore`
|
|
236
305
|
|
|
237
|
-
When you need to update already saved values, use `upstore
|
|
306
|
+
When you need to update already saved values, use `upstore`:
|
|
238
307
|
|
|
239
308
|
```js
|
|
240
309
|
module.exports.traverse = ({push, store}) => ({
|
|
@@ -269,65 +338,15 @@ module.exports.traverse = ({push, store}) => ({
|
|
|
269
338
|
});
|
|
270
339
|
```
|
|
271
340
|
|
|
272
|
-
### Finder
|
|
273
|
-
|
|
274
|
-
`Find plugins` gives you all the control over traversing, but it's the slowest format.
|
|
275
|
-
Because `traversers` not merged in contrast with other plugin formats.
|
|
276
|
-
|
|
277
|
-
```js
|
|
278
|
-
module.exports.report = () => 'debugger statement should not be used';
|
|
279
|
-
|
|
280
|
-
module.exports.fix = (path) => {
|
|
281
|
-
path.remove();
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
module.exports.find = (ast, {push, traverse}) => {
|
|
285
|
-
traverse(ast, {
|
|
286
|
-
'debugger'(path) {
|
|
287
|
-
push(path);
|
|
288
|
-
},
|
|
289
|
-
});
|
|
290
|
-
};
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
## Example
|
|
294
|
-
|
|
295
|
-
```js
|
|
296
|
-
const {runPlugins} = require('@putout/engine-runner');
|
|
297
|
-
const {parse} = require('@putout/engin-parser');
|
|
298
|
-
|
|
299
|
-
const plugins = [{
|
|
300
|
-
rule: "remove-debugger",
|
|
301
|
-
msg: "", // optional
|
|
302
|
-
options: {}, // optional
|
|
303
|
-
plugin: {
|
|
304
|
-
include: () => ['debugger'],
|
|
305
|
-
fix: (path) => path.remove(),
|
|
306
|
-
report: () => `debugger should not be used`,
|
|
307
|
-
},
|
|
308
|
-
}];
|
|
309
|
-
|
|
310
|
-
const ast = parse('const m = "hi"; debugger');
|
|
311
|
-
const places = runPlugins({
|
|
312
|
-
ast,
|
|
313
|
-
shebang: false, // default
|
|
314
|
-
fix: true, // default
|
|
315
|
-
fixCount: 1, // default
|
|
316
|
-
plugins,
|
|
317
|
-
parser: 'babel', // default
|
|
318
|
-
});
|
|
319
|
-
```
|
|
320
|
-
|
|
321
341
|
## Logs
|
|
322
342
|
|
|
323
343
|
To see logs, use:
|
|
324
344
|
|
|
325
|
-
|
|
326
|
-
DEBUG=putout:runner
|
|
327
|
-
DEBUG=putout:runner:
|
|
328
|
-
DEBUG=putout:runner:
|
|
329
|
-
DEBUG=putout:runner:
|
|
330
|
-
```
|
|
345
|
+
- ✅ `DEBUG=putout:runner:*`
|
|
346
|
+
- ✅ `DEBUG=putout:runner:fix`
|
|
347
|
+
- ✅ `DEBUG=putout:runner:find`
|
|
348
|
+
- ✅ `DEBUG=putout:runner:template`
|
|
349
|
+
- ✅ `DEBUG=putout:runner:replace`
|
|
331
350
|
|
|
332
351
|
## License
|
|
333
352
|
|
package/lib/index.js
CHANGED
|
@@ -24,9 +24,7 @@ module.exports.runPlugins = ({ast, shebang, fix, fixCount, plugins, template = r
|
|
|
24
24
|
const {
|
|
25
25
|
pluginsFind,
|
|
26
26
|
pluginsTraverse,
|
|
27
|
-
} = splitPlugins(plugins
|
|
28
|
-
template,
|
|
29
|
-
});
|
|
27
|
+
} = splitPlugins(plugins);
|
|
30
28
|
|
|
31
29
|
for (let i = 0; i < fixCount; i++) {
|
|
32
30
|
places = run({
|
|
@@ -130,23 +128,25 @@ function runWithoutMerge({ast, fix, shebang, template, pluginsFind}) {
|
|
|
130
128
|
return places;
|
|
131
129
|
}
|
|
132
130
|
|
|
133
|
-
function splitPlugins(plugins
|
|
131
|
+
function splitPlugins(plugins) {
|
|
134
132
|
const pluginsFind = [];
|
|
135
133
|
const pluginsTraverse = [];
|
|
136
134
|
|
|
137
135
|
for (const item of plugins) {
|
|
138
136
|
const {plugin} = item;
|
|
139
137
|
|
|
140
|
-
if (plugin.find)
|
|
138
|
+
if (plugin.find) {
|
|
141
139
|
pluginsFind.push(item);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
142
|
|
|
143
|
-
if (plugin.traverse)
|
|
143
|
+
if (plugin.traverse) {
|
|
144
144
|
pluginsTraverse.push(item);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
145
147
|
|
|
146
148
|
if (plugin.replace) {
|
|
147
|
-
pluginsTraverse.push(include(replace(item
|
|
148
|
-
template,
|
|
149
|
-
})));
|
|
149
|
+
pluginsTraverse.push(include(replace(item)));
|
|
150
150
|
continue;
|
|
151
151
|
}
|
|
152
152
|
|
package/lib/replace/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const isString = (a) => typeof a === 'string';
|
|
4
|
+
|
|
3
5
|
const {template} = require('@putout/engine-parser');
|
|
4
6
|
const {
|
|
5
7
|
remove,
|
|
@@ -11,10 +13,15 @@ const {
|
|
|
11
13
|
getValues,
|
|
12
14
|
setValues,
|
|
13
15
|
} = require('@putout/compare');
|
|
16
|
+
const debug = require('debug')('putout:runner:replace');
|
|
14
17
|
|
|
15
18
|
const maybeArray = require('../maybe-array');
|
|
16
19
|
const watermark = require('./watermark');
|
|
17
20
|
|
|
21
|
+
const log = (from, path) => {
|
|
22
|
+
debug.enabled && debug(`${from} -> ${path}\n`);
|
|
23
|
+
};
|
|
24
|
+
|
|
18
25
|
const {keys, entries} = Object;
|
|
19
26
|
const {stringify} = JSON;
|
|
20
27
|
|
|
@@ -23,13 +30,6 @@ const stubMatch = () => ({});
|
|
|
23
30
|
const packKeys = (a) => () => keys(a);
|
|
24
31
|
const isObj = (a) => typeof a === 'object';
|
|
25
32
|
|
|
26
|
-
const validateTemplateValues = (a, b) => {
|
|
27
|
-
for (const key of keys(a)) {
|
|
28
|
-
if (!b[key])
|
|
29
|
-
throw Error(`☝️ Looks like template values not linked: ${stringify(keys(b))} -> ${stringify(keys(a))}`);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
|
|
33
33
|
module.exports = ({rule, plugin, msg, options}) => {
|
|
34
34
|
const {
|
|
35
35
|
report,
|
|
@@ -89,8 +89,10 @@ const fix = (from, to, path) => {
|
|
|
89
89
|
|
|
90
90
|
const nodeTo = parseTo(to, values, path);
|
|
91
91
|
|
|
92
|
-
if (!nodeTo)
|
|
92
|
+
if (!nodeTo) {
|
|
93
|
+
log(from, `''`);
|
|
93
94
|
return remove(path);
|
|
95
|
+
}
|
|
94
96
|
|
|
95
97
|
const waysTo = findVarsWays(nodeTo);
|
|
96
98
|
const newPath = replaceWith(path, nodeTo);
|
|
@@ -105,7 +107,8 @@ const fix = (from, to, path) => {
|
|
|
105
107
|
|
|
106
108
|
mark.add();
|
|
107
109
|
path.scope.getBlockParent().crawl();
|
|
108
|
-
|
|
110
|
+
|
|
111
|
+
log(from, newPath);
|
|
109
112
|
};
|
|
110
113
|
|
|
111
114
|
const getFix = (items) => (path) => {
|
|
@@ -116,7 +119,7 @@ const getFix = (items) => (path) => {
|
|
|
116
119
|
const getFilter = (match = stubMatch, options) => (path) => {
|
|
117
120
|
const all = entries(match({options}));
|
|
118
121
|
|
|
119
|
-
for (const [from,
|
|
122
|
+
for (const [from, matchProperty] of all) {
|
|
120
123
|
const nodeFrom = template.ast(from);
|
|
121
124
|
|
|
122
125
|
if (!compare(path.node, nodeFrom)) {
|
|
@@ -131,7 +134,9 @@ const getFilter = (match = stubMatch, options) => (path) => {
|
|
|
131
134
|
node,
|
|
132
135
|
});
|
|
133
136
|
|
|
134
|
-
|
|
137
|
+
validateMatchProperty(matchProperty);
|
|
138
|
+
|
|
139
|
+
return matchProperty(values, path);
|
|
135
140
|
}
|
|
136
141
|
|
|
137
142
|
return true;
|
|
@@ -143,9 +148,24 @@ function parseTo(to, values, path) {
|
|
|
143
148
|
if (!toStr)
|
|
144
149
|
return null;
|
|
145
150
|
|
|
146
|
-
if (isObj(toStr))
|
|
151
|
+
if (isObj(toStr) && toStr.type)
|
|
147
152
|
return toStr;
|
|
148
153
|
|
|
154
|
+
if (!isString(toStr))
|
|
155
|
+
throw Error(`☝️ Looks like you passed 'replace' value with a wrong type. Allowed: 'string', 'node' and 'path'. Received: '${typeof toStr}' with value '${toStr}'.`);
|
|
156
|
+
|
|
149
157
|
return template.ast.fresh(toStr);
|
|
150
158
|
}
|
|
151
159
|
|
|
160
|
+
function validateMatchProperty(match) {
|
|
161
|
+
if (!isFn(match))
|
|
162
|
+
throw Error(`☝️ Looks like 'match' property value is not a 'function', but '${typeof match}' with value '${match}'.`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const validateTemplateValues = (a, b) => {
|
|
166
|
+
for (const key of keys(a)) {
|
|
167
|
+
if (!b[key])
|
|
168
|
+
throw Error(`☝️ Looks like template values not linked: ${stringify(keys(b))} -> ${stringify(keys(a))}`);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|