UNPKG

astx

Version:

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

525 lines (450 loc) 13.5 kB
'use strict' var _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault') var _typeof = require('@babel/runtime/helpers/typeof') Object.defineProperty(exports, '__esModule', { value: true, }) exports.convertWithCaptures = convertWithCaptures exports.createMatch = createMatch exports['default'] = find var _slicedToArray2 = _interopRequireDefault( require('@babel/runtime/helpers/slicedToArray') ) var _defineProperty2 = _interopRequireDefault( require('@babel/runtime/helpers/defineProperty') ) var _toConsumableArray2 = _interopRequireDefault( require('@babel/runtime/helpers/toConsumableArray') ) var _lodash = require('lodash') var _compileMatcher = _interopRequireWildcard(require('./compileMatcher')) var _ensureArray = _interopRequireDefault(require('./util/ensureArray')) var _forEachNode = _interopRequireDefault(require('./util/forEachNode')) function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== 'function') return null var cacheBabelInterop = new WeakMap() var cacheNodeInterop = new WeakMap() return (_getRequireWildcardCache = function _getRequireWildcardCache( nodeInterop ) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop })(nodeInterop) } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj } if ( obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function') ) { return { default: obj, } } var cache = _getRequireWildcardCache(nodeInterop) if (cache && cache.has(obj)) { return cache.get(obj) } var newObj = {} var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor for (var key in obj) { if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc) } else { newObj[key] = obj[key] } } } newObj['default'] = obj if (cache) { cache.set(obj, newObj) } return newObj } function _createForOfIteratorHelper(o, allowArrayLike) { var it = (typeof Symbol !== 'undefined' && o[Symbol.iterator]) || o['@@iterator'] if (!it) { if ( Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || (allowArrayLike && o && typeof o.length === 'number') ) { if (it) o = it var i = 0 var F = function F() {} return { s: F, n: function n() { if (i >= o.length) return { done: true, } return { done: false, value: o[i++], } }, e: function e(_e) { throw _e }, f: F, } } throw new TypeError( 'Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.' ) } var normalCompletion = true, didErr = false, err return { s: function s() { it = it.call(o) }, n: function n() { var step = it.next() normalCompletion = step.done return step }, e: function e(_e2) { didErr = true err = _e2 }, f: function f() { try { if (!normalCompletion && it['return'] != null) it['return']() } finally { if (didErr) throw err } }, } } function _unsupportedIterableToArray(o, minLen) { if (!o) return if (typeof o === 'string') return _arrayLikeToArray(o, minLen) var n = Object.prototype.toString.call(o).slice(8, -1) if (n === 'Object' && o.constructor) n = o.constructor.name if (n === 'Map' || n === 'Set') return Array.from(o) if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen) } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i] } return arr2 } function convertWithCaptures(matches) { return _compileMatcher.mergeCaptures.apply( void 0, (0, _toConsumableArray2['default'])( (0, _ensureArray['default'])(matches).map(function (_ref) { var pathCaptures = _ref.pathCaptures, arrayPathCaptures = _ref.arrayPathCaptures, stringCaptures = _ref.stringCaptures return { captures: pathCaptures, arrayCaptures: arrayPathCaptures, stringCaptures: stringCaptures, } }) ) ) } function createMatch(paths, result) { var _paths$ if (!result) { throw new Error('result must be defined') } var captures = result.captures, arrayCaptures = result.arrayCaptures, stringCaptures = result.stringCaptures var match = Array.isArray(paths) ? { type: 'nodes', node: (_paths$ = paths[0]) === null || _paths$ === void 0 ? void 0 : _paths$.node, path: paths[0], nodes: paths.map(function (p) { return p.node }), paths: paths, } : { type: 'node', node: paths.node, path: paths, nodes: [paths.node], paths: [paths], } if (captures) { match.pathCaptures = captures match.captures = (0, _lodash.mapValues)(captures, function (path) { return path.node }) } if (arrayCaptures) { match.arrayPathCaptures = arrayCaptures match.arrayCaptures = (0, _lodash.mapValues)( arrayCaptures, function (paths) { return paths.map(function (path) { return path.node }) } ) } if (stringCaptures) match.stringCaptures = stringCaptures return match } function find(paths, pattern, options) { var t = options.backend.t var 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) } var matcher = (0, _compileMatcher['default'])(pattern, options) var matches = [] var nodeTypes = (0, _ensureArray['default'])(matcher.nodeType || 'Node') ;(0, _forEachNode['default'])( t, (0, _ensureArray['default'])(paths), nodeTypes, function (path) { var _options$matchSoFar var 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 var t = options.backend.t var matchers = pattern.map(function (queryElem) { return (0, _compileMatcher['default'])(queryElem, options) }) var firstNonArrayCaptureIndex = matchers.findIndex(function (m) { return !m.arrayPlaceholder }) if (firstNonArrayCaptureIndex < 0) { throw new Error( 'pattern would match every single array of statements, this is unsupported' ) } function remainingElements(matcherIndex) { var count = 0 for (var 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 } var matcher = matchers[matcherIndex] var arrayPlaceholder = matcher.arrayPlaceholder if (arrayPlaceholder) { if (matcherIndex === matchers.length - 1) { return [ (0, _compileMatcher.mergeCaptures)(matchSoFar, { arrayCaptures: (0, _defineProperty2['default'])( {}, arrayPlaceholder, paths.slice(sliceStart) ), }), [sliceStart, paths.length], ] } return matchElem( paths, sliceStart, arrayIndex, matcherIndex + 1, matchSoFar ) } else { var _matchers var origMatchSoFar = matchSoFar var prevArrayPlaceholder = (_matchers = matchers[matcherIndex - 1]) === null || _matchers === void 0 ? void 0 : _matchers.arrayPlaceholder var end = prevArrayPlaceholder && matcherIndex !== firstNonArrayCaptureIndex ? paths.length - remainingElements(matcherIndex + 1) : arrayIndex + 1 for (var i = arrayIndex; i < end; i++) { matchSoFar = matcher.match(paths[i], origMatchSoFar) if (!matchSoFar) continue if (prevArrayPlaceholder) { matchSoFar = (0, _compileMatcher.mergeCaptures)(matchSoFar, { arrayCaptures: (0, _defineProperty2['default'])( {}, prevArrayPlaceholder, paths.slice(sliceStart, i) ), }) } var restMatch = matchElem( paths, i + 1, i + 1, matcherIndex + 1, matchSoFar ) if (restMatch) return [restMatch[0], [i, restMatch[1][1]]] } } return null } var blocks = [] ;(0, _forEachNode['default'])( t, (0, _ensureArray['default'])(paths), ['Block'], function (path) { blocks.push(path) } ) blocks.reverse() var matches = [] var initialMatch = (_options$matchSoFar2 = options === null || options === void 0 ? void 0 : options.matchSoFar) !== null && _options$matchSoFar2 !== void 0 ? _options$matchSoFar2 : null for (var _i = 0, _blocks = blocks; _i < _blocks.length; _i++) { var block = _blocks[_i] var body = block.get('body').filter(function () { return true }) var end = body.length - remainingElements(firstNonArrayCaptureIndex + 1) var sliceStart = 0 for (var arrayIndex = 0; arrayIndex < end; arrayIndex++) { var match = matchElem( body, sliceStart, arrayIndex, firstNonArrayCaptureIndex, initialMatch ) if (match) { var _result, _result2, _result3 var result = match[0] var start = firstNonArrayCaptureIndex > 0 ? 0 : match[1][0] var _match$ = (0, _slicedToArray2['default'])(match[1], 2), _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) var _iterator = _createForOfIteratorHelper(matchers), _step try { for (_iterator.s(); !(_step = _iterator.n()).done; ) { var _result4, _result4$arrayCapture var matcher = _step.value var arrayPlaceholder = matcher.arrayPlaceholder if (!arrayPlaceholder) continue if ( !( (_result4 = result) !== null && _result4 !== void 0 && (_result4$arrayCapture = _result4.arrayCaptures) !== null && _result4$arrayCapture !== void 0 && _result4$arrayCapture[arrayPlaceholder] ) ) result = (0, _compileMatcher.mergeCaptures)(result, { arrayCaptures: (0, _defineProperty2['default'])( {}, arrayPlaceholder, [] ), }) } } catch (err) { _iterator.e(err) } finally { _iterator.f() } var _paths = body.slice(start, _end) var finalMatch = { type: 'nodes', path: _paths[0], node: _paths[0].node, paths: _paths, nodes: _paths.map(function (p) { return p.node }), } if ( (_result = result) !== null && _result !== void 0 && _result.captures ) { finalMatch.pathCaptures = result.captures finalMatch.captures = (0, _lodash.mapValues)( result.captures, function (p) { return p.node } ) } if ( (_result2 = result) !== null && _result2 !== void 0 && _result2.arrayCaptures ) { finalMatch.arrayPathCaptures = result.arrayCaptures finalMatch.arrayCaptures = (0, _lodash.mapValues)( result.arrayCaptures, function (paths) { return paths.map(function (p) { return p.node }) } ) } if ( (_result3 = result) !== null && _result3 !== void 0 && _result3.stringCaptures ) { finalMatch.stringCaptures = result.stringCaptures } matches.push(finalMatch) // prevent overlapping matches sliceStart = _end arrayIndex = _end - 1 } } } return matches }