astx
Version:
super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring
609 lines (509 loc) • 17.7 kB
JavaScript
var _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault')
var _typeof = require('@babel/runtime/helpers/typeof')
Object.defineProperty(exports, '__esModule', {
value: true,
})
exports['default'] = runTransformOnFile
var _regenerator = _interopRequireDefault(require('@babel/runtime/regenerator'))
var _slicedToArray2 = _interopRequireDefault(
require('@babel/runtime/helpers/slicedToArray')
)
var _defineProperty2 = _interopRequireDefault(
require('@babel/runtime/helpers/defineProperty')
)
var _asyncToGenerator2 = _interopRequireDefault(
require('@babel/runtime/helpers/asyncToGenerator')
)
var _fsExtra = _interopRequireDefault(require('fs-extra'))
var _path = _interopRequireDefault(require('path'))
var _lodash = require('lodash')
var _util = require('util')
var _resolve2 = _interopRequireDefault(require('resolve'))
var _omitBlankLineChanges = _interopRequireDefault(
require('../util/omitBlankLineChanges')
)
var _CodeFrameError = _interopRequireDefault(require('../util/CodeFrameError'))
var _chooseGetBackend = _interopRequireDefault(require('../chooseGetBackend'))
var _astxCosmiconfig = require('./astxCosmiconfig')
var _Astx = _interopRequireDefault(require('../Astx'))
require('./registerTsNode')
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 _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
}
var resolve = (0, _util.promisify)(_resolve2['default'])
var getPrettier = (0, _lodash.memoize)(
/*#__PURE__*/ (function () {
var _ref = (0, _asyncToGenerator2['default'])(
/*#__PURE__*/ _regenerator['default'].mark(function _callee(path) {
var prettier
return _regenerator['default'].wrap(
function _callee$(_context) {
while (1) {
switch ((_context.prev = _context.next)) {
case 0:
_context.prev = 0
_context.t0 = Promise
_context.t1 = ''
_context.next = 5
return resolve('prettier', {
basedir: path,
})
case 5:
_context.t2 = _context.sent
_context.t3 = _context.t1.concat.call(
_context.t1,
_context.t2
)
_context.next = 9
return _context.t0.resolve
.call(_context.t0, _context.t3)
.then(function (s) {
return _interopRequireWildcard(require(s))
})
case 9:
prettier = _context.sent
if (prettier['default'] instanceof Object) {
prettier = prettier['default']
}
if (
!(
typeof prettier.format === 'function' &&
typeof prettier.resolveConfig === 'function'
)
) {
_context.next = 13
break
}
return _context.abrupt('return', prettier)
case 13:
_context.next = 17
break
case 15:
_context.prev = 15
_context.t4 = _context['catch'](0)
case 17:
return _context.abrupt('return', null)
case 18:
case 'end':
return _context.stop()
}
}
},
_callee,
null,
[[0, 15]]
)
})
)
return function (_x) {
return _ref.apply(this, arguments)
}
})()
)
function runTransformOnFile(_x2) {
return _runTransformOnFile.apply(this, arguments)
}
function _runTransformOnFile() {
_runTransformOnFile = (0, _asyncToGenerator2['default'])(
/*#__PURE__*/ _regenerator['default'].mark(function _callee2(_ref2) {
var _yield$astxCosmiconfi
var _transform,
transformFile,
configOverrides,
file,
source,
signal,
forWorker,
_ref2$fs,
fs,
transform,
baseConfig,
config,
parser,
parserOptions,
backend,
transformed,
reports,
matches,
transformFn,
find,
replace,
ast,
root,
options,
_yield$Promise$all,
_yield$Promise$all2,
_result,
prettier,
prettierConfig
return _regenerator['default'].wrap(
function _callee2$(_context2) {
while (1) {
switch ((_context2.prev = _context2.next)) {
case 0:
;(_transform = _ref2.transform),
(transformFile = _ref2.transformFile),
(configOverrides = _ref2.config),
(file = _ref2.file),
(source = _ref2.source),
(signal = _ref2.signal),
(forWorker = _ref2.forWorker),
(_ref2$fs = _ref2.fs),
(fs = _ref2$fs === void 0 ? _fsExtra['default'] : _ref2$fs)
if (!transformFile) {
_context2.next = 7
break
}
_context2.next = 4
return Promise.resolve(''.concat(transformFile)).then(function (
s
) {
return _interopRequireWildcard(require(s))
})
case 4:
_context2.t0 = _context2.sent
_context2.next = 8
break
case 7:
_context2.t0 = _transform
case 8:
transform = _context2.t0
_context2.next = 11
return _astxCosmiconfig.astxCosmiconfig.search(
_path['default'].dirname(file)
)
case 11:
_context2.t2 = _yield$astxCosmiconfi = _context2.sent
_context2.t1 = _context2.t2 === null
if (_context2.t1) {
_context2.next = 15
break
}
_context2.t1 = _yield$astxCosmiconfi === void 0
case 15:
if (!_context2.t1) {
_context2.next = 19
break
}
_context2.t3 = void 0
_context2.next = 20
break
case 19:
_context2.t3 = _yield$astxCosmiconfi.config
case 20:
baseConfig = _context2.t3
config = _objectSpread(
_objectSpread(_objectSpread({}, baseConfig), configOverrides),
{},
{
parserOptions:
(baseConfig !== null &&
baseConfig !== void 0 &&
baseConfig.parserOptions) ||
(configOverrides !== null &&
configOverrides !== void 0 &&
configOverrides.parserOptions)
? _objectSpread(
_objectSpread(
{},
baseConfig === null || baseConfig === void 0
? void 0
: baseConfig.parserOptions
),
configOverrides === null ||
configOverrides === void 0
? void 0
: configOverrides.parserOptions
)
: undefined,
}
)
if (!(signal !== null && signal !== void 0 && signal.aborted)) {
_context2.next = 24
break
}
throw new Error('aborted')
case 24:
;(parser = config.parser),
(parserOptions = config.parserOptions)
_context2.next = 27
return (0, _chooseGetBackend['default'])(parser)(
file,
parserOptions
)
case 27:
backend = _context2.sent
if (!(signal !== null && signal !== void 0 && signal.aborted)) {
_context2.next = 30
break
}
throw new Error('aborted')
case 30:
_context2.prev = 30
if (source) {
_context2.next = 35
break
}
_context2.next = 34
return fs.readFile(file, 'utf8')
case 34:
source = _context2.sent
case 35:
if (!(signal !== null && signal !== void 0 && signal.aborted)) {
_context2.next = 37
break
}
throw new Error('aborted')
case 37:
reports = []
transformFn = transform.astx
;(find = transform.find), (replace = transform.replace)
if (typeof transformFn !== 'function' && find) {
transformFn = function transformFn(_ref3) {
var astx = _ref3.astx
var result = astx.find(find, {
where: transform.where,
})
if (replace) result.replace(replace)
matches = result.matches
if (!result.size) return null
}
}
if (!(typeof transformFn === 'function')) {
_context2.next = 77
break
}
_context2.prev = 42
ast = backend.parse(source)
root = new backend.t.NodePath(ast)
_context2.next = 51
break
case 47:
_context2.prev = 47
_context2.t4 = _context2['catch'](42)
if (_context2.t4 instanceof Error) {
_CodeFrameError['default'].rethrow(_context2.t4, {
filename: file,
source: source,
})
}
throw _context2.t4
case 51:
options = _objectSpread(
_objectSpread(
{
source: source,
file: file,
root: root,
t: backend.t,
report: function report(msg) {
var _transform$onReport
if (msg instanceof _Astx['default'] && !msg.size) return
if (!forWorker)
(_transform$onReport = transform.onReport) === null ||
_transform$onReport === void 0
? void 0
: _transform$onReport.call(transform, {
file: file,
report: msg,
})
reports.push(msg)
},
},
backend.template
),
{},
{
astx: new _Astx['default'](backend, [root]),
}
)
_context2.next = 54
return Promise.all([
transformFn(options),
(config === null || config === void 0
? void 0
: config.prettier) !== false
? getPrettier(_path['default'].dirname(file))
: null,
])
case 54:
_yield$Promise$all = _context2.sent
_yield$Promise$all2 = (0, _slicedToArray2['default'])(
_yield$Promise$all,
2
)
_result = _yield$Promise$all2[0]
prettier = _yield$Promise$all2[1]
if (!(signal !== null && signal !== void 0 && signal.aborted)) {
_context2.next = 60
break
}
throw new Error('aborted')
case 60:
if (!(transform.astx || transform.replace)) {
_context2.next = 75
break
}
transformed = _result
if (transformed === undefined) {
transformed = backend.generate(ast).code
}
if (transformed === null) transformed = undefined
if (
!(
prettier &&
typeof transformed === 'string' &&
transformed !== source
)
) {
_context2.next = 74
break
}
_context2.next = 67
return prettier.resolveConfig(file)
case 67:
_context2.t5 = _context2.sent
if (_context2.t5) {
_context2.next = 70
break
}
_context2.t5 = {}
case 70:
prettierConfig = _context2.t5
prettierConfig.filepath = file
if (/\.tsx?$/.test(file)) prettierConfig.parser = 'typescript'
transformed = prettier.format(transformed, prettierConfig)
case 74:
if (transformed != null) {
transformed = (0, _omitBlankLineChanges['default'])(
source,
transformed
)
}
case 75:
_context2.next = 78
break
case 77:
return _context2.abrupt('return', {
file: file,
error: new Error(
'transform file must export either astx or find/replace'
),
backend: backend,
})
case 78:
return _context2.abrupt('return', {
file: file,
source: source,
transformed: transformed,
reports: reports,
matches: matches,
backend: backend,
})
case 81:
_context2.prev = 81
_context2.t6 = _context2['catch'](30)
return _context2.abrupt('return', {
file: file,
error:
_context2.t6 instanceof Error
? _context2.t6
: new Error(String(_context2.t6)),
backend: backend,
})
case 84:
case 'end':
return _context2.stop()
}
}
},
_callee2,
null,
[
[30, 81],
[42, 47],
]
)
})
)
return _runTransformOnFile.apply(this, arguments)
}