| 81 | |
| 82 | |
| 83 | class NodeStripVisitor(TraverserVisitor, SplittingVisitor): |
| 84 | def __init__(self) -> None: |
| 85 | # The current active class. |
| 86 | self.type: TypeInfo | None = None |
| 87 | # This is True at class scope, but not in methods. |
| 88 | self.is_class_body = False |
| 89 | self.recurse_into_functions = True |
| 90 | |
| 91 | def strip_file_top_level(self, file_node: MypyFile) -> None: |
| 92 | """Strip a module top-level (don't recursive into functions).""" |
| 93 | self.recurse_into_functions = False |
| 94 | file_node.plugin_deps.clear() |
| 95 | file_node.accept(self) |
| 96 | for name in file_node.names.copy(): |
| 97 | # TODO: this is a hot fix, we should delete all names, |
| 98 | # see https://github.com/python/mypy/issues/6422. |
| 99 | if "@" not in name: |
| 100 | del file_node.names[name] |
| 101 | |
| 102 | def visit_block(self, b: Block) -> None: |
| 103 | if b.is_unreachable: |
| 104 | return |
| 105 | super().visit_block(b) |
| 106 | |
| 107 | def visit_class_def(self, node: ClassDef) -> None: |
| 108 | """Strip class body and type info, but don't strip methods.""" |
| 109 | # We need to delete any entries that were generated by plugins, |
| 110 | # since they will get regenerated. |
| 111 | to_delete = {v.node for v in node.info.names.values() if v.plugin_generated} |
| 112 | node.type_vars = [] |
| 113 | node.base_type_exprs.extend(node.removed_base_type_exprs) |
| 114 | node.removed_base_type_exprs = [] |
| 115 | node.defs.body = [ |
| 116 | s |
| 117 | for s in node.defs.body |
| 118 | if s not in to_delete # type: ignore[comparison-overlap, redundant-expr] |
| 119 | ] |
| 120 | with self.enter_class(node.info): |
| 121 | super().visit_class_def(node) |
| 122 | node.defs.body.extend(node.removed_statements) |
| 123 | node.removed_statements = [] |
| 124 | type_state.reset_subtype_caches_for(node.info) |
| 125 | # Kill the TypeInfo, since there is none before semantic analysis. |
| 126 | node.info = CLASSDEF_NO_INFO |
| 127 | node.analyzed = None |
| 128 | |
| 129 | def visit_func_def(self, node: FuncDef) -> None: |
| 130 | if not self.recurse_into_functions and not node.def_or_infer_vars: |
| 131 | return |
| 132 | node.expanded = [] |
| 133 | node.type = node.unanalyzed_type |
| 134 | if node.type: |
| 135 | # Type variable binder binds type variables before the type is analyzed, |
| 136 | # this causes unanalyzed_type to be modified in place. We needed to revert this |
| 137 | # in order to get the state exactly as it was before semantic analysis. |
| 138 | # See also #4814. |
| 139 | assert isinstance(node.type, CallableType) |
| 140 | node.type.variables = () |
no outgoing calls
no test coverage detected
searching dependent graphs…