@putout/engine-runner
Version:
198 lines (158 loc) • 4.68 kB
JavaScript
'use strict';
const {traverse: defaultTraverse} = require('@putout/babel');
const once = require('once');
const debug = require('debug')('putout:runner:find');
const runFix = require('./run-fix');
const mergeVisitors = require('./merge-visitors');
const superFind = require('./super-find');
const template = require('./template/index.js');
const {createProgress} = require('./progress');
const {tryThrowWithReason} = require('./try-throw-with-reason');
const {include} = require('./includer/index.js');
const {replace, clearWatermark} = require('./replacer/index.js');
const {declare} = require('./declarator/index.js');
const {scan} = require('./scanner/index.js');
const {getPath, getPosition} = require('./get-position');
const isRemoved = (a) => a?.removed;
module.exports.runPlugins = ({ast, shebang, fix, fixCount = 2, plugins, progress = createProgress(), traverse = defaultTraverse}) => {
let places = [];
const merge = once(mergeVisitors);
const {
pluginsFind,
pluginsTraverse,
} = splitPlugins(plugins, {
progress,
});
for (let i = 0; i < fixCount; i++) {
places = run({
ast,
fix,
shebang,
pluginsFind,
pluginsTraverse,
merge,
template,
traverse,
});
progress.reset();
if (!fix || !places.length)
return places;
clearWatermark(ast);
}
return places;
};
module.exports.getPosition = getPosition;
const run = ({ast, fix, shebang, pluginsFind, pluginsTraverse, template, merge, traverse}) => [
...runWithoutMerge({
ast,
fix,
shebang,
template,
pluginsFind,
traverse,
}),
...runWithMerge({
ast,
fix,
shebang,
template,
pluginsTraverse,
merge,
traverse,
}),
];
function runWithMerge({ast, fix, shebang, template, pluginsTraverse, merge, traverse}) {
const {entries, visitor} = merge(pluginsTraverse, {
fix,
shebang,
template,
});
tryThrowWithReason(traverse, ast, visitor);
const places = [];
for (const [rule, pull] of entries) {
const items = pull();
for (const {message, position} of items) {
places.push({
rule,
message,
position,
});
}
}
return places;
}
function runWithoutMerge({ast, fix, shebang, template, pluginsFind, traverse}) {
const places = [];
for (const {rule, plugin, msg, options} of pluginsFind) {
debug(`find: ${rule}`);
const {report, find} = plugin;
const items = tryThrowWithReason(superFind, {
rule,
find,
ast,
options,
fix,
shebang,
template,
traverse,
});
if (!items.length)
continue;
for (const item of items) {
const message = msg || report(item);
const {parentPath} = getPath(item);
const position = getPosition(item, shebang);
places.push({
rule,
message,
position,
});
if (isRemoved(parentPath))
continue;
runFix(fix, plugin.fix, {
path: item,
rule,
position,
options,
});
}
}
return places;
}
function splitPlugins(plugins, {progress}) {
const pluginsFind = [];
const pluginsTraverse = [];
for (const item of plugins) {
const {plugin} = item;
if (plugin.find) {
pluginsFind.push(item);
continue;
}
if (plugin.traverse) {
pluginsTraverse.push(item);
continue;
}
if (plugin.replace) {
pluginsTraverse.push(include(replace(item)));
continue;
}
if (plugin.declare) {
pluginsTraverse.push(include(declare(item)));
continue;
}
if (plugin.include) {
pluginsTraverse.push(include(item));
continue;
}
if (plugin.scan) {
pluginsTraverse.push(scan(item, {
progress,
}));
continue;
}
}
return {
pluginsFind,
pluginsTraverse,
};
}