astx
Version:
super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring
144 lines (124 loc) • 17 kB
JavaScript
import chalk from 'chalk'
import countLines from './countLines.mjs'
const captureColors = [
chalk.green,
chalk.yellow,
chalk.blue,
chalk.cyan,
chalk.magenta,
chalk.red,
]
function deriveLineAndColumn(source, index) {
const rx = /\r\n?|\n/gm
let lastIndex = 0
let line = 1
while (lastIndex < index) {
rx.lastIndex = lastIndex + 1
const match = rx.exec(source)
if (!match) break
line++
lastIndex = match.index
}
return {
startLine: line,
startColumn: index - lastIndex,
}
}
function formatMatch(backend, source, match, lineCount) {
const lineNumberLength = String(lineCount).length
if (match.type === 'nodes' && !match.nodes.length)
return `${' '.repeat(lineNumberLength)} | (zero statements)`
const { start: nodeStart } = backend.location(match.nodes[0])
const { end: nodeEnd } = backend.location(match.nodes[match.nodes.length - 1])
if (nodeStart == null || nodeEnd == null) {
throw new Error('failed to get match location')
}
let { startLine, startColumn: startCol } = backend.location(match.nodes[0])
if (startLine == null || startCol == null) {
;({ startLine, startColumn: startCol } = deriveLineAndColumn(
source,
nodeStart
))
}
const { captures, arrayCaptures } = match
const start = nodeStart - startCol
const eolRegex = /\r\n?|\n/gm
eolRegex.lastIndex = nodeEnd
const eolMatch = eolRegex.exec(source)
const end = eolMatch ? eolMatch.index : nodeEnd
let captureColor = 0
const captureRanges = []
if (captures) {
for (const [key, node] of Object.entries(captures)) {
const { start, end } = backend.location(node)
if (start != null && end != null) {
captureRanges.push({
key,
start,
end,
color: captureColors[captureColor++] || chalk.gray,
})
}
}
}
if (arrayCaptures) {
for (const [key, nodes] of Object.entries(arrayCaptures)) {
const first = nodes[0]
const last = nodes[nodes.length - 1]
if (!first || !last) continue
const { start } = backend.location(first)
const { end } = backend.location(last)
if (start != null && end != null) {
captureRanges.push({
key,
start,
end,
color: captureColors[captureColor++] || chalk.gray,
})
}
}
}
captureRanges.sort((a, b) => a.start - b.start)
let lastIndex = nodeStart
const parts = []
for (const { start, end, color } of captureRanges) {
if (start < lastIndex) continue
parts.push(source.substring(lastIndex, start))
parts.push(color(source.substring(start, end)))
lastIndex = end
}
parts.push(source.substring(lastIndex, nodeEnd))
const bolded =
source.substring(start, nodeStart) +
chalk.bold(parts.join('')) +
source.substring(nodeEnd, end)
const lines = bolded.split(/\r\n?|\n/gm)
let line = startLine
const result = lines
.map((l) => `${String(line++).padStart(lineNumberLength, ' ')} | ${l}`)
.join('\n')
return captureRanges.length
? `${' '.repeat(lineNumberLength)} | ${captureRanges
.map(({ key, color }) => color(key))
.join(' ')}\n${result}`
: result
}
export default function formatMatches(backend, source, matches) {
const result = []
const lineCount = countLines(source)
for (let i = 0; i < matches.length; i++) {
const match = matches[i]
if (i > 0) result.push(' '.repeat(String(lineCount).length + 1) + '|')
result.push(formatMatch(backend, source, match, lineCount))
}
return result.join('\n')
}
export function formatIpcMatches(source, matches) {
return formatMatches(
{
location: (node) => node.location,
},
source,
matches
)
} //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjaGFsayIsImNvdW50TGluZXMiLCJjYXB0dXJlQ29sb3JzIiwiZ3JlZW4iLCJ5ZWxsb3ciLCJibHVlIiwiY3lhbiIsIm1hZ2VudGEiLCJyZWQiLCJkZXJpdmVMaW5lQW5kQ29sdW1uIiwic291cmNlIiwiaW5kZXgiLCJyeCIsImxhc3RJbmRleCIsImxpbmUiLCJtYXRjaCIsImV4ZWMiLCJzdGFydExpbmUiLCJzdGFydENvbHVtbiIsImZvcm1hdE1hdGNoIiwiYmFja2VuZCIsImxpbmVDb3VudCIsImxpbmVOdW1iZXJMZW5ndGgiLCJTdHJpbmciLCJsZW5ndGgiLCJ0eXBlIiwibm9kZXMiLCJyZXBlYXQiLCJzdGFydCIsIm5vZGVTdGFydCIsImxvY2F0aW9uIiwiZW5kIiwibm9kZUVuZCIsIkVycm9yIiwic3RhcnRDb2wiLCJjYXB0dXJlcyIsImFycmF5Q2FwdHVyZXMiLCJlb2xSZWdleCIsImVvbE1hdGNoIiwiY2FwdHVyZUNvbG9yIiwiY2FwdHVyZVJhbmdlcyIsImtleSIsIm5vZGUiLCJPYmplY3QiLCJlbnRyaWVzIiwicHVzaCIsImNvbG9yIiwiZ3JheSIsImZpcnN0IiwibGFzdCIsInNvcnQiLCJhIiwiYiIsInBhcnRzIiwic3Vic3RyaW5nIiwiYm9sZGVkIiwiYm9sZCIsImpvaW4iLCJsaW5lcyIsInNwbGl0IiwicmVzdWx0IiwibWFwIiwibCIsInBhZFN0YXJ0IiwiZm9ybWF0TWF0Y2hlcyIsIm1hdGNoZXMiLCJpIiwiZm9ybWF0SXBjTWF0Y2hlcyJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL2Zvcm1hdE1hdGNoZXMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNoYWxrIGZyb20gJ2NoYWxrJ1xuaW1wb3J0IGNvdW50TGluZXMgZnJvbSAnLi9jb3VudExpbmVzJ1xuaW1wb3J0IHsgTWF0Y2ggfSBmcm9tICcuLi9maW5kJ1xuaW1wb3J0IHsgTG9jYXRpb24sIE5vZGUgfSBmcm9tICcuLi90eXBlcydcbmltcG9ydCB7IElwY01hdGNoLCBJcGNOb2RlIH0gZnJvbSAnLi4vbm9kZS9pcGMnXG5cbmNvbnN0IGNhcHR1cmVDb2xvcnMgPSBbXG4gIGNoYWxrLmdyZWVuLFxuICBjaGFsay55ZWxsb3csXG4gIGNoYWxrLmJsdWUsXG4gIGNoYWxrLmN5YW4sXG4gIGNoYWxrLm1hZ2VudGEsXG4gIGNoYWxrLnJlZCxcbl1cblxuZnVuY3Rpb24gZGVyaXZlTGluZUFuZENvbHVtbihcbiAgc291cmNlOiBzdHJpbmcsXG4gIGluZGV4OiBudW1iZXJcbik6IHsgc3RhcnRMaW5lOiBudW1iZXI7IHN0YXJ0Q29sdW1uOiBudW1iZXIgfSB7XG4gIGNvbnN0IHJ4ID0gL1xcclxcbj98XFxuL2dtXG5cbiAgbGV0IGxhc3RJbmRleCA9IDBcbiAgbGV0IGxpbmUgPSAxXG5cbiAgd2hpbGUgKGxhc3RJbmRleCA8IGluZGV4KSB7XG4gICAgcngubGFzdEluZGV4ID0gbGFzdEluZGV4ICsgMVxuICAgIGNvbnN0IG1hdGNoID0gcnguZXhlYyhzb3VyY2UpXG4gICAgaWYgKCFtYXRjaCkgYnJlYWtcbiAgICBsaW5lKytcbiAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleFxuICB9XG4gIHJldHVybiB7IHN0YXJ0TGluZTogbGluZSwgc3RhcnRDb2x1bW46IGluZGV4IC0gbGFzdEluZGV4IH1cbn1cblxuaW50ZXJmYWNlIEJhY2tlbmQge1xuICBsb2NhdGlvbjogKG5vZGU6IE5vZGUgfCBJcGNOb2RlKSA9PiBMb2NhdGlvblxufVxuXG5mdW5jdGlvbiBmb3JtYXRNYXRjaChcbiAgYmFja2VuZDogQmFja2VuZCxcbiAgc291cmNlOiBzdHJpbmcsXG4gIG1hdGNoOiBNYXRjaCB8IElwY01hdGNoLFxuICBsaW5lQ291bnQ6IG51bWJlclxuKTogc3RyaW5nIHtcbiAgY29uc3QgbGluZU51bWJlckxlbmd0aCA9IFN0cmluZyhsaW5lQ291bnQpLmxlbmd0aFxuXG4gIGlmIChtYXRjaC50eXBlID09PSAnbm9kZXMnICYmICFtYXRjaC5ub2Rlcy5sZW5ndGgpXG4gICAgcmV0dXJuIGAkeycgJy5yZXBlYXQobGluZU51bWJlckxlbmd0aCl9IHwgKHplcm8gc3RhdGVtZW50cylgXG4gIGNvbnN0IHsgc3RhcnQ6IG5vZGVTdGFydCB9ID0gYmFja2VuZC5sb2NhdGlvbihtYXRjaC5ub2Rlc1swXSlcbiAgY29uc3QgeyBlbmQ6IG5vZGVFbmQgfSA9IGJhY2tlbmQubG9jYXRpb24obWF0Y2gubm9kZXNbbWF0Y2gubm9kZXMubGVuZ3RoIC0gMV0pXG4gIGlmIChub2RlU3RhcnQgPT0gbnVsbCB8fCBub2RlRW5kID09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ZhaWxlZCB0byBnZXQgbWF0Y2ggbG9jYXRpb24nKVxuICB9XG5cbiAgbGV0IHsgc3RhcnRMaW5lLCBzdGFydENvbHVtbjogc3RhcnRDb2wgfSA9IGJhY2tlbmQubG9jYXRpb24obWF0Y2gubm9kZXNbMF0pXG5cbiAgaWYgKHN0YXJ0TGluZSA9PSBudWxsIHx8IHN0YXJ0Q29sID09IG51bGwpIHtcbiAgICA7KHsgc3RhcnRMaW5lLCBzdGFydENvbHVtbjogc3RhcnRDb2wgfSA9IGRlcml2ZUxpbmVBbmRDb2x1bW4oXG4gICAgICBzb3VyY2UsXG4gICAgICBub2RlU3RhcnRcbiAgICApKVxuICB9XG5cbiAgY29uc3QgeyBjYXB0dXJlcywgYXJyYXlDYXB0dXJlcyB9ID0gbWF0Y2hcbiAgY29uc3Qgc3RhcnQgPSBub2RlU3RhcnQgLSBzdGFydENvbFxuICBjb25zdCBlb2xSZWdleCA9IC9cXHJcXG4/fFxcbi9nbVxuICBlb2xSZWdleC5sYXN0SW5kZXggPSBub2RlRW5kXG4gIGNvbnN0IGVvbE1hdGNoID0gZW9sUmVnZXguZXhlYyhzb3VyY2UpXG4gIGNvbnN0IGVuZCA9IGVvbE1hdGNoID8gZW9sTWF0Y2guaW5kZXggOiBub2RlRW5kXG5cbiAgbGV0IGNhcHR1cmVDb2xvciA9IDBcblxuICBjb25zdCBjYXB0dXJlUmFuZ2VzID0gW11cbiAgaWYgKGNhcHR1cmVzKSB7XG4gICAgZm9yIChjb25zdCBba2V5LCBub2RlXSBvZiBPYmplY3QuZW50cmllcyhjYXB0dXJlcykpIHtcbiAgICAgIGNvbnN0IHsgc3RhcnQsIGVuZCB9ID0gYmFja2VuZC5sb2NhdGlvbihub2RlKVxuICAgICAgaWYgKHN0YXJ0ICE9IG51bGwgJiYgZW5kICE9IG51bGwpIHtcbiAgICAgICAgY2FwdHVyZVJhbmdlcy5wdXNoKHtcbiAgICAgICAgICBrZXksXG4gICAgICAgICAgc3RhcnQsXG4gICAgICAgICAgZW5kLFxuICAgICAgICAgIGNvbG9yOiBjYXB0dXJlQ29sb3JzW2NhcHR1cmVDb2xvcisrXSB8fCBjaGFsay5ncmF5LFxuICAgICAgICB9KVxuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAoYXJyYXlDYXB0dXJlcykge1xuICAgIGZvciAoY29uc3QgW2tleSwgbm9kZXNdIG9mIE9iamVjdC5lbnRyaWVzKGFycmF5Q2FwdHVyZXMpKSB7XG4gICAgICBjb25zdCBmaXJzdCA9IG5vZGVzWzBdXG4gICAgICBjb25zdCBsYXN0ID0gbm9kZXNbbm9kZXMubGVuZ3RoIC0gMV1cbiAgICAgIGlmICghZmlyc3QgfHwgIWxhc3QpIGNvbnRpbnVlXG4gICAgICBjb25zdCB7IHN0YXJ0IH0gPSBiYWNrZW5kLmxvY2F0aW9uKGZpcnN0KVxuICAgICAgY29uc3QgeyBlbmQgfSA9IGJhY2tlbmQubG9jYXRpb24obGFzdClcbiAgICAgIGlmIChzdGFydCAhPSBudWxsICYmIGVuZCAhPSBudWxsKSB7XG4gICAgICAgIGNhcHR1cmVSYW5nZXMucHVzaCh7XG4gICAgICAgICAga2V5LFxuICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgIGVuZCxcbiAgICAgICAgICBjb2xvcjogY2FwdHVyZUNvbG9yc1tjYXB0dXJlQ29sb3IrK10gfHwgY2hhbGsuZ3JheSxcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjYXB0dXJlUmFuZ2VzLnNvcnQoKGEsIGIpID0+IGEuc3RhcnQgLSBiLnN0YXJ0KVxuXG4gIGxldCBsYXN0SW5kZXggPSBub2RlU3RhcnRcbiAgY29uc3QgcGFydHMgPSBbXVxuICBmb3IgKGNvbnN0IHsgc3RhcnQsIGVuZCwgY29sb3IgfSBvZiBjYXB0dXJlUmFuZ2VzKSB7XG4gICAgaWYgKHN0YXJ0IDwgbGFzdEluZGV4KSBjb250aW51ZVxuICAgIHBhcnRzLnB1c2goc291cmNlLnN1YnN0cmluZyhsYXN0SW5kZXgsIHN0YXJ0KSlcbiAgICBwYXJ0cy5wdXNoKGNvbG9yKHNvdXJjZS5zdWJzdHJpbmcoc3RhcnQsIGVuZCkpKVxuICAgIGxhc3RJbmRleCA9IGVuZFxuICB9XG4gIHBhcnRzLnB1c2goc291cmNlLnN1YnN0cmluZyhsYXN0SW5kZXgsIG5vZGVFbmQpKVxuXG4gIGNvbnN0IGJvbGRlZCA9XG4gICAgc291cmNlLnN1YnN0cmluZyhzdGFydCwgbm9kZVN0YXJ0KSArXG4gICAgY2hhbGsuYm9sZChwYXJ0cy5qb2luKCcnKSkgK1xuICAgIHNvdXJjZS5zdWJzdHJpbmcobm9kZUVuZCwgZW5kKVxuXG4gIGNvbnN0IGxpbmVzID0gYm9sZGVkLnNwbGl0KC9cXHJcXG4/fFxcbi9nbSlcblxuICBsZXQgbGluZSA9IHN0YXJ0TGluZVxuICBjb25zdCByZXN1bHQgPSBsaW5lc1xuICAgIC5tYXAoKGwpID0+IGAke1N0cmluZyhsaW5lKyspLnBhZFN0YXJ0KGxpbmVOdW1iZXJMZW5ndGgsICcgJyl9IHwgJHtsfWApXG4gICAgLmpvaW4oJ1xcbicpXG5cbiAgcmV0dXJuIGNhcHR1cmVSYW5nZXMubGVuZ3RoXG4gICAgPyBgJHsnICcucmVwZWF0KGxpbmVOdW1iZXJMZW5ndGgpfSB8ICR7Y2FwdHVyZVJhbmdlc1xuICAgICAgICAubWFwKCh7IGtleSwgY29sb3IgfSkgPT4gY29sb3Ioa2V5KSlcbiAgICAgICAgLmpvaW4oJyAnKX1cXG4ke3Jlc3VsdH1gXG4gICAgOiByZXN1bHRcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gZm9ybWF0TWF0Y2hlcyhcbiAgYmFja2VuZDogQmFja2VuZCxcbiAgc291cmNlOiBzdHJpbmcsXG4gIG1hdGNoZXM6IHJlYWRvbmx5IE1hdGNoW10gfCByZWFkb25seSBJcGNNYXRjaFtdXG4pOiBzdHJpbmcge1xuICBjb25zdCByZXN1bHQgPSBbXVxuICBjb25zdCBsaW5lQ291bnQgPSBjb3VudExpbmVzKHNvdXJjZSlcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXRjaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgbWF0Y2ggPSBtYXRjaGVzW2ldXG4gICAgaWYgKGkgPiAwKSByZXN1bHQucHVzaCgnICcucmVwZWF0KFN0cmluZyhsaW5lQ291bnQpLmxlbmd0aCArIDEpICsgJ3wnKVxuICAgIHJlc3VsdC5wdXNoKGZvcm1hdE1hdGNoKGJhY2tlbmQsIHNvdXJjZSwgbWF0Y2gsIGxpbmVDb3VudCkpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdC5qb2luKCdcXG4nKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0SXBjTWF0Y2hlcyhcbiAgc291cmNlOiBzdHJpbmcsXG4gIG1hdGNoZXM6IHJlYWRvbmx5IElwY01hdGNoW11cbik6IHN0cmluZyB7XG4gIHJldHVybiBmb3JtYXRNYXRjaGVzKFxuICAgIHsgbG9jYXRpb246IChub2RlOiBhbnkpID0+IG5vZGUubG9jYXRpb24gfSxcbiAgICBzb3VyY2UsXG4gICAgbWF0Y2hlc1xuICApXG59XG4iXSwibWFwcGluZ3MiOiJBQUFBLE9BQU9BLEtBQVAsTUFBa0IsT0FBbEI7QUFDQSxPQUFPQyxVQUFQLE1BQXVCLGNBQXZCOzs7OztBQUtBLE1BQU1DLGFBQWEsR0FBRztBQUNwQkYsS0FBSyxDQUFDRyxLQURjO0FBRXBCSCxLQUFLLENBQUNJLE1BRmM7QUFHcEJKLEtBQUssQ0FBQ0ssSUFIYztBQUlwQkwsS0FBSyxDQUFDTSxJQUpjO0FBS3BCTixLQUFLLENBQUNPLE9BTGM7QUFNcEJQLEtBQUssQ0FBQ1EsR0FOYyxDQUF0Qjs7O0FBU0EsU0FBU0MsbUJBQVQ7QUFDRUMsTUFERjtBQUVFQyxLQUZGO0FBRzhDO0VBQzVDLE1BQU1DLEVBQUUsR0FBRyxZQUFYOztFQUVB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