How to replace and insert a new node into a ast tree using esprima for python?

225 Views Asked by At

I am having trouble trying to replace and insert a new node into the ast tree using esprima for python. There is an example on github but then it replaces all the nodes with the same node that I created but I just want one of them changed while keeping the rest of the tree intact.

from __future__ import print_function

import json
import esprima
from jscodegen_py import jscodegen

# Build a CallExpression expression statement manually:
# callee = esprima.nodes.Identifier("alert")
# args = [esprima.nodes.Literal("other alert", "'other alert'")]
# call = esprima.nodes.CallExpression(callee, args)
# other_alert = esprima.nodes.ExpressionStatement(call)

generator = jscodegen.CodeGenerator(indent = 2)
def js2ast(js: str):
    return esprima.parseScript(js)
def ast2js(ast: dict):
    return generator.generate(ast)

# Add a few expression statements using `parse()`:

af = {'Lg': {'RawString': 'var Lg = function(WN5, AN5) {\n        return WN5 > AN5;\n    };', 'RawValue': 'WN5 > AN5', 'operator': '>'}}
accessory_function_expression_statements = {}
for name in af:
    accessory_function_expression_statements[name] = esprima.parse(af[name]['RawValue']).body[0]


class MyVisitor(esprima.NodeVisitor):
    def transform_CallExpression(self, node, metadata):
        # If the callee is an `alert()`, change it to `console.log()`:
            if node.callee.name == 'Lg':
                new_node_arguments = []
                for item in node.arguments:
                    new_node_arguments.append(esprima.parse(generator.generate_expression(item.toDict(), 0)).body[0])
                new_node = accessory_function_expression_statements['Lg'].expression
                new_node.left = new_node_arguments[0].expression
                new_node.right = new_node_arguments[1].expression
                print(f'new_node: {new_node}')
                return self.transform_Object(new_node, metadata) # every time this is called it will walk down the tree from the beginning

visitor = MyVisitor()


tree = esprima.parse("""
if (Lg(GP5["length"], 5)) {
    var kP5 = window["parseInt"](GP5[5], 10);
    lP5 = window["isNaN"](kP5) || dK(hA(1), kP5) ? window["Number"]["MAX_VALUE"] : kP5,
        lP5 = kP5;
    var abc = Boolean(Lg(Jj, 21))
}
""", delegate=visitor)

print(ast2js(tree.toDict()))

But using this code it gives this result.

if (Jj > 21) {
var kP5 = window["parseInt"](GP5[5], 10);
lP5 = window["isNaN"](kP5) || dK(hA(1), kP5) ? window["Number"]["MAX_VALUE"] : kP5, lP5 = kP5;
var abc = Boolean(Jj > 21);
}

As you can see the script in the code it replaces all the ifstatements to '(Jj > 21)' but I want it like this.

if (GP5.length > 5) {
var kP5 = window["parseInt"](GP5[5], 10);
lP5 = window["isNaN"](kP5) || dK(hA(1), kP5) ? window["Number"]["MAX_VALUE"] : kP5, lP5 = kP5;
var abc = Boolean(Jj > 21);
}

How can I do this using esprima in python?

0

There are 0 best solutions below