|
16 | 16 | Semantic analysis is the first analysis pass after parsing, and it is |
17 | 17 | subdivided into three passes: |
18 | 18 |
|
19 | | - * SemanticAnalyzerPass1 looks up externally visible names defined in a |
20 | | - module but ignores imports and local definitions. It helps enable |
21 | | - (some) cyclic references between modules, such as module 'a' that |
22 | | - imports module 'b' and used names defined in b *and* vice versa. The |
23 | | - first pass can be performed before dependent modules have been |
24 | | - processed. |
| 19 | + * SemanticAnalyzerPass1 is defined in mypy.semanal_pass1. |
25 | 20 |
|
26 | 21 | * SemanticAnalyzerPass2 is the second pass. It does the bulk of the work. |
27 | 22 | It assumes that dependent modules have been semantically analyzed, |
@@ -3800,275 +3795,6 @@ def accept(self, node: Node) -> None: |
3800 | 3795 | report_internal_error(err, self.errors.file, node.line, self.errors, self.options) |
3801 | 3796 |
|
3802 | 3797 |
|
3803 | | -class SemanticAnalyzerPass1(NodeVisitor[None]): |
3804 | | - """First phase of semantic analysis. |
3805 | | -
|
3806 | | - See docstring of 'analyze()' below for a description of what this does. |
3807 | | - """ |
3808 | | - |
3809 | | - def __init__(self, sem: SemanticAnalyzerPass2) -> None: |
3810 | | - self.sem = sem |
3811 | | - |
3812 | | - def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) -> None: |
3813 | | - """Perform the first analysis pass. |
3814 | | -
|
3815 | | - Populate module global table. Resolve the full names of |
3816 | | - definitions not nested within functions and construct type |
3817 | | - info structures, but do not resolve inter-definition |
3818 | | - references such as base classes. |
3819 | | -
|
3820 | | - Also add implicit definitions such as __name__. |
3821 | | -
|
3822 | | - In this phase we don't resolve imports. For 'from ... import', |
3823 | | - we generate dummy symbol table nodes for the imported names, |
3824 | | - and these will get resolved in later phases of semantic |
3825 | | - analysis. |
3826 | | - """ |
3827 | | - sem = self.sem |
3828 | | - self.sem.options = options # Needed because we sometimes call into it |
3829 | | - self.pyversion = options.python_version |
3830 | | - self.platform = options.platform |
3831 | | - sem.cur_mod_id = mod_id |
3832 | | - sem.errors.set_file(fnam, mod_id) |
3833 | | - sem.globals = SymbolTable() |
3834 | | - sem.global_decls = [set()] |
3835 | | - sem.nonlocal_decls = [set()] |
3836 | | - sem.block_depth = [0] |
3837 | | - |
3838 | | - defs = file.defs |
3839 | | - |
3840 | | - with experiments.strict_optional_set(options.strict_optional): |
3841 | | - # Add implicit definitions of module '__name__' etc. |
3842 | | - for name, t in implicit_module_attrs.items(): |
3843 | | - # unicode docstrings should be accepted in Python 2 |
3844 | | - if name == '__doc__': |
3845 | | - if self.pyversion >= (3, 0): |
3846 | | - typ = UnboundType('__builtins__.str') # type: Type |
3847 | | - else: |
3848 | | - typ = UnionType([UnboundType('__builtins__.str'), |
3849 | | - UnboundType('__builtins__.unicode')]) |
3850 | | - else: |
3851 | | - assert t is not None, 'type should be specified for {}'.format(name) |
3852 | | - typ = UnboundType(t) |
3853 | | - v = Var(name, typ) |
3854 | | - v._fullname = self.sem.qualified_name(name) |
3855 | | - self.sem.globals[name] = SymbolTableNode(GDEF, v) |
3856 | | - |
3857 | | - for d in defs: |
3858 | | - d.accept(self) |
3859 | | - |
3860 | | - # Add implicit definition of literals/keywords to builtins, as we |
3861 | | - # cannot define a variable with them explicitly. |
3862 | | - if mod_id == 'builtins': |
3863 | | - literal_types = [ |
3864 | | - ('None', NoneTyp()), |
3865 | | - # reveal_type is a mypy-only function that gives an error with |
3866 | | - # the type of its arg. |
3867 | | - ('reveal_type', AnyType(TypeOfAny.special_form)), |
3868 | | - ] # type: List[Tuple[str, Type]] |
3869 | | - |
3870 | | - # TODO(ddfisher): This guard is only needed because mypy defines |
3871 | | - # fake builtins for its tests which often don't define bool. If |
3872 | | - # mypy is fast enough that we no longer need those, this |
3873 | | - # conditional check should be removed. |
3874 | | - if 'bool' in self.sem.globals: |
3875 | | - bool_type = self.sem.named_type('bool') |
3876 | | - literal_types.extend([ |
3877 | | - ('True', bool_type), |
3878 | | - ('False', bool_type), |
3879 | | - ('__debug__', bool_type), |
3880 | | - ]) |
3881 | | - else: |
3882 | | - # We are running tests without 'bool' in builtins. |
3883 | | - # TODO: Find a permanent solution to this problem. |
3884 | | - # Maybe add 'bool' to all fixtures? |
3885 | | - literal_types.append(('True', AnyType(TypeOfAny.special_form))) |
3886 | | - |
3887 | | - for name, typ in literal_types: |
3888 | | - v = Var(name, typ) |
3889 | | - v._fullname = self.sem.qualified_name(name) |
3890 | | - self.sem.globals[name] = SymbolTableNode(GDEF, v) |
3891 | | - |
3892 | | - del self.sem.options |
3893 | | - |
3894 | | - def visit_block(self, b: Block) -> None: |
3895 | | - if b.is_unreachable: |
3896 | | - return |
3897 | | - self.sem.block_depth[-1] += 1 |
3898 | | - for node in b.body: |
3899 | | - node.accept(self) |
3900 | | - self.sem.block_depth[-1] -= 1 |
3901 | | - |
3902 | | - def visit_assignment_stmt(self, s: AssignmentStmt) -> None: |
3903 | | - if self.sem.is_module_scope(): |
3904 | | - for lval in s.lvalues: |
3905 | | - self.analyze_lvalue(lval, explicit_type=s.type is not None) |
3906 | | - |
3907 | | - def visit_func_def(self, func: FuncDef) -> None: |
3908 | | - sem = self.sem |
3909 | | - func.is_conditional = sem.block_depth[-1] > 0 |
3910 | | - func._fullname = sem.qualified_name(func.name()) |
3911 | | - at_module = sem.is_module_scope() |
3912 | | - if at_module and func.name() in sem.globals: |
3913 | | - # Already defined in this module. |
3914 | | - original_sym = sem.globals[func.name()] |
3915 | | - if original_sym.kind == UNBOUND_IMPORTED: |
3916 | | - # Ah this is an imported name. We can't resolve them now, so we'll postpone |
3917 | | - # this until the main phase of semantic analysis. |
3918 | | - return |
3919 | | - if not sem.set_original_def(original_sym.node, func): |
3920 | | - # Report error. |
3921 | | - sem.check_no_global(func.name(), func) |
3922 | | - else: |
3923 | | - if at_module: |
3924 | | - sem.globals[func.name()] = SymbolTableNode(GDEF, func) |
3925 | | - # Also analyze the function body (in case there are conditional imports). |
3926 | | - sem.function_stack.append(func) |
3927 | | - sem.errors.push_function(func.name()) |
3928 | | - sem.enter() |
3929 | | - func.body.accept(self) |
3930 | | - sem.leave() |
3931 | | - sem.errors.pop_function() |
3932 | | - sem.function_stack.pop() |
3933 | | - |
3934 | | - def visit_overloaded_func_def(self, func: OverloadedFuncDef) -> None: |
3935 | | - kind = self.kind_by_scope() |
3936 | | - if kind == GDEF: |
3937 | | - self.sem.check_no_global(func.name(), func, True) |
3938 | | - func._fullname = self.sem.qualified_name(func.name()) |
3939 | | - if kind == GDEF: |
3940 | | - self.sem.globals[func.name()] = SymbolTableNode(kind, func) |
3941 | | - if func.impl: |
3942 | | - impl = func.impl |
3943 | | - # Also analyze the function body (in case there are conditional imports). |
3944 | | - sem = self.sem |
3945 | | - |
3946 | | - if isinstance(impl, FuncDef): |
3947 | | - sem.function_stack.append(impl) |
3948 | | - sem.errors.push_function(func.name()) |
3949 | | - sem.enter() |
3950 | | - impl.body.accept(self) |
3951 | | - elif isinstance(impl, Decorator): |
3952 | | - sem.function_stack.append(impl.func) |
3953 | | - sem.errors.push_function(func.name()) |
3954 | | - sem.enter() |
3955 | | - impl.func.body.accept(self) |
3956 | | - else: |
3957 | | - assert False, "Implementation of an overload needs to be FuncDef or Decorator" |
3958 | | - sem.leave() |
3959 | | - sem.errors.pop_function() |
3960 | | - sem.function_stack.pop() |
3961 | | - |
3962 | | - def visit_class_def(self, cdef: ClassDef) -> None: |
3963 | | - kind = self.kind_by_scope() |
3964 | | - if kind == LDEF: |
3965 | | - return |
3966 | | - elif kind == GDEF: |
3967 | | - self.sem.check_no_global(cdef.name, cdef) |
3968 | | - cdef.fullname = self.sem.qualified_name(cdef.name) |
3969 | | - info = TypeInfo(SymbolTable(), cdef, self.sem.cur_mod_id) |
3970 | | - info.set_line(cdef.line, cdef.column) |
3971 | | - cdef.info = info |
3972 | | - if kind == GDEF: |
3973 | | - self.sem.globals[cdef.name] = SymbolTableNode(kind, info) |
3974 | | - self.process_nested_classes(cdef) |
3975 | | - |
3976 | | - def process_nested_classes(self, outer_def: ClassDef) -> None: |
3977 | | - self.sem.enter_class(outer_def.info) |
3978 | | - for node in outer_def.defs.body: |
3979 | | - if isinstance(node, ClassDef): |
3980 | | - node.info = TypeInfo(SymbolTable(), node, self.sem.cur_mod_id) |
3981 | | - if outer_def.fullname: |
3982 | | - node.info._fullname = outer_def.fullname + '.' + node.info.name() |
3983 | | - else: |
3984 | | - node.info._fullname = node.info.name() |
3985 | | - node.fullname = node.info._fullname |
3986 | | - symbol = SymbolTableNode(MDEF, node.info) |
3987 | | - outer_def.info.names[node.name] = symbol |
3988 | | - self.process_nested_classes(node) |
3989 | | - elif isinstance(node, (ImportFrom, Import, ImportAll, IfStmt)): |
3990 | | - node.accept(self) |
3991 | | - self.sem.leave_class() |
3992 | | - |
3993 | | - def visit_import_from(self, node: ImportFrom) -> None: |
3994 | | - # We can't bind module names during the first pass, as the target module might be |
3995 | | - # unprocessed. However, we add dummy unbound imported names to the symbol table so |
3996 | | - # that we at least know that the name refers to a module. |
3997 | | - at_module = self.sem.is_module_scope() |
3998 | | - node.is_top_level = at_module |
3999 | | - if not at_module: |
4000 | | - return |
4001 | | - for name, as_name in node.names: |
4002 | | - imported_name = as_name or name |
4003 | | - if imported_name not in self.sem.globals: |
4004 | | - self.sem.add_symbol(imported_name, SymbolTableNode(UNBOUND_IMPORTED, None), node) |
4005 | | - |
4006 | | - def visit_import(self, node: Import) -> None: |
4007 | | - node.is_top_level = self.sem.is_module_scope() |
4008 | | - # This is similar to visit_import_from -- see the comment there. |
4009 | | - if not self.sem.is_module_scope(): |
4010 | | - return |
4011 | | - for id, as_id in node.ids: |
4012 | | - imported_id = as_id or id |
4013 | | - if imported_id not in self.sem.globals: |
4014 | | - self.sem.add_symbol(imported_id, SymbolTableNode(UNBOUND_IMPORTED, None), node) |
4015 | | - else: |
4016 | | - # If the previous symbol is a variable, this should take precedence. |
4017 | | - self.sem.globals[imported_id] = SymbolTableNode(UNBOUND_IMPORTED, None) |
4018 | | - |
4019 | | - def visit_import_all(self, node: ImportAll) -> None: |
4020 | | - node.is_top_level = self.sem.is_module_scope() |
4021 | | - |
4022 | | - def visit_while_stmt(self, s: WhileStmt) -> None: |
4023 | | - if self.sem.is_module_scope(): |
4024 | | - s.body.accept(self) |
4025 | | - if s.else_body: |
4026 | | - s.else_body.accept(self) |
4027 | | - |
4028 | | - def visit_for_stmt(self, s: ForStmt) -> None: |
4029 | | - if self.sem.is_module_scope(): |
4030 | | - self.analyze_lvalue(s.index, explicit_type=s.index_type is not None) |
4031 | | - s.body.accept(self) |
4032 | | - if s.else_body: |
4033 | | - s.else_body.accept(self) |
4034 | | - |
4035 | | - def visit_with_stmt(self, s: WithStmt) -> None: |
4036 | | - if self.sem.is_module_scope(): |
4037 | | - for n in s.target: |
4038 | | - if n: |
4039 | | - self.analyze_lvalue(n, explicit_type=s.target_type is not None) |
4040 | | - s.body.accept(self) |
4041 | | - |
4042 | | - def visit_decorator(self, d: Decorator) -> None: |
4043 | | - d.var._fullname = self.sem.qualified_name(d.var.name()) |
4044 | | - self.sem.add_symbol(d.var.name(), SymbolTableNode(self.kind_by_scope(), d.var), d) |
4045 | | - |
4046 | | - def visit_if_stmt(self, s: IfStmt) -> None: |
4047 | | - infer_reachability_of_if_statement(s, pyversion=self.pyversion, platform=self.platform) |
4048 | | - for node in s.body: |
4049 | | - node.accept(self) |
4050 | | - if s.else_body: |
4051 | | - s.else_body.accept(self) |
4052 | | - |
4053 | | - def visit_try_stmt(self, s: TryStmt) -> None: |
4054 | | - if self.sem.is_module_scope(): |
4055 | | - self.sem.analyze_try_stmt(s, self, add_global=self.sem.is_module_scope()) |
4056 | | - |
4057 | | - def analyze_lvalue(self, lvalue: Lvalue, explicit_type: bool = False) -> None: |
4058 | | - self.sem.analyze_lvalue(lvalue, add_global=self.sem.is_module_scope(), |
4059 | | - explicit_type=explicit_type) |
4060 | | - |
4061 | | - def kind_by_scope(self) -> int: |
4062 | | - if self.sem.is_module_scope(): |
4063 | | - return GDEF |
4064 | | - elif self.sem.is_class_scope(): |
4065 | | - return MDEF |
4066 | | - elif self.sem.is_func_scope(): |
4067 | | - return LDEF |
4068 | | - else: |
4069 | | - assert False, "Couldn't determine scope" |
4070 | | - |
4071 | | - |
4072 | 3798 | def replace_implicit_first_type(sig: FunctionLike, new: Type) -> FunctionLike: |
4073 | 3799 | if isinstance(sig, CallableType): |
4074 | 3800 | return sig.copy_modified(arg_types=[new] + sig.arg_types[1:]) |
|
0 commit comments