Как заменить и вставить новый узел в дерево ast, используя esprima для python?
У меня возникли проблемы с попыткой заменить и вставить новый узел в дерево ast, используя esprima для python. На github есть пример, но затем он заменяет все узлы тем же узлом, который я создал, но я просто хочу изменить один из них, сохранив остальную часть дерева нетронутой.
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()))
Но использование этого кода дает такой результат.
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);
}
Как вы можете видеть, скрипт в коде заменяет все операторы if на «(Jj > 21)», но я хочу, чтобы это было так.
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);
}
Как я могу сделать это, используя esprima в python?