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