benjamn / ast-types

Esprima-compatible implementation of the Mozilla JS Parser API

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for immutable AST modification

Pauan opened this issue · comments

commented

Right now you can use types.visit which will traverse over the AST, and then you can mutate the AST in whatever way you want.

This works fine, and most of the time it's what you want, but sometimes you want to return a new AST which is exactly like an existing AST but with certain things changed.

So I propose a new types.map function, which has a similar API as types.visit, except that in addition to visiting the existing AST, it also returns a fresh new AST:

var newAST = types.map(oldAST, {
  visitIdentifier: function (path) {
    this.traverse(path);

    return {
      type: "Identifier",
      name: path.node.name.toUpperCase(),
      loc: path.node.loc
    };
  }
});

In the above example, the types.map function will traverse over oldAST, and when it encounters an Identifier it will call the visitIdentifier method, which returns a new Identifier.

Therefore the newAST variable contains an AST which is exactly the same as oldAST except that all Identifiers have been replaced by the return value of the visitIdentifier method.

This does not modify oldAST, instead it creates a fresh AST. And it should work no matter how deeply nested the Identifier is in oldAST.

This makes it quite easy to non-destructively update an AST, even if the modification is buried deep in the AST.