UNPKG

astx

Version:

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

1,132 lines (989 loc) 31.4 kB
'use strict' var _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault') var _typeof3 = require('@babel/runtime/helpers/typeof') Object.defineProperty(exports, '__esModule', { value: true, }) exports['default'] = void 0 var _regenerator = _interopRequireDefault(require('@babel/runtime/regenerator')) var _toConsumableArray2 = _interopRequireDefault( require('@babel/runtime/helpers/toConsumableArray') ) var _typeof2 = _interopRequireDefault(require('@babel/runtime/helpers/typeof')) var _assertThisInitialized2 = _interopRequireDefault( require('@babel/runtime/helpers/assertThisInitialized') ) var _inherits2 = _interopRequireDefault( require('@babel/runtime/helpers/inherits') ) var _possibleConstructorReturn2 = _interopRequireDefault( require('@babel/runtime/helpers/possibleConstructorReturn') ) var _getPrototypeOf2 = _interopRequireDefault( require('@babel/runtime/helpers/getPrototypeOf') ) var _defineProperty2 = _interopRequireDefault( require('@babel/runtime/helpers/defineProperty') ) var _createClass2 = _interopRequireDefault( require('@babel/runtime/helpers/createClass') ) var _classCallCheck2 = _interopRequireDefault( require('@babel/runtime/helpers/classCallCheck') ) var _slicedToArray2 = _interopRequireDefault( require('@babel/runtime/helpers/slicedToArray') ) var _find2 = _interopRequireWildcard(require('./find')) var _replace2 = _interopRequireDefault(require('./replace')) var _compileMatcher = _interopRequireDefault(require('./compileMatcher')) var _CodeFrameError = _interopRequireDefault(require('./util/CodeFrameError')) var _ensureArray = _interopRequireDefault(require('./util/ensureArray')) var _Placeholder = require('./compileMatcher/Placeholder') var _Symbol$iterator 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 || (_typeof3(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 ownKeys(object, enumerableOnly) { var keys = Object.keys(object) if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object) enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable })), keys.push.apply(keys, symbols) } return keys } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {} i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { ;(0, _defineProperty2['default'])(target, key, source[key]) }) : Object.getOwnPropertyDescriptors ? Object.defineProperties( target, Object.getOwnPropertyDescriptors(source) ) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty( target, key, Object.getOwnPropertyDescriptor(source, key) ) }) } return target } 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 _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct() return function _createSuperInternal() { var Super = (0, _getPrototypeOf2['default'])(Derived), result if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2['default'])(this).constructor result = Reflect.construct(Super, arguments, NewTarget) } else { result = Super.apply(this, arguments) } return (0, _possibleConstructorReturn2['default'])(this, result) } } function _isNativeReflectConstruct() { if (typeof Reflect === 'undefined' || !Reflect.construct) return false if (Reflect.construct.sham) return false if (typeof Proxy === 'function') return true try { Boolean.prototype.valueOf.call( Reflect.construct(Boolean, [], function () {}) ) return true } catch (e) { return false } } function isNode(x) { return x instanceof Object && typeof x.type === 'string' } function isNodeArray(x) { return Array.isArray(x) && !Array.isArray(x.raw) } function isPlaceholdersHash(item) { if (!(item instanceof Object)) return false for ( var _i = 0, _Object$entries = Object.entries(item); _i < _Object$entries.length; _i++ ) { var _Object$entries$_i = (0, _slicedToArray2['default'])( _Object$entries[_i], 2 ), key = _Object$entries$_i[0], value = _Object$entries$_i[1] if (!(0, _Placeholder.isPlaceholder)(key)) return false if (!(value instanceof Astx)) return false } return true } var ExtendableProxy = /*#__PURE__*/ (0, _createClass2['default'])( function ExtendableProxy(handler) { ;(0, _classCallCheck2['default'])(this, ExtendableProxy) return new Proxy(this, handler) } ) _Symbol$iterator = Symbol.iterator var Astx = /*#__PURE__*/ (function (_ExtendableProxy) { ;(0, _inherits2['default'])(Astx, _ExtendableProxy) var _super = _createSuper(Astx) function Astx(backend, paths) { var _this var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, _ref$withCaptures = _ref.withCaptures, withCaptures = _ref$withCaptures === void 0 ? [] : _ref$withCaptures, placeholder = _ref.placeholder ;(0, _classCallCheck2['default'])(this, Astx) _this = _super.call(this, { get: function get(target, prop) { if ( (0, _typeof2['default'])(prop) === 'symbol' || !prop.startsWith('$') ) return target[prop] var matches = [] var _iterator = _createForOfIteratorHelper(target._matches), _step try { for (_iterator.s(); !(_step = _iterator.n()).done; ) { var _step$value = _step.value, arrayPathCaptures = _step$value.arrayPathCaptures, pathCaptures = _step$value.pathCaptures, stringCaptures = _step$value.stringCaptures var _path = pathCaptures === null || pathCaptures === void 0 ? void 0 : pathCaptures[prop] var stringValue = stringCaptures === null || stringCaptures === void 0 ? void 0 : stringCaptures[prop] var arrayPaths = arrayPathCaptures === null || arrayPathCaptures === void 0 ? void 0 : arrayPathCaptures[prop] if (_path) matches.push( (0, _find2.createMatch)(_path, { stringCaptures: stringValue ? (0, _defineProperty2['default'])({}, prop, stringValue) : undefined, }) ) if (arrayPaths) matches.push((0, _find2.createMatch)(arrayPaths, {})) } } catch (err) { _iterator.e(err) } finally { _iterator.f() } return new Astx(target.backend, matches, { placeholder: prop, }) }, }) ;(0, _defineProperty2['default'])( (0, _assertThisInitialized2['default'])(_this), 'backend', void 0 ) ;(0, _defineProperty2['default'])( (0, _assertThisInitialized2['default'])(_this), '_matches', void 0 ) ;(0, _defineProperty2['default'])( (0, _assertThisInitialized2['default'])(_this), '_withCaptures', void 0 ) ;(0, _defineProperty2['default'])( (0, _assertThisInitialized2['default'])(_this), '_placeholder', void 0 ) ;(0, _defineProperty2['default'])( (0, _assertThisInitialized2['default'])(_this), '_lazyPaths', void 0 ) ;(0, _defineProperty2['default'])( (0, _assertThisInitialized2['default'])(_this), '_lazyNodes', void 0 ) ;(0, _defineProperty2['default'])( (0, _assertThisInitialized2['default'])(_this), '_lazyInitialMatch', void 0 ) _this.backend = backend _this._placeholder = placeholder var NodePath = backend.t.NodePath _this._matches = paths[0] instanceof NodePath ? paths.map(function (path) { return (0, _find2.createMatch)(path, {}) }) : paths _this._withCaptures = withCaptures return _this } ;(0, _createClass2['default'])(Astx, [ { key: 'placeholder', get: function get() { return this._placeholder }, }, { key: 'size', get: function get() { return this._matches.length }, }, { key: 'matches', get: function get() { return this._matches }, }, { key: _Symbol$iterator, value: /*#__PURE__*/ _regenerator['default'].mark(function value() { var _iterator2, _step2, _path2, _iterator3, _step3, match return _regenerator['default'].wrap( function value$(_context) { while (1) { switch ((_context.prev = _context.next)) { case 0: if (!this._placeholder) { _context.next = 20 break } _iterator2 = _createForOfIteratorHelper(this.paths) _context.prev = 2 _iterator2.s() case 4: if ((_step2 = _iterator2.n()).done) { _context.next = 10 break } _path2 = _step2.value _context.next = 8 return new Astx(this.backend, [_path2]) case 8: _context.next = 4 break case 10: _context.next = 15 break case 12: _context.prev = 12 _context.t0 = _context['catch'](2) _iterator2.e(_context.t0) case 15: _context.prev = 15 _iterator2.f() return _context.finish(15) case 18: _context.next = 37 break case 20: _iterator3 = _createForOfIteratorHelper(this._matches) _context.prev = 21 _iterator3.s() case 23: if ((_step3 = _iterator3.n()).done) { _context.next = 29 break } match = _step3.value _context.next = 27 return new Astx(this.backend, [match]) case 27: _context.next = 23 break case 29: _context.next = 34 break case 31: _context.prev = 31 _context.t1 = _context['catch'](21) _iterator3.e(_context.t1) case 34: _context.prev = 34 _iterator3.f() return _context.finish(34) case 37: case 'end': return _context.stop() } } }, value, this, [ [2, 12, 15, 18], [21, 31, 34, 37], ] ) }), }, { key: 'match', get: function get() { var _this$_matches = (0, _slicedToArray2['default'])(this._matches, 1), match = _this$_matches[0] if (!match) { throw new Error("you can't call match() when there are no matches") } return match }, }, { key: 'node', get: function get() { return this.match.node }, }, { key: 'path', get: function get() { return this.match.path }, }, { key: 'code', get: function get() { return this.backend.generate(this.node).code }, }, { key: 'stringValue', get: function get() { var _this$match$stringCap var result = (_this$match$stringCap = this.match.stringCaptures) === null || _this$match$stringCap === void 0 ? void 0 : _this$match$stringCap[this._placeholder || ''] if (!result) throw new Error('not a string capture') return result }, }, { key: 'paths', get: function get() { return ( this._lazyPaths || (this._lazyPaths = this.matches .map(function (m) { return m.paths }) .flat()) ) }, }, { key: 'nodes', get: function get() { return ( this._lazyNodes || (this._lazyNodes = this.matches .map(function (m) { return m.nodes }) .flat()) ) }, }, { key: 'filter', value: function filter(iteratee) { var filtered = [] var index = 0 var _iterator4 = _createForOfIteratorHelper(this), _step4 try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done; ) { var _astx = _step4.value if (iteratee(_astx, index++, this)) { filtered.push(_astx.match) } } } catch (err) { _iterator4.e(err) } finally { _iterator4.f() } return new Astx(this.backend, filtered) }, }, { key: 'map', value: function map(iteratee) { var result = [] var index = 0 var _iterator5 = _createForOfIteratorHelper(this), _step5 try { for (_iterator5.s(); !(_step5 = _iterator5.n()).done; ) { var _astx2 = _step5.value result.push(iteratee(_astx2, index++, this)) } } catch (err) { _iterator5.e(err) } finally { _iterator5.f() } return result }, }, { key: 'at', value: function at(index) { return new Astx(this.backend, [this._matches[index]]) }, }, { key: 'withCaptures', value: function withCaptures() { var withCaptures = (0, _toConsumableArray2['default'])( this._withCaptures ) for ( var _len = arguments.length, captures = new Array(_len), _key = 0; _key < _len; _key++ ) { captures[_key] = arguments[_key] } for (var _i2 = 0, _captures = captures; _i2 < _captures.length; _i2++) { var item = _captures[_i2] if (item instanceof Astx) { if (item._placeholder) { var placeholder = item._placeholder var _iterator6 = _createForOfIteratorHelper(item._matches), _step6 try { for (_iterator6.s(); !(_step6 = _iterator6.n()).done; ) { var _step6$value = _step6.value, _path3 = _step6$value.path, paths = _step6$value.paths, stringCaptures = _step6$value.stringCaptures withCaptures.push( (0, _find2.createMatch)(paths, { captures: (0, _Placeholder.getPlaceholder)(placeholder) ? (0, _defineProperty2['default'])( {}, placeholder, _path3 ) : undefined, arrayCaptures: (0, _Placeholder.getArrayPlaceholder)(placeholder) || (0, _Placeholder.getRestPlaceholder)(placeholder) ? (0, _defineProperty2['default'])( {}, placeholder, paths ) : undefined, stringCaptures: (0, _Placeholder.getPlaceholder)(placeholder) && stringCaptures !== null && stringCaptures !== void 0 && stringCaptures[placeholder] ? (0, _defineProperty2['default'])( {}, placeholder, stringCaptures[placeholder] ) : undefined, }) ) } } catch (err) { _iterator6.e(err) } finally { _iterator6.f() } } else { var _iterator7 = _createForOfIteratorHelper(item._withCaptures), _step7 try { for (_iterator7.s(); !(_step7 = _iterator7.n()).done; ) { var match = _step7.value withCaptures.push(match) } } catch (err) { _iterator7.e(err) } finally { _iterator7.f() } var _iterator8 = _createForOfIteratorHelper(item._matches), _step8 try { for (_iterator8.s(); !(_step8 = _iterator8.n()).done; ) { var _match = _step8.value withCaptures.push(_match) } } catch (err) { _iterator8.e(err) } finally { _iterator8.f() } } } else if (isPlaceholdersHash(item)) { for ( var _i3 = 0, _Object$entries2 = Object.entries(item); _i3 < _Object$entries2.length; _i3++ ) { var _Object$entries2$_i = (0, _slicedToArray2['default'])( _Object$entries2[_i3], 2 ), _placeholder2 = _Object$entries2$_i[0], _astx3 = _Object$entries2$_i[1] var _placeholder = _astx3._placeholder var _iterator9 = _createForOfIteratorHelper(_astx3._matches), _step9 try { for (_iterator9.s(); !(_step9 = _iterator9.n()).done; ) { var _step9$value = _step9.value, _path4 = _step9$value.path, _paths = _step9$value.paths, _stringCaptures = _step9$value.stringCaptures withCaptures.push( (0, _find2.createMatch)(_paths, { captures: (0, _Placeholder.getPlaceholder)(_placeholder2) ? (0, _defineProperty2['default'])( {}, _placeholder2, _path4 ) : undefined, arrayCaptures: (0, _Placeholder.getArrayPlaceholder)(_placeholder2) || (0, _Placeholder.getRestPlaceholder)(_placeholder2) ? (0, _defineProperty2['default'])( {}, _placeholder2, _paths ) : undefined, stringCaptures: (0, _Placeholder.getPlaceholder)(_placeholder2) && _placeholder && _stringCaptures !== null && _stringCaptures !== void 0 && _stringCaptures[_placeholder] ? (0, _defineProperty2['default'])( {}, _placeholder2, _stringCaptures[_placeholder] ) : undefined, }) ) } } catch (err) { _iterator9.e(err) } finally { _iterator9.f() } } } else { withCaptures.push(item) } } return new Astx(this.backend, this._matches, { withCaptures: withCaptures, }) }, }, { key: 'initialMatch', get: function get() { return ( this._lazyInitialMatch || (this._lazyInitialMatch = (0, _find2.convertWithCaptures)( [].concat( (0, _toConsumableArray2['default'])(this._matches), (0, _toConsumableArray2['default'])(this._withCaptures) ) )) ) }, }, { key: '_execPattern', value: function _execPattern(name, exec, arg0) { var backend = this.backend var parsePattern = backend.parsePattern var NodePath = backend.t.NodePath try { var _pattern, _options for ( var _len2 = arguments.length, rest = new Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++ ) { rest[_key2 - 3] = arguments[_key2] } if (typeof arg0 === 'string') { _pattern = parsePattern(arg0) _options = rest[0] } else if ( Array.isArray(arg0) ? arg0[0] instanceof NodePath : arg0 instanceof NodePath ) { _pattern = (0, _ensureArray['default'])(arg0) _options = rest[0] } else if (isNode(arg0) || isNodeArray(arg0)) { _pattern = (0, _ensureArray['default'])(arg0).map(function (node) { return new NodePath(node) }) _options = rest[0] } else { _pattern = parsePattern.apply(void 0, [arg0].concat(rest)) return function (options) { return exec(_pattern, options) } } return exec(_pattern, _options) } catch (error) { if (error instanceof Error) { _CodeFrameError['default'].rethrow(error, { filename: ''.concat(name, ' pattern'), source: typeof arg0 === 'string' ? arg0 : undefined, }) } throw error } }, }, { key: 'closest', value: function closest(arg0) { var _this2 = this var backend = this.backend for ( var _len3 = arguments.length, rest = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++ ) { rest[_key3 - 1] = arguments[_key3] } return this._execPattern.apply( this, [ 'closest', function (pattern, options) { pattern = (0, _ensureArray['default'])(pattern) if (pattern.length !== 1) { throw new Error('must be a single node') } var matcher = (0, _compileMatcher['default'])( pattern[0], _objectSpread( _objectSpread({}, options), {}, { backend: backend, } ) ) var matchedParents = new Set() var matches = [] _this2.paths.forEach(function (path) { for (var p = path.parentPath; p; p = p.parentPath) { if (matchedParents.has(p)) return var match = matcher.match(p, _this2.initialMatch) if (match) { matchedParents.add(p) matches.push((0, _find2.createMatch)(p, match)) return } } }) return new Astx(backend, matches) }, arg0, ].concat(rest) ) }, }, { key: 'find', value: function find(arg0) { var _this3 = this var backend = this.backend for ( var _len4 = arguments.length, rest = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++ ) { rest[_key4 - 1] = arguments[_key4] } return this._execPattern.apply( this, [ 'find', function (pattern, options) { return new Astx( backend, (0, _find2['default'])( _this3.paths, pattern, _objectSpread( _objectSpread({}, options), {}, { backend: backend, matchSoFar: _this3.initialMatch, } ) ) ) }, arg0, ].concat(rest) ) }, }, { key: 'replace', value: function replace(arg0) { var _this4 = this var backend = this.backend var parsePatternToNodes = backend.parsePatternToNodes try { if (typeof arg0 === 'function') { var _iterator10 = _createForOfIteratorHelper(this), _step10 try { for (_iterator10.s(); !(_step10 = _iterator10.n()).done; ) { var _astx4 = _step10.value var _replacement = arg0(_astx4, parsePatternToNodes) ;(0, _replace2['default'])( _astx4.match, typeof _replacement === 'string' ? parsePatternToNodes(_replacement) : _replacement, { backend: backend, } ) } } catch (err) { _iterator10.e(err) } finally { _iterator10.f() } } else if (typeof arg0 === 'string') { var _replacement2 = parsePatternToNodes(arg0) var _iterator11 = _createForOfIteratorHelper(this._matches), _step11 try { for (_iterator11.s(); !(_step11 = _iterator11.n()).done; ) { var match = _step11.value ;(0, _replace2['default'])(match, _replacement2, { backend: backend, }) } } catch (err) { _iterator11.e(err) } finally { _iterator11.f() } } else if (isNode(arg0) || isNodeArray(arg0)) { var _iterator12 = _createForOfIteratorHelper(this._matches), _step12 try { for (_iterator12.s(); !(_step12 = _iterator12.n()).done; ) { var _match2 = _step12.value ;(0, _replace2['default'])(_match2, arg0, { backend: backend, }) } } catch (err) { _iterator12.e(err) } finally { _iterator12.f() } } else { for ( var _len5 = arguments.length, quasis = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++ ) { quasis[_key5 - 1] = arguments[_key5] } var finalPaths = parsePatternToNodes.apply( void 0, [arg0].concat(quasis) ) return function () { return _this4.replace(finalPaths) } } } catch (error) { if (error instanceof Error) { _CodeFrameError['default'].rethrow(error, { filename: 'replace pattern', source: typeof arg0 === 'string' ? arg0 : undefined, }) } throw error } }, }, ]) return Astx })(ExtendableProxy) exports['default'] = Astx