Serialize ast.AST nodes to the JSON schema expected by the Rust core.
| 12 | |
| 13 | |
| 14 | class AstEncoder(json.JSONEncoder): |
| 15 | """Serialize ast.AST nodes to the JSON schema expected by the Rust core.""" |
| 16 | |
| 17 | def default(self, node: Any) -> Any: |
| 18 | if isinstance(node, ast.AST): |
| 19 | out: Dict[str, Any] = { |
| 20 | "node_type": node.__class__.__name__, |
| 21 | "lineno": getattr(node, "lineno", -1), |
| 22 | "col_offset": getattr(node, "col_offset", -1), |
| 23 | } |
| 24 | child_nodes: Dict[str, Any] = {} |
| 25 | simple_fields: Dict[str, Any] = {} |
| 26 | for fname, value in ast.iter_fields(node): |
| 27 | if type(value) is list: |
| 28 | if value and all(isinstance(n, ast.AST) for n in value): |
| 29 | child_nodes[fname] = value |
| 30 | else: |
| 31 | simple_fields[fname] = str(value) if value else [] |
| 32 | elif isinstance(value, ast.AST): |
| 33 | child_nodes[fname] = [value] |
| 34 | else: |
| 35 | if isinstance(value, bytes): |
| 36 | simple_fields[fname] = value.decode("utf-8", errors="replace") |
| 37 | elif isinstance(value, int) and value.bit_length() > 14000: |
| 38 | simple_fields[fname] = 0 |
| 39 | elif isinstance(value, (int, float, str, bool)) or value is None: |
| 40 | simple_fields[fname] = value |
| 41 | else: |
| 42 | simple_fields[fname] = str(value) |
| 43 | out["children"] = child_nodes |
| 44 | out["fields"] = simple_fields |
| 45 | return out |
| 46 | if isinstance(node, bytes): |
| 47 | return node.decode("utf-8", errors="replace") |
| 48 | if hasattr(node, "__dict__"): |
| 49 | return str(node) |
| 50 | return super().default(node) |
| 51 | |
| 52 | |
| 53 | def encode_node(node: ast.AST) -> str: |
nothing calls this directly
no outgoing calls
no test coverage detected