是否可以执行排除某些节点类型的 Babel "scope rename"?
Is it possible to do a Babel "scope rename" excluding certain node types?
我正在开发一个重新绑定(使用 bind
)一些导入的 Babel 插件,这意味着我需要创建一个新变量来指向新绑定,因为导入是只读的。在那之后,我想做一个 nodePath.scope.rename
从原始导入名称到新的“被劫持”变量。这工作正常,但问题是原始导入也被重命名,因为它们在全局范围内。
有没有办法在排除 ImportDeclaration
类型的节点的同时执行 nodePath.scope.rename
?
获取绑定解决方案
我们不能重命名全局范围内的所有内容,而只能重命名绑定,它通过将范围限定到其父对象来排除原始节点:
const binding = matchingNodePath.scope.getBinding(currentName);
binding.referencePaths.forEach((referencePath) => {
referencePath.scope.rename(
currentName,
hijackedNamespace,
referencePath.parent
);
});
节点替换方案
我在执行 scope.rename
时找不到任何方法来排除导入声明。所以我最后做的是先克隆节点:
// Get all import declarations.
const importDeclarationNodePaths = (nodePath.get('body') as NodePath[]).filter((node) =>
node.isImportDeclaration()
) as NodePath<ImportDeclaration>[];
// Make a copy of the node so we can restore it later after we rename all matching variables.
const originalImportDeclarationNodes = importDeclarationNodePaths.map((nodePath) => {
return cloneNode(nodePath.node, true);
}) as ImportDeclaration[];
然后我们可以重命名并恢复原来的说明符
nodePath.scope.rename('originalName', 'newName');
// Because of the global scope rename, we need to set back original import declarations.
for (const importPosition in importDeclarationNodePaths) {
const hijackedImportDeclarationNodePath = importDeclarationNodePaths[importPosition];
const originalImportDeclarationNode = originalImportDeclarationNodes[importPosition];
// Replace the specifiers of the hijacked import declaration with its original value.
hijackedImportDeclarationNodePath.replaceWith(
importDeclaration(
originalImportDeclarationNode.specifiers,
hijackedImportDeclarationNodePath.node.source
)
);
}
我正在开发一个重新绑定(使用 bind
)一些导入的 Babel 插件,这意味着我需要创建一个新变量来指向新绑定,因为导入是只读的。在那之后,我想做一个 nodePath.scope.rename
从原始导入名称到新的“被劫持”变量。这工作正常,但问题是原始导入也被重命名,因为它们在全局范围内。
有没有办法在排除 ImportDeclaration
类型的节点的同时执行 nodePath.scope.rename
?
获取绑定解决方案
我们不能重命名全局范围内的所有内容,而只能重命名绑定,它通过将范围限定到其父对象来排除原始节点:
const binding = matchingNodePath.scope.getBinding(currentName);
binding.referencePaths.forEach((referencePath) => {
referencePath.scope.rename(
currentName,
hijackedNamespace,
referencePath.parent
);
});
节点替换方案
我在执行 scope.rename
时找不到任何方法来排除导入声明。所以我最后做的是先克隆节点:
// Get all import declarations.
const importDeclarationNodePaths = (nodePath.get('body') as NodePath[]).filter((node) =>
node.isImportDeclaration()
) as NodePath<ImportDeclaration>[];
// Make a copy of the node so we can restore it later after we rename all matching variables.
const originalImportDeclarationNodes = importDeclarationNodePaths.map((nodePath) => {
return cloneNode(nodePath.node, true);
}) as ImportDeclaration[];
然后我们可以重命名并恢复原来的说明符
nodePath.scope.rename('originalName', 'newName');
// Because of the global scope rename, we need to set back original import declarations.
for (const importPosition in importDeclarationNodePaths) {
const hijackedImportDeclarationNodePath = importDeclarationNodePaths[importPosition];
const originalImportDeclarationNode = originalImportDeclarationNodes[importPosition];
// Replace the specifiers of the hijacked import declaration with its original value.
hijackedImportDeclarationNodePath.replaceWith(
importDeclaration(
originalImportDeclarationNode.specifiers,
hijackedImportDeclarationNodePath.node.source
)
);
}