2017-07-30 29 views
0

首先我創建了一個esprima AST,然後我想用estraverse刪除一個節點,最後用escodegen重新生成代碼。 但我得到一個錯誤。在刪除節點後用escodegen生成代碼時出錯

我想要的代碼是:

var esprima = require('esprima'); 
var estraverse = require('estraverse'); 
var escodegen = require('escodegen'); 

(function() { 
//build an ast with 2 lines of code 
var ast = esprima.parse("console.log('1');\n console.log('2');") 
console.log("original code:\n" + escodegen.generate(ast)); 
console.log(); 

//change one of the lines, works 
ast = estraverse.replace(ast, { 
    enter: function (node) { 
    }, 
    leave: function (node) { 
    if (node.type === esprima.Syntax.CallExpression) { 
     this.break(); 
     return esprima.parse("console.log('patch');").body[0].expression; 
    } 
    } 
}); 
console.log("patched code:\n" + escodegen.generate(ast)); 
console.log(); 

//remove one of the lines, error 
ast = estraverse.replace(ast, { 
    enter: function (node) { 
    }, 
    leave: function (node) { 
    if (node.type === esprima.Syntax.CallExpression) { 
     this.break(); 
     return this.remove(); 
    } 
    } 
}); 
console.log("removed node:\n" + escodegen.generate(ast)); 
})() 

的錯誤跟蹤:

C:\temp\node_modules\escodegen\escodegen.js:2450 
     type = expr.type || Syntax.Property; 
       ^

TypeError: Cannot read property 'type' of null 
    at CodeGenerator.generateExpression (C:\temp\node_modules\escodegen\escodegen.js:2450:20) 
    at CodeGenerator.ExpressionStatement (C:\temp\node_modules\escodegen\escodegen.js:1335:28) 
    at CodeGenerator.generateStatement (C:\temp\node_modules\escodegen\escodegen.js:2469:33) 
    at CodeGenerator.Program (C:\temp\node_modules\escodegen\escodegen.js:1717:43) 
    at CodeGenerator.generateStatement (C:\temp\node_modules\escodegen\escodegen.js:2469:33) 
    at generateInternal (C:\temp\node_modules\escodegen\escodegen.js:2490:28) 
    at Object.generate (C:\temp\node_modules\escodegen\escodegen.js:2558:18) 
    at C:\temp\bug1.js:35:45 
    at Object.<anonymous> (C:\temp\bug1.js:38:3) 
    at Module._compile (module.js:570:32) 

難道我做錯了什麼?這是escodegen還是estraverse的錯誤?

在此先感謝。

回答

0

我把一個issue在github上,我得到了一個答案,我正在做一個無效的AST。

刪除CallExpression時,他的父表達式語句留空,因此無效。解決方案是簡單地刪除ExpressionStatement。

此代碼按預期工作:

var esprima = require('esprima'); 
var estraverse = require('estraverse'); 
var escodegen = require('escodegen'); 

(function() { 
    //build an ast with 2 lines of code 
    var ast = esprima.parse("console.log('1');\n console.log('2');") 
    console.log("original code:\n" + escodegen.generate(ast)); 
    console.log(); 

    //remove one of the lines, works! 
    var done = false; 
    ast = estraverse.replace(ast, { 
    enter: function (node) { 
     if (done) 
     return this.break(); 
     if (node.type === esprima.Syntax.ExpressionStatement) { 
     done = true; 
     this.remove(); 
     } 
    }, 
    leave: function (node) { 
     if (done) 
     return this.break(); 
    } 
    }); 
    console.log("removed node:\n" + escodegen.generate(ast)); 
})() 

輸出:

original code: 
console.log('1'); 
console.log('2'); 

removed node: 
console.log('2'); 
+0

一個小技巧加入(在'done'東西),因爲我無法刪除節點,在打破同一步驟。 – fonkap