在重构代码时,我经常需要重命名变量,我目前使用正则表达式以一种有点笨拙的方式进行 - 由于缺乏实际结构,我最终不得不使用愚蠢的文本解决方法解决方法,例如,将“req”重命名为“请求”并避免使用类似名称(如“require”)的副作用。
想想这些东西:这有点像用正则表达式修改 DOM:它只是行不通。
我了解了 AST 和 Esprima 等代码结构修改工具。是否有重命名变量的工具,基于 Esprima 或其他?
在重构代码时,我经常需要重命名变量,我目前使用正则表达式以一种有点笨拙的方式进行 - 由于缺乏实际结构,我最终不得不使用愚蠢的文本解决方法解决方法,例如,将“req”重命名为“请求”并避免使用类似名称(如“require”)的副作用。
想想这些东西:这有点像用正则表达式修改 DOM:它只是行不通。
我了解了 AST 和 Esprima 等代码结构修改工具。是否有重命名变量的工具,基于 Esprima 或其他?
看起来http://graspjs.com/正是这样做的。
grasp selector --replace replacement file.js
例如,将 'el' 重命名为 'element':
grasp '#el' --replace 'element' index.js
Visual Studio Code还包括一个真正的替换工具。只需右键单击一个标记并选择重命名符号。
我知道您一直在要求“工具”;但我认为最好只使用 esprima 本身和 esprima 之上的各种通用工具,并使用自己的重命名器。因为它真的很容易,然后你有更多的控制权。这是一个仅 12 行代码的完整示例。它在 github 上使用 escodegen 和 estraverse,并且据我所知,它是与 esprima 结合使用的“标准”。esprima 本质上给出了解析函数字符串 -> 抽象语法树,而 escodegen 本质上给出了相反的结果,即抽象语法树 -> 字符串。并且 estraverse 使用 traverse 方法“走树”,从而有助于分析或修改它。
这里的代码:
function rename(code, renamingObj){
var ast = esprima.parse(code);
function callback(node){
if (node.type==='Identifier') {
if (node.name in renamingObj){
node.name = renamingObj[node.name];
}
}
}
estraverse.traverse(ast, { enter: callback });
return escodegen.generate(ast);
}
测试用例:
function blah(x,y){
var difference = x + y;
var product = x - y;
var sum = x * y;
return 42;
}
var renamingObj = {
sum : 'product',
difference : 'sum',
product : 'difference'
};
运行:
rename(blah.toString(), renamingObj)
输出:
function blah(x, y) {
var sum = x + y;
var difference = x - y;
var product = x * y;
return 42;
}
我想说,如果你有什么特别的事情要做,修改上面的代码比筛选一些工具文档更容易。
我们的 JavaScript Formatter/Obfuscator 将可靠地做到这一点。它解析 JavaScript,构建 AST,然后打印一个漂亮的版本,或者一个丑陋(混淆)的版本。[这些在一起的原因是因为漂亮和丑陋是同一枚硬币的反面!)。
它所做的一件事是打乱(整个)标识符名称。通过使用 AST,它只重命名“整个标识符”;它不会将“req”与“require”混淆,或意外修改字符串或评论内容。
您可以告诉它构建所有标识符名称的映射,然后将它们全部重命名为自己;只改变一个,你就会得到你的重命名效果。标识符映射如下所示:
x -> y
p -> q
...
指示 x 重命名为 y,p 重命名为 q,等等。你想要:
x -> x
p -> q
...
仅将 p 更改为 q。生成身份图作为您的起点非常容易。
我不会说这很方便,但它确实有效。它显然对范围一无所知。(总有一天!)。
有关详细信息,请参阅我的简历。许多 SO 版主讨厌工具问题,当我提供包含工具链接的工具答案时,他们似乎特别不喜欢它。所以你必须自己追踪链接,对不起。(如果您认为这很愚蠢,请在 Meta 上投诉)。