#python #parsing #concrete-syntax-tree #libcst
Вопрос:
Я пытаюсь ввести новый узел (как новую строку кода), точно перед назначенным узлом.
Проблема возникает при использовании FlattenSentinel
для представления нового узла, так как я хочу, чтобы узел был отдельным, но libcst объединяет их с помощью точки с запятой ( ;
), пример:
a = 6
Становится:
print('returning'); a = 6
Код для воспроизведения примера:
import libcst as cst
class MyTransformer(cst.CSTTransformer):
def leave_Assign(self, old_node, updated_node):
log_stmt = cst.Expr(cst.parse_expression("print('returning')"))
return cst.FlattenSentinel([log_stmt, updated_node])
source_tree = cst.parse_module("a = 6")
modified_tree = source_tree.visit(MyTransformer())
print(modified_tree.code)
Я также попытался ввести новую строку, но это выглядит еще хуже, пример кода:
def leave_Assign(self, old_node, updated_node):
log_stmt = cst.Expr(cst.parse_expression("print('returning')"))
return cst.FlattenSentinel([log_stmt, cst.Expr(cst.Newline()), updated_node])
Моим желаемым результатом было бы вставить новый узел над существующим узлом (на том же уровне ), без точки с запятой, как это:
print('returning')
a = 6
Возможно ли это в libcst?
Ответ №1:
Твой АСТ такой:
Module
FunctionDef
SimpleStatementLine
Assign
Target
Integer
Когда вы пытаетесь заменить назначение несколькими узлами, вам все равно нужно соблюдать текущую строку, которая заставляет точки с запятой.
Module
FunctionDef
SimpleStatementLine
Call // Your print call
Assign // a = 6
Target
Integer
Вместо этого вы хотите заменить родительский SimpleStatementLine
FlattenSentinel
элемент на новый SimpleStatementLine
s с вашими новыми узлами. Таким образом, вам действительно нужно изменить свой код, чтобы работать дальше leave_SimpleStatementLine
.