UNPKG

astx

Version:

super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring

287 lines (252 loc) 29.4 kB
import { mapValues } from 'lodash-es' import compileMatcher, { mergeCaptures } from './compileMatcher/index.mjs' import ensureArray from './util/ensureArray.mjs' import forEachNode from './util/forEachNode.mjs' export function convertWithCaptures(matches) { return mergeCaptures( ...ensureArray(matches).map( ({ pathCaptures, arrayPathCaptures, stringCaptures }) => ({ captures: pathCaptures, arrayCaptures: arrayPathCaptures, stringCaptures, }) ) ) } export function createMatch(paths, result) { var _paths$ if (!result) { throw new Error('result must be defined') } const { captures, arrayCaptures, stringCaptures } = result const match = Array.isArray(paths) ? { type: 'nodes', node: (_paths$ = paths[0]) === null || _paths$ === void 0 ? void 0 : _paths$.node, path: paths[0], nodes: paths.map((p) => p.node), paths, } : { type: 'node', node: paths.node, path: paths, nodes: [paths.node], paths: [paths], } if (captures) { match.pathCaptures = captures match.captures = mapValues(captures, (path) => path.node) } if (arrayCaptures) { match.arrayPathCaptures = arrayCaptures match.arrayCaptures = mapValues(arrayCaptures, (paths) => paths.map((path) => path.node) ) } if (stringCaptures) match.stringCaptures = stringCaptures return match } export default function find(paths, pattern, options) { const t = options.backend.t const n = t.namedTypes if (Array.isArray(pattern) && pattern.length === 1) pattern = pattern[0] if (Array.isArray(pattern)) { if (!n.Statement.check(pattern[0].value)) { throw new Error(`pattern array must be an array of statements`) } return findStatements(paths, pattern, options) } const matcher = compileMatcher(pattern, options) const matches = [] const nodeTypes = ensureArray(matcher.nodeType || 'Node') forEachNode(t, ensureArray(paths), nodeTypes, (path) => { var _options$matchSoFar const result = matcher.match( path, (_options$matchSoFar = options === null || options === void 0 ? void 0 : options.matchSoFar) !== null && _options$matchSoFar !== void 0 ? _options$matchSoFar : null ) if (result) matches.push(createMatch(path, result)) }) return matches } function findStatements(paths, pattern, options) { var _options$matchSoFar2 const t = options.backend.t const matchers = pattern.map((queryElem) => compileMatcher(queryElem, options) ) const firstNonArrayCaptureIndex = matchers.findIndex( (m) => !m.arrayPlaceholder ) if (firstNonArrayCaptureIndex < 0) { throw new Error( `pattern would match every single array of statements, this is unsupported` ) } function remainingElements(matcherIndex) { let count = 0 for (let i = matcherIndex; i < matchers.length; i++) { if (!matchers[i].arrayPlaceholder) count++ } return count } function matchElem(paths, sliceStart, arrayIndex, matcherIndex, matchSoFar) { if (arrayIndex === paths.length || matcherIndex === matchers.length) { return remainingElements(matcherIndex) === 0 ? [matchSoFar || {}, [arrayIndex, arrayIndex]] : null } const matcher = matchers[matcherIndex] const { arrayPlaceholder } = matcher if (arrayPlaceholder) { if (matcherIndex === matchers.length - 1) { return [ mergeCaptures(matchSoFar, { arrayCaptures: { [arrayPlaceholder]: paths.slice(sliceStart), }, }), [sliceStart, paths.length], ] } return matchElem( paths, sliceStart, arrayIndex, matcherIndex + 1, matchSoFar ) } else { var _matchers const origMatchSoFar = matchSoFar const prevArrayPlaceholder = (_matchers = matchers[matcherIndex - 1]) === null || _matchers === void 0 ? void 0 : _matchers.arrayPlaceholder const end = prevArrayPlaceholder && matcherIndex !== firstNonArrayCaptureIndex ? paths.length - remainingElements(matcherIndex + 1) : arrayIndex + 1 for (let i = arrayIndex; i < end; i++) { matchSoFar = matcher.match(paths[i], origMatchSoFar) if (!matchSoFar) continue if (prevArrayPlaceholder) { matchSoFar = mergeCaptures(matchSoFar, { arrayCaptures: { [prevArrayPlaceholder]: paths.slice(sliceStart, i), }, }) } const restMatch = matchElem( paths, i + 1, i + 1, matcherIndex + 1, matchSoFar ) if (restMatch) return [restMatch[0], [i, restMatch[1][1]]] } } return null } const blocks = [] forEachNode(t, ensureArray(paths), ['Block'], (path) => { blocks.push(path) }) blocks.reverse() const matches = [] const initialMatch = (_options$matchSoFar2 = options === null || options === void 0 ? void 0 : options.matchSoFar) !== null && _options$matchSoFar2 !== void 0 ? _options$matchSoFar2 : null for (const block of blocks) { const body = block.get('body').filter(() => true) const end = body.length - remainingElements(firstNonArrayCaptureIndex + 1) let sliceStart = 0 for (let arrayIndex = 0; arrayIndex < end; arrayIndex++) { const match = matchElem( body, sliceStart, arrayIndex, firstNonArrayCaptureIndex, initialMatch ) if (match) { var _result2, _result3, _result4 let result = match[0] const start = firstNonArrayCaptureIndex > 0 ? 0 : match[1][0] const [, end] = match[1] // make sure all * captures are present in results // (if there are more than one adjacent *, all captured paths will be in the // last one and the rest will be empty) for (const matcher of matchers) { var _result, _result$arrayCaptures const { arrayPlaceholder } = matcher if (!arrayPlaceholder) continue if ( !( (_result = result) !== null && _result !== void 0 && (_result$arrayCaptures = _result.arrayCaptures) !== null && _result$arrayCaptures !== void 0 && _result$arrayCaptures[arrayPlaceholder] ) ) result = mergeCaptures(result, { arrayCaptures: { [arrayPlaceholder]: [], }, }) } const paths = body.slice(start, end) const finalMatch = { type: 'nodes', path: paths[0], node: paths[0].node, paths, nodes: paths.map((p) => p.node), } if ( (_result2 = result) !== null && _result2 !== void 0 && _result2.captures ) { finalMatch.pathCaptures = result.captures finalMatch.captures = mapValues(result.captures, (p) => p.node) } if ( (_result3 = result) !== null && _result3 !== void 0 && _result3.arrayCaptures ) { finalMatch.arrayPathCaptures = result.arrayCaptures finalMatch.arrayCaptures = mapValues(result.arrayCaptures, (paths) => paths.map((p) => p.node) ) } if ( (_result4 = result) !== null && _result4 !== void 0 && _result4.stringCaptures ) { finalMatch.stringCaptures = result.stringCaptures } matches.push(finalMatch) // prevent overlapping matches sliceStart = end arrayIndex = end - 1 } } } return matches } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJtYXBWYWx1ZXMiLCJjb21waWxlTWF0Y2hlciIsIm1lcmdlQ2FwdHVyZXMiLCJlbnN1cmVBcnJheSIsImZvckVhY2hOb2RlIiwiY29udmVydFdpdGhDYXB0dXJlcyIsIm1hdGNoZXMiLCJtYXAiLCJwYXRoQ2FwdHVyZXMiLCJhcnJheVBhdGhDYXB0dXJlcyIsInN0cmluZ0NhcHR1cmVzIiwiY2FwdHVyZXMiLCJhcnJheUNhcHR1cmVzIiwiY3JlYXRlTWF0Y2giLCJwYXRocyIsInJlc3VsdCIsIkVycm9yIiwibWF0Y2giLCJBcnJheSIsImlzQXJyYXkiLCJ0eXBlIiwibm9kZSIsInBhdGgiLCJub2RlcyIsInAiLCJmaW5kIiwicGF0dGVybiIsIm9wdGlvbnMiLCJ0IiwiYmFja2VuZCIsIm4iLCJuYW1lZFR5cGVzIiwibGVuZ3RoIiwiU3RhdGVtZW50IiwiY2hlY2siLCJ2YWx1ZSIsImZpbmRTdGF0ZW1lbnRzIiwibWF0Y2hlciIsIm5vZGVUeXBlcyIsIm5vZGVUeXBlIiwibWF0Y2hTb0ZhciIsInB1c2giLCJtYXRjaGVycyIsInF1ZXJ5RWxlbSIsImZpcnN0Tm9uQXJyYXlDYXB0dXJlSW5kZXgiLCJmaW5kSW5kZXgiLCJtIiwiYXJyYXlQbGFjZWhvbGRlciIsInJlbWFpbmluZ0VsZW1lbnRzIiwibWF0Y2hlckluZGV4IiwiY291bnQiLCJpIiwibWF0Y2hFbGVtIiwic2xpY2VTdGFydCIsImFycmF5SW5kZXgiLCJzbGljZSIsIm9yaWdNYXRjaFNvRmFyIiwicHJldkFycmF5UGxhY2Vob2xkZXIiLCJlbmQiLCJyZXN0TWF0Y2giLCJibG9ja3MiLCJyZXZlcnNlIiwiaW5pdGlhbE1hdGNoIiwiYmxvY2siLCJib2R5IiwiZ2V0IiwiZmlsdGVyIiwic3RhcnQiLCJmaW5hbE1hdGNoIl0sInNvdXJjZXMiOlsiLi4vc3JjL2ZpbmQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTm9kZVR5cGUsIE5vZGVQYXRoLCBOb2RlLCBTdGF0ZW1lbnQsIEJsb2NrIH0gZnJvbSAnLi90eXBlcydcbmltcG9ydCB7IG1hcFZhbHVlcyB9IGZyb20gJ2xvZGFzaCdcbmltcG9ydCBjb21waWxlTWF0Y2hlciwge1xuICBDb21waWxlZE1hdGNoZXIsXG4gIE1hdGNoUmVzdWx0LFxuICBtZXJnZUNhcHR1cmVzLFxufSBmcm9tICcuL2NvbXBpbGVNYXRjaGVyJ1xuaW1wb3J0IHsgQmFja2VuZCB9IGZyb20gJy4vYmFja2VuZC9CYWNrZW5kJ1xuaW1wb3J0IGVuc3VyZUFycmF5IGZyb20gJy4vdXRpbC9lbnN1cmVBcnJheSdcbmltcG9ydCBmb3JFYWNoTm9kZSBmcm9tICcuL3V0aWwvZm9yRWFjaE5vZGUnXG5cbmV4cG9ydCB0eXBlIE1hdGNoID0ge1xuICB0eXBlOiAnbm9kZScgfCAnbm9kZXMnXG4gIHBhdGg6IE5vZGVQYXRoXG4gIG5vZGU6IE5vZGVcbiAgcGF0aHM6IE5vZGVQYXRoW11cbiAgbm9kZXM6IE5vZGVbXVxuICBwYXRoQ2FwdHVyZXM/OiBSZWNvcmQ8c3RyaW5nLCBOb2RlUGF0aD5cbiAgY2FwdHVyZXM/OiBSZWNvcmQ8c3RyaW5nLCBOb2RlPlxuICBhcnJheVBhdGhDYXB0dXJlcz86IFJlY29yZDxzdHJpbmcsIE5vZGVQYXRoW10+XG4gIGFycmF5Q2FwdHVyZXM/OiBSZWNvcmQ8c3RyaW5nLCBOb2RlW10+XG4gIHN0cmluZ0NhcHR1cmVzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxufVxuXG5leHBvcnQgdHlwZSBGaW5kT3B0aW9ucyA9IHtcbiAgYmFja2VuZDogQmFja2VuZFxuICB3aGVyZT86IHsgW2NhcHR1cmVOYW1lOiBzdHJpbmddOiAocGF0aDogTm9kZVBhdGgpID0+IGJvb2xlYW4gfVxuICBtYXRjaFNvRmFyPzogTWF0Y2hSZXN1bHRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRXaXRoQ2FwdHVyZXMobWF0Y2hlczogTWF0Y2ggfCBNYXRjaFtdKTogTWF0Y2hSZXN1bHQge1xuICByZXR1cm4gbWVyZ2VDYXB0dXJlcyhcbiAgICAuLi5lbnN1cmVBcnJheShtYXRjaGVzKS5tYXAoXG4gICAgICAoeyBwYXRoQ2FwdHVyZXMsIGFycmF5UGF0aENhcHR1cmVzLCBzdHJpbmdDYXB0dXJlcyB9KTogTWF0Y2hSZXN1bHQgPT4gKHtcbiAgICAgICAgY2FwdHVyZXM6IHBhdGhDYXB0dXJlcyxcbiAgICAgICAgYXJyYXlDYXB0dXJlczogYXJyYXlQYXRoQ2FwdHVyZXMsXG4gICAgICAgIHN0cmluZ0NhcHR1cmVzLFxuICAgICAgfSlcbiAgICApXG4gIClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU1hdGNoKFxuICBwYXRoczogTm9kZVBhdGggfCBOb2RlUGF0aFtdLFxuICByZXN1bHQ6IE1hdGNoUmVzdWx0XG4pOiBNYXRjaCB7XG4gIGlmICghcmVzdWx0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdyZXN1bHQgbXVzdCBiZSBkZWZpbmVkJylcbiAgfVxuICBjb25zdCB7IGNhcHR1cmVzLCBhcnJheUNhcHR1cmVzLCBzdHJpbmdDYXB0dXJlcyB9ID0gcmVzdWx0XG4gIGNvbnN0IG1hdGNoOiBNYXRjaCA9IEFycmF5LmlzQXJyYXkocGF0aHMpXG4gICAgPyB7XG4gICAgICAgIHR5cGU6ICdub2RlcycsXG4gICAgICAgIG5vZGU6IHBhdGhzWzBdPy5ub2RlLFxuICAgICAgICBwYXRoOiBwYXRoc1swXSxcbiAgICAgICAgbm9kZXM6IHBhdGhzLm1hcCgocCkgPT4gcC5ub2RlKSxcbiAgICAgICAgcGF0aHMsXG4gICAgICB9XG4gICAgOiB7XG4gICAgICAgIHR5cGU6ICdub2RlJyxcbiAgICAgICAgbm9kZTogcGF0aHMubm9kZSxcbiAgICAgICAgcGF0aDogcGF0aHMsXG4gICAgICAgIG5vZGVzOiBbcGF0aHMubm9kZV0sXG4gICAgICAgIHBhdGhzOiBbcGF0aHNdLFxuICAgICAgfVxuICBpZiAoY2FwdHVyZXMpIHtcbiAgICBtYXRjaC5wYXRoQ2FwdHVyZXMgPSBjYXB0dXJlc1xuICAgIG1hdGNoLmNhcHR1cmVzID0gbWFwVmFsdWVzKGNhcHR1cmVzLCAocGF0aDogTm9kZVBhdGgpID0+IHBhdGgubm9kZSlcbiAgfVxuICBpZiAoYXJyYXlDYXB0dXJlcykge1xuICAgIG1hdGNoLmFycmF5UGF0aENhcHR1cmVzID0gYXJyYXlDYXB0dXJlc1xuICAgIG1hdGNoLmFycmF5Q2FwdHVyZXMgPSBtYXBWYWx1ZXMoYXJyYXlDYXB0dXJlcywgKHBhdGhzOiBOb2RlUGF0aFtdKSA9PlxuICAgICAgcGF0aHMubWFwKChwYXRoKSA9PiBwYXRoLm5vZGUpXG4gICAgKVxuICB9XG4gIGlmIChzdHJpbmdDYXB0dXJlcykgbWF0Y2guc3RyaW5nQ2FwdHVyZXMgPSBzdHJpbmdDYXB0dXJlc1xuICByZXR1cm4gbWF0Y2hcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gZmluZChcbiAgcGF0aHM6IE5vZGVQYXRoIHwgcmVhZG9ubHkgTm9kZVBhdGhbXSxcbiAgcGF0dGVybjogTm9kZVBhdGggfCByZWFkb25seSBOb2RlUGF0aFtdLFxuICBvcHRpb25zOiBGaW5kT3B0aW9uc1xuKTogTWF0Y2hbXSB7XG4gIGNvbnN0IHQgPSBvcHRpb25zLmJhY2tlbmQudFxuICBjb25zdCBuID0gdC5uYW1lZFR5cGVzXG4gIGlmIChBcnJheS5pc0FycmF5KHBhdHRlcm4pICYmIHBhdHRlcm4ubGVuZ3RoID09PSAxKSBwYXR0ZXJuID0gcGF0dGVyblswXVxuICBpZiAoQXJyYXkuaXNBcnJheShwYXR0ZXJuKSkge1xuICAgIGlmICghbi5TdGF0ZW1lbnQuY2hlY2socGF0dGVyblswXS52YWx1ZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgcGF0dGVybiBhcnJheSBtdXN0IGJlIGFuIGFycmF5IG9mIHN0YXRlbWVudHNgKVxuICAgIH1cbiAgICByZXR1cm4gZmluZFN0YXRlbWVudHMoXG4gICAgICBwYXRocyxcbiAgICAgIHBhdHRlcm4gYXMgTm9kZVBhdGg8U3RhdGVtZW50LCBTdGF0ZW1lbnQ+W10sXG4gICAgICBvcHRpb25zXG4gICAgKVxuICB9XG5cbiAgY29uc3QgbWF0Y2hlciA9IGNvbXBpbGVNYXRjaGVyKHBhdHRlcm4gYXMgTm9kZVBhdGgsIG9wdGlvbnMpXG5cbiAgY29uc3QgbWF0Y2hlczogQXJyYXk8TWF0Y2g+ID0gW11cblxuICBjb25zdCBub2RlVHlwZXM6IHJlYWRvbmx5IE5vZGVUeXBlW10gPSBlbnN1cmVBcnJheShtYXRjaGVyLm5vZGVUeXBlIHx8ICdOb2RlJylcblxuICBmb3JFYWNoTm9kZSh0LCBlbnN1cmVBcnJheShwYXRocyksIG5vZGVUeXBlcywgKHBhdGg6IE5vZGVQYXRoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gbWF0Y2hlci5tYXRjaChwYXRoLCBvcHRpb25zPy5tYXRjaFNvRmFyID8/IG51bGwpXG4gICAgaWYgKHJlc3VsdCkgbWF0Y2hlcy5wdXNoKGNyZWF0ZU1hdGNoKHBhdGgsIHJlc3VsdCkpXG4gIH0pXG5cbiAgcmV0dXJuIG1hdGNoZXNcbn1cblxuZnVuY3Rpb24gZmluZFN0YXRlbWVudHMoXG4gIHBhdGhzOiBOb2RlUGF0aCB8IHJlYWRvbmx5IE5vZGVQYXRoW10sXG4gIHBhdHRlcm46IHJlYWRvbmx5IE5vZGVQYXRoPFN0YXRlbWVudCwgU3RhdGVtZW50PltdLFxuICBvcHRpb25zOiBGaW5kT3B0aW9uc1xuKTogTWF0Y2hbXSB7XG4gIGNvbnN0IHQgPSBvcHRpb25zLmJhY2tlbmQudFxuXG4gIGNvbnN0IG1hdGNoZXJzOiBDb21waWxlZE1hdGNoZXJbXSA9IHBhdHRlcm4ubWFwKChxdWVyeUVsZW0pID0+XG4gICAgY29tcGlsZU1hdGNoZXIocXVlcnlFbGVtLCBvcHRpb25zKVxuICApXG5cbiAgY29uc3QgZmlyc3ROb25BcnJheUNhcHR1cmVJbmRleCA9IG1hdGNoZXJzLmZpbmRJbmRleChcbiAgICAobSkgPT4gIW0uYXJyYXlQbGFjZWhvbGRlclxuICApXG5cbiAgaWYgKGZpcnN0Tm9uQXJyYXlDYXB0dXJlSW5kZXggPCAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYHBhdHRlcm4gd291bGQgbWF0Y2ggZXZlcnkgc2luZ2xlIGFycmF5IG9mIHN0YXRlbWVudHMsIHRoaXMgaXMgdW5zdXBwb3J0ZWRgXG4gICAgKVxuICB9XG5cbiAgZnVuY3Rpb24gcmVtYWluaW5nRWxlbWVudHMobWF0Y2hlckluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCBjb3VudCA9IDBcbiAgICBmb3IgKGxldCBpID0gbWF0Y2hlckluZGV4OyBpIDwgbWF0Y2hlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICghbWF0Y2hlcnNbaV0uYXJyYXlQbGFjZWhvbGRlcikgY291bnQrK1xuICAgIH1cbiAgICByZXR1cm4gY291bnRcbiAgfVxuXG4gIGZ1bmN0aW9uIG1hdGNoRWxlbShcbiAgICBwYXRoczogTm9kZVBhdGg8U3RhdGVtZW50PltdLFxuICAgIHNsaWNlU3RhcnQ6IG51bWJlcixcbiAgICBhcnJheUluZGV4OiBudW1iZXIsXG4gICAgbWF0Y2hlckluZGV4OiBudW1iZXIsXG4gICAgbWF0Y2hTb0ZhcjogTWF0Y2hSZXN1bHRcbiAgKTogW01hdGNoUmVzdWx0LCBbbnVtYmVyLCBudW1iZXJdXSB8IG51bGwge1xuICAgIGlmIChhcnJheUluZGV4ID09PSBwYXRocy5sZW5ndGggfHwgbWF0Y2hlckluZGV4ID09PSBtYXRjaGVycy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiByZW1haW5pbmdFbGVtZW50cyhtYXRjaGVySW5kZXgpID09PSAwXG4gICAgICAgID8gW21hdGNoU29GYXIgfHwge30sIFthcnJheUluZGV4LCBhcnJheUluZGV4XV1cbiAgICAgICAgOiBudWxsXG4gICAgfVxuXG4gICAgY29uc3QgbWF0Y2hlciA9IG1hdGNoZXJzW21hdGNoZXJJbmRleF1cbiAgICBjb25zdCB7IGFycmF5UGxhY2Vob2xkZXIgfSA9IG1hdGNoZXJcbiAgICBpZiAoYXJyYXlQbGFjZWhvbGRlcikge1xuICAgICAgaWYgKG1hdGNoZXJJbmRleCA9PT0gbWF0Y2hlcnMubGVuZ3RoIC0gMSkge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIG1lcmdlQ2FwdHVyZXMobWF0Y2hTb0Zhciwge1xuICAgICAgICAgICAgYXJyYXlDYXB0dXJlczoge1xuICAgICAgICAgICAgICBbYXJyYXlQbGFjZWhvbGRlcl06IHBhdGhzLnNsaWNlKHNsaWNlU3RhcnQpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBbc2xpY2VTdGFydCwgcGF0aHMubGVuZ3RoXSxcbiAgICAgICAgXVxuICAgICAgfVxuICAgICAgcmV0dXJuIG1hdGNoRWxlbShcbiAgICAgICAgcGF0aHMsXG4gICAgICAgIHNsaWNlU3RhcnQsXG4gICAgICAgIGFycmF5SW5kZXgsXG4gICAgICAgIG1hdGNoZXJJbmRleCArIDEsXG4gICAgICAgIG1hdGNoU29GYXJcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgb3JpZ01hdGNoU29GYXIgPSBtYXRjaFNvRmFyXG4gICAgICBjb25zdCBwcmV2QXJyYXlQbGFjZWhvbGRlciA9IG1hdGNoZXJzW21hdGNoZXJJbmRleCAtIDFdPy5hcnJheVBsYWNlaG9sZGVyXG4gICAgICBjb25zdCBlbmQgPVxuICAgICAgICBwcmV2QXJyYXlQbGFjZWhvbGRlciAmJiBtYXRjaGVySW5kZXggIT09IGZpcnN0Tm9uQXJyYXlDYXB0dXJlSW5kZXhcbiAgICAgICAgICA/IHBhdGhzLmxlbmd0aCAtIHJlbWFpbmluZ0VsZW1lbnRzKG1hdGNoZXJJbmRleCArIDEpXG4gICAgICAgICAgOiBhcnJheUluZGV4ICsgMVxuICAgICAgZm9yIChsZXQgaSA9IGFycmF5SW5kZXg7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgICBtYXRjaFNvRmFyID0gbWF0Y2hlci5tYXRjaChwYXRoc1tpXSwgb3JpZ01hdGNoU29GYXIpXG4gICAgICAgIGlmICghbWF0Y2hTb0ZhcikgY29udGludWVcbiAgICAgICAgaWYgKHByZXZBcnJheVBsYWNlaG9sZGVyKSB7XG4gICAgICAgICAgbWF0Y2hTb0ZhciA9IG1lcmdlQ2FwdHVyZXMobWF0Y2hTb0Zhciwge1xuICAgICAgICAgICAgYXJyYXlDYXB0dXJlczoge1xuICAgICAgICAgICAgICBbcHJldkFycmF5UGxhY2Vob2xkZXJdOiBwYXRocy5zbGljZShzbGljZVN0YXJ0LCBpKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXN0TWF0Y2ggPSBtYXRjaEVsZW0oXG4gICAgICAgICAgcGF0aHMsXG4gICAgICAgICAgaSArIDEsXG4gICAgICAgICAgaSArIDEsXG4gICAgICAgICAgbWF0Y2hlckluZGV4ICsgMSxcbiAgICAgICAgICBtYXRjaFNvRmFyXG4gICAgICAgIClcbiAgICAgICAgaWYgKHJlc3RNYXRjaCkgcmV0dXJuIFtyZXN0TWF0Y2hbMF0sIFtpLCByZXN0TWF0Y2hbMV1bMV1dXVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgY29uc3QgYmxvY2tzOiBOb2RlUGF0aDxCbG9jaz5bXSA9IFtdXG5cbiAgZm9yRWFjaE5vZGUodCwgZW5zdXJlQXJyYXkocGF0aHMpLCBbJ0Jsb2NrJ10sIChwYXRoOiBOb2RlUGF0aCkgPT4ge1xuICAgIGJsb2Nrcy5wdXNoKHBhdGggYXMgTm9kZVBhdGg8QmxvY2s+KVxuICB9KVxuICBibG9ja3MucmV2ZXJzZSgpXG5cbiAgY29uc3QgbWF0Y2hlczogTWF0Y2hbXSA9IFtdXG5cbiAgY29uc3QgaW5pdGlhbE1hdGNoID0gb3B0aW9ucz8ubWF0Y2hTb0ZhciA/PyBudWxsXG5cbiAgZm9yIChjb25zdCBibG9jayBvZiBibG9ja3MpIHtcbiAgICBjb25zdCBib2R5OiBOb2RlUGF0aDxTdGF0ZW1lbnQ+W10gPSBibG9jay5nZXQoJ2JvZHknKS5maWx0ZXIoKCkgPT4gdHJ1ZSlcbiAgICBjb25zdCBlbmQgPSBib2R5Lmxlbmd0aCAtIHJlbWFpbmluZ0VsZW1lbnRzKGZpcnN0Tm9uQXJyYXlDYXB0dXJlSW5kZXggKyAxKVxuICAgIGxldCBzbGljZVN0YXJ0ID0gMFxuICAgIGZvciAobGV0IGFycmF5SW5kZXggPSAwOyBhcnJheUluZGV4IDwgZW5kOyBhcnJheUluZGV4KyspIHtcbiAgICAgIGNvbnN0IG1hdGNoID0gbWF0Y2hFbGVtKFxuICAgICAgICBib2R5LFxuICAgICAgICBzbGljZVN0YXJ0LFxuICAgICAgICBhcnJheUluZGV4LFxuICAgICAgICBmaXJzdE5vbkFycmF5Q2FwdHVyZUluZGV4LFxuICAgICAgICBpbml0aWFsTWF0Y2hcbiAgICAgIClcbiAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICBsZXQgcmVzdWx0ID0gbWF0Y2hbMF1cbiAgICAgICAgY29uc3Qgc3RhcnQgPSBmaXJzdE5vbkFycmF5Q2FwdHVyZUluZGV4ID4gMCA/IDAgOiBtYXRjaFsxXVswXVxuICAgICAgICBjb25zdCBbLCBlbmRdID0gbWF0Y2hbMV1cblxuICAgICAgICAvLyBtYWtlIHN1cmUgYWxsICogY2FwdHVyZXMgYXJlIHByZXNlbnQgaW4gcmVzdWx0c1xuICAgICAgICAvLyAoaWYgdGhlcmUgYXJlIG1vcmUgdGhhbiBvbmUgYWRqYWNlbnQgKiwgYWxsIGNhcHR1cmVkIHBhdGhzIHdpbGwgYmUgaW4gdGhlXG4gICAgICAgIC8vIGxhc3Qgb25lIGFuZCB0aGUgcmVzdCB3aWxsIGJlIGVtcHR5KVxuICAgICAgICBmb3IgKGNvbnN0IG1hdGNoZXIgb2YgbWF0Y2hlcnMpIHtcbiAgICAgICAgICBjb25zdCB7IGFycmF5UGxhY2Vob2xkZXIgfSA9IG1hdGNoZXJcbiAgICAgICAgICBpZiAoIWFycmF5UGxhY2Vob2xkZXIpIGNvbnRpbnVlXG4gICAgICAgICAgaWYgKCFyZXN1bHQ/LmFycmF5Q2FwdHVyZXM/LlthcnJheVBsYWNlaG9sZGVyXSlcbiAgICAgICAgICAgIHJlc3VsdCA9IG1lcmdlQ2FwdHVyZXMocmVzdWx0LCB7XG4gICAgICAgICAgICAgIGFycmF5Q2FwdHVyZXM6IHsgW2FycmF5UGxhY2Vob2xkZXJdOiBbXSB9LFxuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhdGhzID0gYm9keS5zbGljZShzdGFydCwgZW5kKVxuXG4gICAgICAgIGNvbnN0IGZpbmFsTWF0Y2g6IE1hdGNoID0ge1xuICAgICAgICAgIHR5cGU6ICdub2RlcycsXG4gICAgICAgICAgcGF0aDogcGF0aHNbMF0sXG4gICAgICAgICAgbm9kZTogcGF0aHNbMF0ubm9kZSxcbiAgICAgICAgICBwYXRocyxcbiAgICAgICAgICBub2RlczogcGF0aHMubWFwKChwKSA9PiBwLm5vZGUpLFxuICAgICAgICB9XG4gICAgICAgIGlmIChyZXN1bHQ/LmNhcHR1cmVzKSB7XG4gICAgICAgICAgZmluYWxNYXRjaC5wYXRoQ2FwdHVyZXMgPSByZXN1bHQuY2FwdHVyZXNcbiAgICAgICAgICBmaW5hbE1hdGNoLmNhcHR1cmVzID0gbWFwVmFsdWVzKHJlc3VsdC5jYXB0dXJlcywgKHApID0+IHAubm9kZSlcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzdWx0Py5hcnJheUNhcHR1cmVzKSB7XG4gICAgICAgICAgZmluYWxNYXRjaC5hcnJheVBhdGhDYXB0dXJlcyA9IHJlc3VsdC5hcnJheUNhcHR1cmVzXG4gICAgICAgICAgZmluYWxNYXRjaC5hcnJheUNhcHR1cmVzID0gbWFwVmFsdWVzKHJlc3VsdC5hcnJheUNhcHR1cmVzLCAocGF0aHMpID0+XG4gICAgICAgICAgICBwYXRocy5tYXAoKHApID0+IHAubm9kZSlcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdD8uc3RyaW5nQ2FwdHVyZXMpIHtcbiAgICAgICAgICBmaW5hbE1hdGNoLnN0cmluZ0NhcHR1cmVzID0gcmVzdWx0LnN0cmluZ0NhcHR1cmVzXG4gICAgICAgIH1cblxuICAgICAgICBtYXRjaGVzLnB1c2goZmluYWxNYXRjaClcblxuICAgICAgICAvLyBwcmV2ZW50IG92ZXJsYXBwaW5nIG1hdGNoZXNcbiAgICAgICAgc2xpY2VTdGFydCA9IGVuZFxuICAgICAgICBhcnJheUluZGV4ID0gZW5kIC0gMVxuICAgICAgfVxu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