天天看点

利用estools修改javascript源代码

工作中需要将javascript的if语句描述进行一些规范化,将类似

if(test) value0
else value1
           

的语句的全部统一成:

if (test)
    result = value0;
else
    result = value1;
           

 格式的,便于后续处理。

方法之一使用AST替换来完成,主要用到estools提供的javascript解析和代码生成工具。

主要操作如下

1) 安装node.js

2) mkdir convert

cd convert
npm install esprima
npm install estraverse
npm install escodegen
           

3) 编写AST解析代码,并且查看生成的AST树

var ast = esprima.parse(code);
console.log(JSON.stringify(ast,null,4));
           

4)编写遍历if语句的代码,如果不符合格式,就改变AST的节点。

 ast = estraverse.replace(ast, {
        leave: function(node, parent)
        {
            modifiedNode = node;
            if (node.type === 'IfStatement') {
                if (node.consequent.type === 'ExpressionStatement') 
                {
                    if (node.consequent.expression.type === 'Literal'){
                            modifiedNode['consequent'] = {
                                        "type": "ExpressionStatement",
                                        "expression": {
                                            "type": "AssignmentExpression",
                                            "operator": "=",
                                            "left": {
                                                "type": "Identifier",
                                                "name": "result"
                                            },
                                            "right": node.consequent.expression
                                        }
                                    }
                    };
                    if (node.alternate != null && node.alternate.expression.type === 'Literal'){
                            modifiedNode['alternate'] = {
                                        "type": "ExpressionStatement",
                                        "expression": {
                                            "type":
"AssignmentExpression",
                                            "operator": "=",
                                            "left": {
                                                "type": "Identifier",
                                                "name": "result"
                                            },
                                            "right": node.alternate.expression
                                        }
                                    }
                    };
                }
            };
            return modifiedNode;
        }
    });
           

5)修改好后的ast,生成源代码

var modifiedCode = escodegen.generate(ast);
           

6)运行

获得结果

$ node exc1.js test1.js
Reading test1.js
=============
if (var1 > 2) result = 3;
else result = 0;
if(var2 < 3) 0
else 1
if (var3 === 9) 1;
=============
if (var1 > 2)
    result = 3;
else
    result = 0;
if (var2 < 3)
    result = 0;
else
    result = 1;
if (var3 === 9)
    result = 1;
           

7) 完整代码

exc1.js
-----------
/*
 */
var fs = require('fs'),
    esprima = require('esprima'),
    estraverse = require('estraverse'),
    escodegen = require('escodegen');
function analyzeCode(code) {
    var ast = esprima.parse(code);
    //console.log(JSON.stringify(ast,null,4));
    ast = estraverse.replace(ast, {
        leave: function(node, parent)
        {
            modifiedNode = node;
            if (node.type === 'IfStatement') {
                if (node.consequent != null && node.consequent.type === 'ExpressionStatement') 
                {
                    if (node.consequent.expression.type === 'Literal'){
                            modifiedNode['consequent'] = {
                                        "type": "ExpressionStatement",
                                        "expression": {
                                            "type": "AssignmentExpression",
                                            "operator": "=",
                                            "left": {
                                                "type": "Identifier",
                                                "name": "result"
                                            },
                                            "right": node.consequent.expression
                                        }
                                    }
                    };
                    if (node.alternate != null && node.alternate.expression.type === 'Literal'){
                            modifiedNode['alternate'] = {
                                        "type": "ExpressionStatement",
                                        "expression": {
                                            "type": "AssignmentExpression",
                                            "operator": "=",
                                            "left": {
                                                "type": "Identifier",
                                                "name": "result"
                                            },
                                            "right": node.alternate.expression
                                        }
                                    }
                    };
                }
            };
            return modifiedNode;
        }
    });
    var modifiedCode = escodegen.generate(ast);
    console.log('=============');
    console.log(modifiedCode);
    //console.log(JSON.stringify(ast,null,4));
}
if (process.argv.length < 3) {
    console.log('Usage: zz.js file.js');
    process.exit(1);
}
var filename = process.argv[2];
console.log('Reading ' + filename);
var code = fs.readFileSync(filename);
console.log('=============');
console.log(''+code);
analyzeCode(code);
console.log('Done');
--------------
           
test1.js
if (var1 > 2) result = 3;
else result = 0;
if(var2 < 3) 0
else 1
if (var3 === 9) 1
           

8)

各种语言用来修改ast语法树的一些方法收集见:

http://adamrehn.com/articles/ast-instrumentation-examples-by-language#sec___javascript

版权声明:本文为CSDN博主「weixin_33826609」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_33826609/article/details/91671473

继续阅读