Skip to content

Commit eba78d9

Browse files
author
Guido van Rossum
committed
Change the TypeChecker toplevel interface.
1 parent 7a80f55 commit eba78d9

File tree

2 files changed

+28
-27
lines changed

2 files changed

+28
-27
lines changed

mypy/build.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,8 +1414,10 @@ def type_check(self) -> None:
14141414
if self.options.semantic_analysis_only:
14151415
return
14161416
with self.wrap_context():
1417-
type_checker = TypeChecker(manager.errors, manager.modules)
1418-
type_checker.visit_file(self.tree, self.xpath, self.options)
1417+
type_checker = TypeChecker(manager.errors, manager.modules, self.options,
1418+
self.tree, self.xpath)
1419+
type_checker.check_first_pass()
1420+
type_checker.check_second_pass()
14191421
manager.all_types.update(type_checker.type_map)
14201422

14211423
if self.options.incremental:

mypy/checker.py

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class TypeChecker(NodeVisitor[Type]):
7373
"""Mypy type checker.
7474
7575
Type check mypy source files that have been semantically analyzed.
76+
77+
You must create a separate instance for each source file.
7678
"""
7779

7880
# Are we type checking a stub?
@@ -119,53 +121,51 @@ class TypeChecker(NodeVisitor[Type]):
119121
# directly or indirectly.
120122
module_refs = None # type: Set[str]
121123

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:
123126
"""Construct a type checker.
124127
125128
Use errors to report type check errors.
126129
"""
127130
self.errors = errors
128131
self.modules = modules
132+
self.options = options
133+
self.tree = tree
134+
self.path = path
129135
self.msg = MessageBuilder(errors, modules)
130-
self.type_map = {}
131-
self.binder = ConditionalTypeBinder()
132136
self.expr_checker = mypy.checkexpr.ExpressionChecker(self, self.msg)
137+
self.binder = ConditionalTypeBinder()
138+
self.globals = tree.names
133139
self.return_types = []
134140
self.type_context = []
135141
self.dynamic_funcs = []
136142
self.function_stack = []
137143
self.partial_types = []
138144
self.deferred_nodes = []
139-
self.pass_num = 0
140-
self.current_node_deferred = False
145+
self.type_map = {}
141146
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
146147
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
155153
else:
156154
self.suppress_none_errors = not any(fnmatch.fnmatch(path, pattern)
157155
for pattern
158-
in self.options.strict_optional_whitelist)
156+
in options.strict_optional_whitelist)
159157

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:
161164
self.accept(d)
162165

163166
self.leave_partial_types()
164167

165-
if self.deferred_nodes:
166-
self.check_second_pass()
167-
168-
self.current_node_deferred = False
168+
assert not self.current_node_deferred
169169

170170
all_ = self.globals.get('__all__')
171171
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:
176176
self.fail(messages.ALL_MUST_BE_SEQ_STR.format(str_seq_s, all_s),
177177
all_.node)
178178

179-
del self.options
180-
181179
def check_second_pass(self) -> None:
182180
"""Run second pass of type checking which goes through deferred nodes."""
181+
self.errors.set_file(self.path)
183182
self.pass_num = 1
184183
for node, type_name in self.deferred_nodes:
185184
if type_name:

0 commit comments

Comments
 (0)