【问题标题】:Error generating code with escodegen after node removal删除节点后使用 escodegen 生成代码时出错
【发布时间】:2018-01-05 23:24:47
【问题描述】:

首先我创建了一个esprima AST,然后我想使用estraverse 删除一个节点,最后使用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 中的错误?

提前致谢。

【问题讨论】:

    标签: javascript node.js esprima escodegen estraverse


    【解决方案1】:

    我在 github 上放了一个issue,我得到了一个答案,我正在制作一个无效的 AST。

    删除 CallExpression 会导致其父 ExpressionStatement 为空,因此无效。解决方案就是删除 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');
    

    【讨论】:

    • 添加了一个小技巧(done 的东西),因为我无法删除节点并在同一步骤中中断。
    猜你喜欢
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 2022-12-30
    • 2020-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多