astx
Version:
super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring
164 lines (152 loc) • 16.7 kB
JavaScript
import compileMatcher from './index.mjs'
import indentDebug from './indentDebug.mjs'
import areFieldValuesEqual from '../util/areFieldValuesEqual.mjs'
const equivalenceClassesArray = [
{
nodeTypes: new Set(['ClassDeclaration', 'ClassExpression']),
},
{
nodeTypes: new Set([
'FunctionDeclaration',
'FunctionExpression',
'ArrowFunctionExpression',
'ObjectMethod',
'ClassMethod',
'ClassPrivateMethod',
]),
baseType: 'Function',
},
{
nodeTypes: new Set(['Identifier', 'JSXIdentifier']),
},
]
const equivalenceClasses = {}
for (const klass of equivalenceClassesArray) {
for (const type of klass.nodeTypes) equivalenceClasses[type] = klass
}
const normalizeNull = (value) => {
return value === undefined ? null : value
}
export default function compileGenericNodeMatcher(
path,
compileOptions,
options
) {
const {
backend: { t },
} = compileOptions
const pattern = path.node
const { baseType, nodeTypes } = equivalenceClasses[pattern.type] || {}
const nodeType =
baseType || (nodeTypes ? [...nodeTypes] : null) || pattern.type
const isType = baseType
? (node) => {
var _baseType
return (_baseType = t.namedTypes[baseType]) === null ||
_baseType === void 0
? void 0
: _baseType.check(node)
}
: null
const isCorrectType = isType
? (node) => isType(node)
: nodeTypes
? (node) =>
nodeTypes.has(node === null || node === void 0 ? void 0 : node.type)
: (node) =>
(node === null || node === void 0 ? void 0 : node.type) === pattern.type
const { debug } = compileOptions
const keyMatchers = Object.fromEntries(
t.getFieldNames(pattern).map((key) => {
var _options$keyMatchers
const custom =
options === null || options === void 0
? void 0
: (_options$keyMatchers = options.keyMatchers) === null ||
_options$keyMatchers === void 0
? void 0
: _options$keyMatchers[key]
if (custom) return [key, custom]
const value = normalizeNull(t.getFieldValue(pattern, key))
const fieldPath = path.get(key)
if (Array.isArray(value) || fieldPath.node === value) {
return [
key,
compileMatcher(fieldPath, {
...compileOptions,
debug: indentDebug(debug, 2),
}),
]
} else if (value instanceof Object) {
return [
key,
{
pattern: fieldPath,
match: (path, matchSoFar) => {
const nodeValue = normalizeNull(path.value)
if (areFieldValuesEqual(t, value, nodeValue)) {
debug(' %s === %s', value, nodeValue)
return matchSoFar || {}
} else {
debug(' %s !== %s', value, nodeValue)
return null
}
},
},
]
} else {
return [
key,
{
pattern: fieldPath,
match: (path, matchSoFar) => {
const nodeValue = normalizeNull(path.value)
if (
value === nodeValue ||
(value === null && nodeValue === false) ||
(value === false && nodeValue === null)
) {
debug(' %s === %s', value, nodeValue)
return matchSoFar || {}
} else {
debug(' %s !== %s', value, nodeValue)
return null
}
},
},
]
}
})
)
return {
pattern: path,
match: (path, matchSoFar) => {
debug('%s (generic)', pattern.type)
if (Array.isArray(path.value)) return null
if (
isCorrectType(path === null || path === void 0 ? void 0 : path.value)
) {
for (const key in keyMatchers) {
debug(' .%s', key)
const matcher = keyMatchers[key]
matchSoFar = matcher.match(path.get(key), matchSoFar)
if (!matchSoFar) return null
}
return matchSoFar || {}
} else {
var _path$value
debug(
' path?.value?.type (%s) is not compatible with pattern.type (%s)',
path === null || path === void 0
? void 0
: (_path$value = path.value) === null || _path$value === void 0
? void 0
: _path$value.type,
pattern.type
)
return null
}
},
nodeType,
}
} //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjb21waWxlTWF0Y2hlciIsImluZGVudERlYnVnIiwiYXJlRmllbGRWYWx1ZXNFcXVhbCIsImVxdWl2YWxlbmNlQ2xhc3Nlc0FycmF5Iiwibm9kZVR5cGVzIiwiU2V0IiwiYmFzZVR5cGUiLCJlcXVpdmFsZW5jZUNsYXNzZXMiLCJrbGFzcyIsInR5cGUiLCJub3JtYWxpemVOdWxsIiwidmFsdWUiLCJ1bmRlZmluZWQiLCJjb21waWxlR2VuZXJpY05vZGVNYXRjaGVyIiwicGF0aCIsImNvbXBpbGVPcHRpb25zIiwib3B0aW9ucyIsImJhY2tlbmQiLCJ0IiwicGF0dGVybiIsIm5vZGUiLCJub2RlVHlwZSIsImlzVHlwZSIsIm5hbWVkVHlwZXMiLCJjaGVjayIsImlzQ29ycmVjdFR5cGUiLCJoYXMiLCJkZWJ1ZyIsImtleU1hdGNoZXJzIiwiT2JqZWN0IiwiZnJvbUVudHJpZXMiLCJnZXRGaWVsZE5hbWVzIiwibWFwIiwia2V5IiwiY3VzdG9tIiwiZ2V0RmllbGRWYWx1ZSIsImZpZWxkUGF0aCIsImdldCIsIkFycmF5IiwiaXNBcnJheSIsIm1hdGNoIiwibWF0Y2hTb0ZhciIsIm5vZGVWYWx1ZSIsIm1hdGNoZXIiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tcGlsZU1hdGNoZXIvR2VuZXJpY05vZGVNYXRjaGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5vZGUsIE5vZGVQYXRoLCBOb2RlVHlwZSB9IGZyb20gJy4uL3R5cGVzJ1xuaW1wb3J0IGNvbXBpbGVNYXRjaGVyLCB7XG4gIENvbXBpbGVkTWF0Y2hlcixcbiAgQ29tcGlsZU9wdGlvbnMsXG4gIE1hdGNoUmVzdWx0LFxufSBmcm9tICcuL2luZGV4J1xuaW1wb3J0IGluZGVudERlYnVnIGZyb20gJy4vaW5kZW50RGVidWcnXG5pbXBvcnQgYXJlRmllbGRWYWx1ZXNFcXVhbCBmcm9tICcuLi91dGlsL2FyZUZpZWxkVmFsdWVzRXF1YWwnXG5cbmNvbnN0IGVxdWl2YWxlbmNlQ2xhc3Nlc0FycmF5OiB7XG4gIG5vZGVUeXBlczogU2V0PE5vZGVUeXBlPlxuICBiYXNlVHlwZT86IE5vZGVUeXBlXG59W10gPSBbXG4gIHsgbm9kZVR5cGVzOiBuZXcgU2V0KFsnQ2xhc3NEZWNsYXJhdGlvbicsICdDbGFzc0V4cHJlc3Npb24nXSkgfSxcbiAge1xuICAgIG5vZGVUeXBlczogbmV3IFNldChbXG4gICAgICAnRnVuY3Rpb25EZWNsYXJhdGlvbicsXG4gICAgICAnRnVuY3Rpb25FeHByZXNzaW9uJyxcbiAgICAgICdBcnJvd0Z1bmN0aW9uRXhwcmVzc2lvbicsXG4gICAgICAnT2JqZWN0TWV0aG9kJyxcbiAgICAgICdDbGFzc01ldGhvZCcsXG4gICAgICAnQ2xhc3NQcml2YXRlTWV0aG9kJyxcbiAgICBdKSxcbiAgICBiYXNlVHlwZTogJ0Z1bmN0aW9uJyxcbiAgfSxcbiAge1xuICAgIG5vZGVUeXBlczogbmV3IFNldChbJ0lkZW50aWZpZXInLCAnSlNYSWRlbnRpZmllciddKSxcbiAgfSxcbl1cblxuY29uc3QgZXF1aXZhbGVuY2VDbGFzc2VzOiBQYXJ0aWFsPFxuICBSZWNvcmQ8Tm9kZVR5cGUsIHsgbm9kZVR5cGVzOiBTZXQ8Tm9kZVR5cGU+OyBiYXNlVHlwZT86IE5vZGVUeXBlIH0+XG4+ID0ge31cbmZvciAoY29uc3Qga2xhc3Mgb2YgZXF1aXZhbGVuY2VDbGFzc2VzQXJyYXkpIHtcbiAgZm9yIChjb25zdCB0eXBlIG9mIGtsYXNzLm5vZGVUeXBlcykgZXF1aXZhbGVuY2VDbGFzc2VzW3R5cGVdID0ga2xhc3Ncbn1cblxuY29uc3Qgbm9ybWFsaXplTnVsbCA9IDxUPih2YWx1ZTogVCB8IG51bGwgfCB1bmRlZmluZWQpOiBUIHwgbnVsbCA9PiB7XG4gIHJldHVybiB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IHZhbHVlXG59XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGNvbXBpbGVHZW5lcmljTm9kZU1hdGNoZXIoXG4gIHBhdGg6IE5vZGVQYXRoPE5vZGUsIE5vZGU+LFxuICBjb21waWxlT3B0aW9uczogQ29tcGlsZU9wdGlvbnMsXG4gIG9wdGlvbnM/OiB7XG4gICAga2V5TWF0Y2hlcnM/OiBSZWNvcmQ8c3RyaW5nLCBDb21waWxlZE1hdGNoZXI+XG4gIH1cbik6IENvbXBpbGVkTWF0Y2hlciB7XG4gIGNvbnN0IHtcbiAgICBiYWNrZW5kOiB7IHQgfSxcbiAgfSA9IGNvbXBpbGVPcHRpb25zXG5cbiAgY29uc3QgcGF0dGVybjogTm9kZSA9IHBhdGgubm9kZVxuXG4gIGNvbnN0IHsgYmFzZVR5cGUsIG5vZGVUeXBlcyB9ID1cbiAgICBlcXVpdmFsZW5jZUNsYXNzZXNbcGF0dGVybi50eXBlIGFzIE5vZGVUeXBlXSB8fCB7fVxuXG4gIGNvbnN0IG5vZGVUeXBlID1cbiAgICBiYXNlVHlwZSB8fFxuICAgIChub2RlVHlwZXMgPyBbLi4ubm9kZVR5cGVzXSA6IG51bGwpIHx8XG4gICAgKHBhdHRlcm4udHlwZSBhcyBOb2RlVHlwZSlcbiAgY29uc3QgaXNUeXBlID0gYmFzZVR5cGVcbiAgICA/IChub2RlOiBhbnkpID0+ICh0Lm5hbWVkVHlwZXMgYXMgYW55KVtiYXNlVHlwZV0/LmNoZWNrKG5vZGUpXG4gICAgOiBudWxsXG4gIGNvbnN0IGlzQ29ycmVjdFR5cGUgPSBpc1R5cGVcbiAgICA/IChub2RlOiBOb2RlKSA9PiBpc1R5cGUobm9kZSlcbiAgICA6IG5vZGVUeXBlc1xuICAgID8gKG5vZGU6IE5vZGUpID0+IG5vZGVUeXBlcy5oYXMobm9kZT8udHlwZSBhcyBOb2RlVHlwZSlcbiAgICA6IChub2RlOiBOb2RlKSA9PiBub2RlPy50eXBlID09PSBwYXR0ZXJuLnR5cGVcblxuICBjb25zdCB7IGRlYnVnIH0gPSBjb21waWxlT3B0aW9uc1xuXG4gIGNvbnN0IGtleU1hdGNoZXJzOiBSZWNvcmQ8c3RyaW5nLCBDb21waWxlZE1hdGNoZXI+ID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgIHQuZ2V0RmllbGROYW1lcyhwYXR0ZXJuKS5tYXAoKGtleTogc3RyaW5nKTogW3N0cmluZywgQ29tcGlsZWRNYXRjaGVyXSA9PiB7XG4gICAgICBjb25zdCBjdXN0b20gPSBvcHRpb25zPy5rZXlNYXRjaGVycz8uW2tleV1cblxuICAgICAgaWYgKGN1c3RvbSkgcmV0dXJuIFtrZXksIGN1c3RvbV1cblxuICAgICAgY29uc3QgdmFsdWUgPSBub3JtYWxpemVOdWxsKHQuZ2V0RmllbGRWYWx1ZShwYXR0ZXJuLCBrZXkpKVxuICAgICAgY29uc3QgZmllbGRQYXRoID0gcGF0aC5nZXQoa2V5KVxuXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgfHwgZmllbGRQYXRoLm5vZGUgPT09IHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAga2V5LFxuICAgICAgICAgIGNvbXBpbGVNYXRjaGVyKGZpZWxkUGF0aCwge1xuICAgICAgICAgICAgLi4uY29tcGlsZU9wdGlvbnMsXG4gICAgICAgICAgICBkZWJ1ZzogaW5kZW50RGVidWcoZGVidWcsIDIpLFxuICAgICAgICAgIH0pLFxuICAgICAgICBdXG4gICAgICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAga2V5LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHBhdHRlcm46IGZpZWxkUGF0aCxcbiAgICAgICAgICAgIG1hdGNoOiAocGF0aDogTm9kZVBhdGgsIG1hdGNoU29GYXI6IE1hdGNoUmVzdWx0KTogTWF0Y2hSZXN1bHQgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBub2RlVmFsdWUgPSBub3JtYWxpemVOdWxsKHBhdGgudmFsdWUpXG5cbiAgICAgICAgICAgICAgaWYgKGFyZUZpZWxkVmFsdWVzRXF1YWwodCwgdmFsdWUsIG5vZGVWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBkZWJ1ZygnICAgICVzID09PSAlcycsIHZhbHVlLCBub2RlVmFsdWUpXG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoU29GYXIgfHwge31cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZWJ1ZygnICAgICVzICE9PSAlcycsIHZhbHVlLCBub2RlVmFsdWUpXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICBdXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIGtleSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwYXR0ZXJuOiBmaWVsZFBhdGgsXG4gICAgICAgICAgICBtYXRjaDogKHBhdGg6IE5vZGVQYXRoLCBtYXRjaFNvRmFyOiBNYXRjaFJlc3VsdCk6IE1hdGNoUmVzdWx0ID0+IHtcbiAgICAgICAgICAgICAgY29uc3Qgbm9kZVZhbHVlID0gbm9ybWFsaXplTnVsbChwYXRoLnZhbHVlKVxuXG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICB2YWx1ZSA9PT0gbm9kZVZhbHVlIHx8XG4gICAgICAgICAgICAgICAgKHZhbHVlID09PSBudWxsICYmIG5vZGVWYWx1ZSA9PT0gZmFsc2UpIHx8XG4gICAgICAgICAgICAgICAgKHZhbHVlID09PSBmYWxzZSAmJiBub2RlVmFsdWUgPT09IG51bGwpXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGRlYnVnKCcgICAgJXMgPT09ICVzJywgdmFsdWUsIG5vZGVWYWx1ZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gbWF0Y2hTb0ZhciB8fCB7fVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRlYnVnKCcgICAgJXMgIT09ICVzJywgdmFsdWUsIG5vZGVWYWx1ZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIF1cbiAgICAgIH1cbiAgICB9KVxuICApXG5cbiAgcmV0dXJuIHtcbiAgICBwYXR0ZXJuOiBwYXRoLFxuICAgIG1hdGNoOiAocGF0aDogTm9kZVBhdGgsIG1hdGNoU29GYXI6IE1hdGNoUmVzdWx0KTogTWF0Y2hSZXN1bHQgPT4ge1xuICAgICAgZGVidWcoJyVzIChnZW5lcmljKScsIHBhdHRlcm4udHlwZSlcblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkocGF0aC52YWx1ZSkpIHJldHVybiBudWxsXG5cbiAgICAgIGlmIChpc0NvcnJlY3RUeXBlKHBhdGg/LnZhbHVlKSkge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBrZXlNYXRjaGVycykge1xuICAgICAgICAgIGRlYnVnKCcgIC4lcycsIGtleSlcbiAgICAgICAgICBjb25zdCBtYXRjaGVyID0ga2V5TWF0Y2hlcnNba2V5XVxuICAgICAgICAgIG1hdGNoU29GYXIgPSBtYXRjaGVyLm1hdGNoKHBhdGguZ2V0KGtleSksIG1hdGNoU29GYXIpXG4gICAgICAgICAgaWYgKCFtYXRjaFNvRmFyKSByZXR1cm4gbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1hdGNoU29GYXIgfHwge31cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlYnVnKFxuICAgICAgICAgICcgIHBhdGg/LnZhbHVlPy50eXBlICglcykgaXMgbm90IGNvbXBhdGlibGUgd2l0aCBwYXR0ZXJuLnR5cGUgKCVzKScsXG4gICAgICAgICAgcGF0aD8udmFsdWU/LnR5cGUsXG4gICAgICAgICAgcGF0dGVybi50eXBlXG4gICAgICAgIClcblxuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgfVxuICAgIH0sXG5cbiAgICBub2RlVHlwZSxcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQ0EsT0FBT0EsY0FBUDs7OztBQUlPLFNBSlA7QUFLQSxPQUFPQyxXQUFQLE1BQXdCLGVBQXhCO0FBQ0EsT0FBT0MsbUJBQVAsTUFBZ0MsNkJBQWhDOztBQUVBLE1BQU1DLHVCQUdIOzs7QUFBRztBQUNKLEVBQUVDLFNBQVMsRUFBRSxJQUFJQyxHQUFKLENBQVEsQ0FB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