@@ -73,6 +73,8 @@ class TypeChecker(NodeVisitor[Type]):
73
73
"""Mypy type checker.
74
74
75
75
Type check mypy source files that have been semantically analyzed.
76
+
77
+ You must create a separate instance for each source file.
76
78
"""
77
79
78
80
# Are we type checking a stub?
@@ -119,53 +121,51 @@ class TypeChecker(NodeVisitor[Type]):
119
121
# directly or indirectly.
120
122
module_refs = None # type: Set[str]
121
123
122
- def __init__ (self , errors : Errors , modules : Dict [str , MypyFile ]) -> None :
124
+ def __init__ (self , errors : Errors , modules : Dict [str , MypyFile ], options : Options ,
125
+ tree : MypyFile , path : str ) -> None :
123
126
"""Construct a type checker.
124
127
125
128
Use errors to report type check errors.
126
129
"""
127
130
self .errors = errors
128
131
self .modules = modules
132
+ self .options = options
133
+ self .tree = tree
134
+ self .path = path
129
135
self .msg = MessageBuilder (errors , modules )
130
- self .type_map = {}
131
- self .binder = ConditionalTypeBinder ()
132
136
self .expr_checker = mypy .checkexpr .ExpressionChecker (self , self .msg )
137
+ self .binder = ConditionalTypeBinder ()
138
+ self .globals = tree .names
133
139
self .return_types = []
134
140
self .type_context = []
135
141
self .dynamic_funcs = []
136
142
self .function_stack = []
137
143
self .partial_types = []
138
144
self .deferred_nodes = []
139
- self .pass_num = 0
140
- self .current_node_deferred = False
145
+ self .type_map = {}
141
146
self .module_refs = set ()
142
-
143
- def visit_file (self , file_node : MypyFile , path : str , options : Options ) -> None :
144
- """Type check a mypy file with the given path."""
145
- self .options = options
146
147
self .pass_num = 0
147
- self .is_stub = file_node .is_stub
148
- self .errors .set_file (path )
149
- self .globals = file_node .names
150
- self .enter_partial_types ()
151
- self .is_typeshed_stub = self .errors .is_typeshed_file (path )
152
- self .module_refs = set ()
153
- if self .options .strict_optional_whitelist is None :
154
- self .suppress_none_errors = not self .options .show_none_errors
148
+ self .current_node_deferred = False
149
+ self .is_stub = tree .is_stub
150
+ self .is_typeshed_stub = errors .is_typeshed_file (path )
151
+ if options .strict_optional_whitelist is None :
152
+ self .suppress_none_errors = not options .show_none_errors
155
153
else :
156
154
self .suppress_none_errors = not any (fnmatch .fnmatch (path , pattern )
157
155
for pattern
158
- in self . options .strict_optional_whitelist )
156
+ in options .strict_optional_whitelist )
159
157
160
- for d in file_node .defs :
158
+ def check_first_pass (self ) -> None :
159
+ """Type check the entire file, but defer functions with forward references."""
160
+ self .errors .set_file (self .path )
161
+ self .enter_partial_types ()
162
+
163
+ for d in self .tree .defs :
161
164
self .accept (d )
162
165
163
166
self .leave_partial_types ()
164
167
165
- if self .deferred_nodes :
166
- self .check_second_pass ()
167
-
168
- self .current_node_deferred = False
168
+ assert not self .current_node_deferred
169
169
170
170
all_ = self .globals .get ('__all__' )
171
171
if all_ is not None and all_ .type is not None :
@@ -176,10 +176,9 @@ def visit_file(self, file_node: MypyFile, path: str, options: Options) -> None:
176
176
self .fail (messages .ALL_MUST_BE_SEQ_STR .format (str_seq_s , all_s ),
177
177
all_ .node )
178
178
179
- del self .options
180
-
181
179
def check_second_pass (self ) -> None :
182
180
"""Run second pass of type checking which goes through deferred nodes."""
181
+ self .errors .set_file (self .path )
183
182
self .pass_num = 1
184
183
for node , type_name in self .deferred_nodes :
185
184
if type_name :
0 commit comments