1"""Base visitor that implements an identity AST transform. 2 3Subclass TransformVisitor to perform non-trivial transformations. 4""" 5 6from typing import List, Dict, cast, Optional, Iterable 7 8from mypy.nodes import ( 9 MypyFile, Import, Node, ImportAll, ImportFrom, FuncItem, FuncDef, 10 OverloadedFuncDef, ClassDef, Decorator, Block, Var, 11 OperatorAssignmentStmt, ExpressionStmt, AssignmentStmt, ReturnStmt, 12 RaiseStmt, AssertStmt, DelStmt, BreakStmt, ContinueStmt, 13 PassStmt, GlobalDecl, WhileStmt, ForStmt, IfStmt, TryStmt, WithStmt, 14 CastExpr, RevealExpr, TupleExpr, GeneratorExpr, ListComprehension, ListExpr, 15 ConditionalExpr, DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, 16 UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, 17 SliceExpr, OpExpr, UnaryExpr, LambdaExpr, TypeApplication, PrintStmt, 18 SymbolTable, RefExpr, TypeVarExpr, ParamSpecExpr, NewTypeExpr, PromoteExpr, 19 ComparisonExpr, TempNode, StarExpr, Statement, Expression, 20 YieldFromExpr, NamedTupleExpr, TypedDictExpr, NonlocalDecl, SetComprehension, 21 DictionaryComprehension, ComplexExpr, TypeAliasExpr, EllipsisExpr, 22 YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr, AssignmentExpr, 23 OverloadPart, EnumCallExpr, REVEAL_TYPE, GDEF 24) 25from mypy.types import Type, FunctionLike, ProperType 26from mypy.traverser import TraverserVisitor 27from mypy.visitor import NodeVisitor 28from mypy.util import replace_object_state 29 30 31class TransformVisitor(NodeVisitor[Node]): 32 """Transform a semantically analyzed AST (or subtree) to an identical copy. 33 34 Use the node() method to transform an AST node. 35 36 Subclass to perform a non-identity transform. 37 38 Notes: 39 40 * This can only be used to transform functions or classes, not top-level 41 statements, and/or modules as a whole. 42 * Do not duplicate TypeInfo nodes. This would generally not be desirable. 43 * Only update some name binding cross-references, but only those that 44 refer to Var, Decorator or FuncDef nodes, not those targeting ClassDef or 45 TypeInfo nodes. 46 * Types are not transformed, but you can override type() to also perform 47 type transformation. 48 49 TODO nested classes and functions have not been tested well enough 50 """ 51 52 def __init__(self) -> None: 53 # To simplify testing, set this flag to True if you want to transform 54 # all statements in a file (this is prohibited in normal mode). 55 self.test_only = False 56 # There may be multiple references to a Var node. Keep track of 57 # Var translations using a dictionary. 58 self.var_map = {} # type: Dict[Var, Var] 59 # These are uninitialized placeholder nodes used temporarily for nested 60 # functions while we are transforming a top-level function. This maps an 61 # untransformed node to a placeholder (which will later become the 62 # transformed node). 63 self.func_placeholder_map = {} # type: Dict[FuncDef, FuncDef] 64 65 def visit_mypy_file(self, node: MypyFile) -> MypyFile: 66 assert self.test_only, "This visitor should not be used for whole files." 67 # NOTE: The 'names' and 'imports' instance variables will be empty! 68 ignored_lines = {line: codes[:] 69 for line, codes in node.ignored_lines.items()} 70 new = MypyFile(self.statements(node.defs), [], node.is_bom, 71 ignored_lines=ignored_lines) 72 new._fullname = node._fullname 73 new.path = node.path 74 new.names = SymbolTable() 75 return new 76 77 def visit_import(self, node: Import) -> Import: 78 return Import(node.ids[:]) 79 80 def visit_import_from(self, node: ImportFrom) -> ImportFrom: 81 return ImportFrom(node.id, node.relative, node.names[:]) 82 83 def visit_import_all(self, node: ImportAll) -> ImportAll: 84 return ImportAll(node.id, node.relative) 85 86 def copy_argument(self, argument: Argument) -> Argument: 87 arg = Argument( 88 self.visit_var(argument.variable), 89 argument.type_annotation, 90 argument.initializer, 91 argument.kind, 92 ) 93 94 # Refresh lines of the inner things 95 arg.set_line(argument.line) 96 97 return arg 98 99 def visit_func_def(self, node: FuncDef) -> FuncDef: 100 # Note that a FuncDef must be transformed to a FuncDef. 101 102 # These contortions are needed to handle the case of recursive 103 # references inside the function being transformed. 104 # Set up placeholder nodes for references within this function 105 # to other functions defined inside it. 106 # Don't create an entry for this function itself though, 107 # since we want self-references to point to the original 108 # function if this is the top-level node we are transforming. 109 init = FuncMapInitializer(self) 110 for stmt in node.body.body: 111 stmt.accept(init) 112 113 new = FuncDef(node.name, 114 [self.copy_argument(arg) for arg in node.arguments], 115 self.block(node.body), 116 cast(Optional[FunctionLike], self.optional_type(node.type))) 117 118 self.copy_function_attributes(new, node) 119 120 new._fullname = node._fullname 121 new.is_decorated = node.is_decorated 122 new.is_conditional = node.is_conditional 123 new.is_abstract = node.is_abstract 124 new.is_static = node.is_static 125 new.is_class = node.is_class 126 new.is_property = node.is_property 127 new.is_final = node.is_final 128 new.original_def = node.original_def 129 130 if node in self.func_placeholder_map: 131 # There is a placeholder definition for this function. Replace 132 # the attributes of the placeholder with those form the transformed 133 # function. We know that the classes will be identical (otherwise 134 # this wouldn't work). 135 result = self.func_placeholder_map[node] 136 replace_object_state(result, new) 137 return result 138 else: 139 return new 140 141 def visit_lambda_expr(self, node: LambdaExpr) -> LambdaExpr: 142 new = LambdaExpr([self.copy_argument(arg) for arg in node.arguments], 143 self.block(node.body), 144 cast(Optional[FunctionLike], self.optional_type(node.type))) 145 self.copy_function_attributes(new, node) 146 return new 147 148 def copy_function_attributes(self, new: FuncItem, 149 original: FuncItem) -> None: 150 new.info = original.info 151 new.min_args = original.min_args 152 new.max_pos = original.max_pos 153 new.is_overload = original.is_overload 154 new.is_generator = original.is_generator 155 new.line = original.line 156 157 def visit_overloaded_func_def(self, node: OverloadedFuncDef) -> OverloadedFuncDef: 158 items = [cast(OverloadPart, item.accept(self)) for item in node.items] 159 for newitem, olditem in zip(items, node.items): 160 newitem.line = olditem.line 161 new = OverloadedFuncDef(items) 162 new._fullname = node._fullname 163 new_type = self.optional_type(node.type) 164 assert isinstance(new_type, ProperType) 165 new.type = new_type 166 new.info = node.info 167 new.is_static = node.is_static 168 new.is_class = node.is_class 169 new.is_property = node.is_property 170 new.is_final = node.is_final 171 if node.impl: 172 new.impl = cast(OverloadPart, node.impl.accept(self)) 173 return new 174 175 def visit_class_def(self, node: ClassDef) -> ClassDef: 176 new = ClassDef(node.name, 177 self.block(node.defs), 178 node.type_vars, 179 self.expressions(node.base_type_exprs), 180 self.optional_expr(node.metaclass)) 181 new.fullname = node.fullname 182 new.info = node.info 183 new.decorators = [self.expr(decorator) 184 for decorator in node.decorators] 185 return new 186 187 def visit_global_decl(self, node: GlobalDecl) -> GlobalDecl: 188 return GlobalDecl(node.names[:]) 189 190 def visit_nonlocal_decl(self, node: NonlocalDecl) -> NonlocalDecl: 191 return NonlocalDecl(node.names[:]) 192 193 def visit_block(self, node: Block) -> Block: 194 return Block(self.statements(node.body)) 195 196 def visit_decorator(self, node: Decorator) -> Decorator: 197 # Note that a Decorator must be transformed to a Decorator. 198 func = self.visit_func_def(node.func) 199 func.line = node.func.line 200 new = Decorator(func, self.expressions(node.decorators), 201 self.visit_var(node.var)) 202 new.is_overload = node.is_overload 203 return new 204 205 def visit_var(self, node: Var) -> Var: 206 # Note that a Var must be transformed to a Var. 207 if node in self.var_map: 208 return self.var_map[node] 209 new = Var(node.name, self.optional_type(node.type)) 210 new.line = node.line 211 new._fullname = node._fullname 212 new.info = node.info 213 new.is_self = node.is_self 214 new.is_ready = node.is_ready 215 new.is_initialized_in_class = node.is_initialized_in_class 216 new.is_staticmethod = node.is_staticmethod 217 new.is_classmethod = node.is_classmethod 218 new.is_property = node.is_property 219 new.is_final = node.is_final 220 new.final_value = node.final_value 221 new.final_unset_in_class = node.final_unset_in_class 222 new.final_set_in_init = node.final_set_in_init 223 new.set_line(node.line) 224 self.var_map[node] = new 225 return new 226 227 def visit_expression_stmt(self, node: ExpressionStmt) -> ExpressionStmt: 228 return ExpressionStmt(self.expr(node.expr)) 229 230 def visit_assignment_stmt(self, node: AssignmentStmt) -> AssignmentStmt: 231 return self.duplicate_assignment(node) 232 233 def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt: 234 new = AssignmentStmt(self.expressions(node.lvalues), 235 self.expr(node.rvalue), 236 self.optional_type(node.unanalyzed_type)) 237 new.line = node.line 238 new.is_final_def = node.is_final_def 239 new.type = self.optional_type(node.type) 240 return new 241 242 def visit_operator_assignment_stmt(self, 243 node: OperatorAssignmentStmt) -> OperatorAssignmentStmt: 244 return OperatorAssignmentStmt(node.op, 245 self.expr(node.lvalue), 246 self.expr(node.rvalue)) 247 248 def visit_while_stmt(self, node: WhileStmt) -> WhileStmt: 249 return WhileStmt(self.expr(node.expr), 250 self.block(node.body), 251 self.optional_block(node.else_body)) 252 253 def visit_for_stmt(self, node: ForStmt) -> ForStmt: 254 new = ForStmt(self.expr(node.index), 255 self.expr(node.expr), 256 self.block(node.body), 257 self.optional_block(node.else_body), 258 self.optional_type(node.unanalyzed_index_type)) 259 new.is_async = node.is_async 260 new.index_type = self.optional_type(node.index_type) 261 return new 262 263 def visit_return_stmt(self, node: ReturnStmt) -> ReturnStmt: 264 return ReturnStmt(self.optional_expr(node.expr)) 265 266 def visit_assert_stmt(self, node: AssertStmt) -> AssertStmt: 267 return AssertStmt(self.expr(node.expr), self.optional_expr(node.msg)) 268 269 def visit_del_stmt(self, node: DelStmt) -> DelStmt: 270 return DelStmt(self.expr(node.expr)) 271 272 def visit_if_stmt(self, node: IfStmt) -> IfStmt: 273 return IfStmt(self.expressions(node.expr), 274 self.blocks(node.body), 275 self.optional_block(node.else_body)) 276 277 def visit_break_stmt(self, node: BreakStmt) -> BreakStmt: 278 return BreakStmt() 279 280 def visit_continue_stmt(self, node: ContinueStmt) -> ContinueStmt: 281 return ContinueStmt() 282 283 def visit_pass_stmt(self, node: PassStmt) -> PassStmt: 284 return PassStmt() 285 286 def visit_raise_stmt(self, node: RaiseStmt) -> RaiseStmt: 287 return RaiseStmt(self.optional_expr(node.expr), 288 self.optional_expr(node.from_expr)) 289 290 def visit_try_stmt(self, node: TryStmt) -> TryStmt: 291 return TryStmt(self.block(node.body), 292 self.optional_names(node.vars), 293 self.optional_expressions(node.types), 294 self.blocks(node.handlers), 295 self.optional_block(node.else_body), 296 self.optional_block(node.finally_body)) 297 298 def visit_with_stmt(self, node: WithStmt) -> WithStmt: 299 new = WithStmt(self.expressions(node.expr), 300 self.optional_expressions(node.target), 301 self.block(node.body), 302 self.optional_type(node.unanalyzed_type)) 303 new.is_async = node.is_async 304 new.analyzed_types = [self.type(typ) for typ in node.analyzed_types] 305 return new 306 307 def visit_print_stmt(self, node: PrintStmt) -> PrintStmt: 308 return PrintStmt(self.expressions(node.args), 309 node.newline, 310 self.optional_expr(node.target)) 311 312 def visit_exec_stmt(self, node: ExecStmt) -> ExecStmt: 313 return ExecStmt(self.expr(node.expr), 314 self.optional_expr(node.globals), 315 self.optional_expr(node.locals)) 316 317 def visit_star_expr(self, node: StarExpr) -> StarExpr: 318 return StarExpr(node.expr) 319 320 def visit_int_expr(self, node: IntExpr) -> IntExpr: 321 return IntExpr(node.value) 322 323 def visit_str_expr(self, node: StrExpr) -> StrExpr: 324 return StrExpr(node.value, node.from_python_3) 325 326 def visit_bytes_expr(self, node: BytesExpr) -> BytesExpr: 327 return BytesExpr(node.value) 328 329 def visit_unicode_expr(self, node: UnicodeExpr) -> UnicodeExpr: 330 return UnicodeExpr(node.value) 331 332 def visit_float_expr(self, node: FloatExpr) -> FloatExpr: 333 return FloatExpr(node.value) 334 335 def visit_complex_expr(self, node: ComplexExpr) -> ComplexExpr: 336 return ComplexExpr(node.value) 337 338 def visit_ellipsis(self, node: EllipsisExpr) -> EllipsisExpr: 339 return EllipsisExpr() 340 341 def visit_name_expr(self, node: NameExpr) -> NameExpr: 342 return self.duplicate_name(node) 343 344 def duplicate_name(self, node: NameExpr) -> NameExpr: 345 # This method is used when the transform result must be a NameExpr. 346 # visit_name_expr() is used when there is no such restriction. 347 new = NameExpr(node.name) 348 self.copy_ref(new, node) 349 new.is_special_form = node.is_special_form 350 return new 351 352 def visit_member_expr(self, node: MemberExpr) -> MemberExpr: 353 member = MemberExpr(self.expr(node.expr), 354 node.name) 355 if node.def_var: 356 # This refers to an attribute and we don't transform attributes by default, 357 # just normal variables. 358 member.def_var = node.def_var 359 self.copy_ref(member, node) 360 return member 361 362 def copy_ref(self, new: RefExpr, original: RefExpr) -> None: 363 new.kind = original.kind 364 new.fullname = original.fullname 365 target = original.node 366 if isinstance(target, Var): 367 # Do not transform references to global variables. See 368 # testGenericFunctionAliasExpand for an example where this is important. 369 if original.kind != GDEF: 370 target = self.visit_var(target) 371 elif isinstance(target, Decorator): 372 target = self.visit_var(target.var) 373 elif isinstance(target, FuncDef): 374 # Use a placeholder node for the function if it exists. 375 target = self.func_placeholder_map.get(target, target) 376 new.node = target 377 new.is_new_def = original.is_new_def 378 new.is_inferred_def = original.is_inferred_def 379 380 def visit_yield_from_expr(self, node: YieldFromExpr) -> YieldFromExpr: 381 return YieldFromExpr(self.expr(node.expr)) 382 383 def visit_yield_expr(self, node: YieldExpr) -> YieldExpr: 384 return YieldExpr(self.optional_expr(node.expr)) 385 386 def visit_await_expr(self, node: AwaitExpr) -> AwaitExpr: 387 return AwaitExpr(self.expr(node.expr)) 388 389 def visit_call_expr(self, node: CallExpr) -> CallExpr: 390 return CallExpr(self.expr(node.callee), 391 self.expressions(node.args), 392 node.arg_kinds[:], 393 node.arg_names[:], 394 self.optional_expr(node.analyzed)) 395 396 def visit_op_expr(self, node: OpExpr) -> OpExpr: 397 new = OpExpr(node.op, self.expr(node.left), self.expr(node.right)) 398 new.method_type = self.optional_type(node.method_type) 399 return new 400 401 def visit_comparison_expr(self, node: ComparisonExpr) -> ComparisonExpr: 402 new = ComparisonExpr(node.operators, self.expressions(node.operands)) 403 new.method_types = [self.optional_type(t) for t in node.method_types] 404 return new 405 406 def visit_cast_expr(self, node: CastExpr) -> CastExpr: 407 return CastExpr(self.expr(node.expr), 408 self.type(node.type)) 409 410 def visit_reveal_expr(self, node: RevealExpr) -> RevealExpr: 411 if node.kind == REVEAL_TYPE: 412 assert node.expr is not None 413 return RevealExpr(kind=REVEAL_TYPE, expr=self.expr(node.expr)) 414 else: 415 # Reveal locals expressions don't have any sub expressions 416 return node 417 418 def visit_super_expr(self, node: SuperExpr) -> SuperExpr: 419 call = self.expr(node.call) 420 assert isinstance(call, CallExpr) 421 new = SuperExpr(node.name, call) 422 new.info = node.info 423 return new 424 425 def visit_assignment_expr(self, node: AssignmentExpr) -> AssignmentExpr: 426 return AssignmentExpr(node.target, node.value) 427 428 def visit_unary_expr(self, node: UnaryExpr) -> UnaryExpr: 429 new = UnaryExpr(node.op, self.expr(node.expr)) 430 new.method_type = self.optional_type(node.method_type) 431 return new 432 433 def visit_list_expr(self, node: ListExpr) -> ListExpr: 434 return ListExpr(self.expressions(node.items)) 435 436 def visit_dict_expr(self, node: DictExpr) -> DictExpr: 437 return DictExpr([(self.expr(key) if key else None, self.expr(value)) 438 for key, value in node.items]) 439 440 def visit_tuple_expr(self, node: TupleExpr) -> TupleExpr: 441 return TupleExpr(self.expressions(node.items)) 442 443 def visit_set_expr(self, node: SetExpr) -> SetExpr: 444 return SetExpr(self.expressions(node.items)) 445 446 def visit_index_expr(self, node: IndexExpr) -> IndexExpr: 447 new = IndexExpr(self.expr(node.base), self.expr(node.index)) 448 if node.method_type: 449 new.method_type = self.type(node.method_type) 450 if node.analyzed: 451 if isinstance(node.analyzed, TypeApplication): 452 new.analyzed = self.visit_type_application(node.analyzed) 453 else: 454 new.analyzed = self.visit_type_alias_expr(node.analyzed) 455 new.analyzed.set_line(node.analyzed.line) 456 return new 457 458 def visit_type_application(self, node: TypeApplication) -> TypeApplication: 459 return TypeApplication(self.expr(node.expr), 460 self.types(node.types)) 461 462 def visit_list_comprehension(self, node: ListComprehension) -> ListComprehension: 463 generator = self.duplicate_generator(node.generator) 464 generator.set_line(node.generator.line, node.generator.column) 465 return ListComprehension(generator) 466 467 def visit_set_comprehension(self, node: SetComprehension) -> SetComprehension: 468 generator = self.duplicate_generator(node.generator) 469 generator.set_line(node.generator.line, node.generator.column) 470 return SetComprehension(generator) 471 472 def visit_dictionary_comprehension(self, node: DictionaryComprehension 473 ) -> DictionaryComprehension: 474 return DictionaryComprehension(self.expr(node.key), self.expr(node.value), 475 [self.expr(index) for index in node.indices], 476 [self.expr(s) for s in node.sequences], 477 [[self.expr(cond) for cond in conditions] 478 for conditions in node.condlists], 479 node.is_async) 480 481 def visit_generator_expr(self, node: GeneratorExpr) -> GeneratorExpr: 482 return self.duplicate_generator(node) 483 484 def duplicate_generator(self, node: GeneratorExpr) -> GeneratorExpr: 485 return GeneratorExpr(self.expr(node.left_expr), 486 [self.expr(index) for index in node.indices], 487 [self.expr(s) for s in node.sequences], 488 [[self.expr(cond) for cond in conditions] 489 for conditions in node.condlists], 490 node.is_async) 491 492 def visit_slice_expr(self, node: SliceExpr) -> SliceExpr: 493 return SliceExpr(self.optional_expr(node.begin_index), 494 self.optional_expr(node.end_index), 495 self.optional_expr(node.stride)) 496 497 def visit_conditional_expr(self, node: ConditionalExpr) -> ConditionalExpr: 498 return ConditionalExpr(self.expr(node.cond), 499 self.expr(node.if_expr), 500 self.expr(node.else_expr)) 501 502 def visit_backquote_expr(self, node: BackquoteExpr) -> BackquoteExpr: 503 return BackquoteExpr(self.expr(node.expr)) 504 505 def visit_type_var_expr(self, node: TypeVarExpr) -> TypeVarExpr: 506 return TypeVarExpr(node.name, node.fullname, 507 self.types(node.values), 508 self.type(node.upper_bound), variance=node.variance) 509 510 def visit_paramspec_expr(self, node: ParamSpecExpr) -> ParamSpecExpr: 511 return ParamSpecExpr( 512 node.name, node.fullname, self.type(node.upper_bound), variance=node.variance 513 ) 514 515 def visit_type_alias_expr(self, node: TypeAliasExpr) -> TypeAliasExpr: 516 return TypeAliasExpr(node.node) 517 518 def visit_newtype_expr(self, node: NewTypeExpr) -> NewTypeExpr: 519 res = NewTypeExpr(node.name, node.old_type, line=node.line, column=node.column) 520 res.info = node.info 521 return res 522 523 def visit_namedtuple_expr(self, node: NamedTupleExpr) -> NamedTupleExpr: 524 return NamedTupleExpr(node.info) 525 526 def visit_enum_call_expr(self, node: EnumCallExpr) -> EnumCallExpr: 527 return EnumCallExpr(node.info, node.items, node.values) 528 529 def visit_typeddict_expr(self, node: TypedDictExpr) -> Node: 530 return TypedDictExpr(node.info) 531 532 def visit__promote_expr(self, node: PromoteExpr) -> PromoteExpr: 533 return PromoteExpr(node.type) 534 535 def visit_temp_node(self, node: TempNode) -> TempNode: 536 return TempNode(self.type(node.type)) 537 538 def node(self, node: Node) -> Node: 539 new = node.accept(self) 540 new.set_line(node.line) 541 return new 542 543 def mypyfile(self, node: MypyFile) -> MypyFile: 544 new = node.accept(self) 545 assert isinstance(new, MypyFile) 546 new.set_line(node.line) 547 return new 548 549 def expr(self, expr: Expression) -> Expression: 550 new = expr.accept(self) 551 assert isinstance(new, Expression) 552 new.set_line(expr.line, expr.column) 553 return new 554 555 def stmt(self, stmt: Statement) -> Statement: 556 new = stmt.accept(self) 557 assert isinstance(new, Statement) 558 new.set_line(stmt.line, stmt.column) 559 return new 560 561 # Helpers 562 # 563 # All the node helpers also propagate line numbers. 564 565 def optional_expr(self, expr: Optional[Expression]) -> Optional[Expression]: 566 if expr: 567 return self.expr(expr) 568 else: 569 return None 570 571 def block(self, block: Block) -> Block: 572 new = self.visit_block(block) 573 new.line = block.line 574 return new 575 576 def optional_block(self, block: Optional[Block]) -> Optional[Block]: 577 if block: 578 return self.block(block) 579 else: 580 return None 581 582 def statements(self, statements: List[Statement]) -> List[Statement]: 583 return [self.stmt(stmt) for stmt in statements] 584 585 def expressions(self, expressions: List[Expression]) -> List[Expression]: 586 return [self.expr(expr) for expr in expressions] 587 588 def optional_expressions(self, expressions: Iterable[Optional[Expression]] 589 ) -> List[Optional[Expression]]: 590 return [self.optional_expr(expr) for expr in expressions] 591 592 def blocks(self, blocks: List[Block]) -> List[Block]: 593 return [self.block(block) for block in blocks] 594 595 def names(self, names: List[NameExpr]) -> List[NameExpr]: 596 return [self.duplicate_name(name) for name in names] 597 598 def optional_names(self, names: Iterable[Optional[NameExpr]]) -> List[Optional[NameExpr]]: 599 result = [] # type: List[Optional[NameExpr]] 600 for name in names: 601 if name: 602 result.append(self.duplicate_name(name)) 603 else: 604 result.append(None) 605 return result 606 607 def type(self, type: Type) -> Type: 608 # Override this method to transform types. 609 return type 610 611 def optional_type(self, type: Optional[Type]) -> Optional[Type]: 612 if type: 613 return self.type(type) 614 else: 615 return None 616 617 def types(self, types: List[Type]) -> List[Type]: 618 return [self.type(type) for type in types] 619 620 621class FuncMapInitializer(TraverserVisitor): 622 """This traverser creates mappings from nested FuncDefs to placeholder FuncDefs. 623 624 The placeholders will later be replaced with transformed nodes. 625 """ 626 627 def __init__(self, transformer: TransformVisitor) -> None: 628 self.transformer = transformer 629 630 def visit_func_def(self, node: FuncDef) -> None: 631 if node not in self.transformer.func_placeholder_map: 632 # Haven't seen this FuncDef before, so create a placeholder node. 633 self.transformer.func_placeholder_map[node] = FuncDef( 634 node.name, node.arguments, node.body, None) 635 super().visit_func_def(node) 636