| 1448 | scope_closure=field(default=None) |
| 1449 | ) |
| 1450 | class Context: |
| 1451 | __slots__ = ( |
| 1452 | "node", "parent", "replace", |
| 1453 | "visitor", "stack", "depth", |
| 1454 | "modified", "shared_state", "scope_closure" |
| 1455 | ) |
| 1456 | |
| 1457 | node: NodeType |
| 1458 | parent: typing.Union[Context, None] |
| 1459 | # can_replace: bool = True |
| 1460 | replace: typing.Callable[[NodeType], None] |
| 1461 | visitor: typing.Any # FIXME typing |
| 1462 | stack: Stack |
| 1463 | depth: int |
| 1464 | modified: bool |
| 1465 | shared_state: dict |
| 1466 | scope_closure: typing.Optional[ASTNode] |
| 1467 | |
| 1468 | @property |
| 1469 | def call_graph(self): |
| 1470 | return self.visitor.call_graph |
| 1471 | |
| 1472 | @property |
| 1473 | def signature(self) -> str: |
| 1474 | return f"{self.visitor.normalized_path}:{self.node.line_no}" |
| 1475 | |
| 1476 | def as_child(self, node: NodeType, replace=lambda x: None) -> Context: |
| 1477 | return Context( |
| 1478 | parent=self, |
| 1479 | node=node, |
| 1480 | depth=self.depth + 1, |
| 1481 | visitor=self.visitor, |
| 1482 | replace=replace, |
| 1483 | stack=self.stack, |
| 1484 | shared_state=self.shared_state, |
| 1485 | scope_closure=self.scope_closure |
| 1486 | ) |
| 1487 | |
| 1488 | def visit_child(self, node, stack=None, replace=lambda x: None, closure=None): |
| 1489 | if type(node) in (str, int, type(...)) or node is None or node == ...: |
| 1490 | return |
| 1491 | |
| 1492 | new_context = self.as_child(node, replace=replace) |
| 1493 | if stack is not None: |
| 1494 | new_context.stack = stack |
| 1495 | if closure is not None: |
| 1496 | new_context.scope_closure = closure |
| 1497 | new_context.visitor.push(new_context) |
| 1498 | |
| 1499 | |
| 1500 | def to_json(element): |