|
305 | 305 | ) |
306 | 306 | from mypy.types_utils import is_invalid_recursive_alias, store_argument_type |
307 | 307 | from mypy.typevars import fill_typevars |
308 | | -from mypy.util import correct_relative_import, is_dunder, module_prefix, unmangle, unnamed_function |
| 308 | +from mypy.util import ( |
| 309 | + correct_relative_import, |
| 310 | + is_dunder, |
| 311 | + module_prefix, |
| 312 | + split_module_names, |
| 313 | + unmangle, |
| 314 | + unnamed_function, |
| 315 | +) |
309 | 316 | from mypy.visitor import NodeVisitor |
310 | 317 |
|
311 | 318 | T = TypeVar("T") |
@@ -2808,7 +2815,6 @@ def get_declared_metaclass( |
2808 | 2815 | and not sym.node.alias_tvars |
2809 | 2816 | ): |
2810 | 2817 | target = get_proper_type(sym.node.target) |
2811 | | - self.add_type_alias_deps({(sym.node.module, sym.node.fullname)}) |
2812 | 2818 | if isinstance(target, Instance): |
2813 | 2819 | metaclass_info = target.type |
2814 | 2820 |
|
@@ -3887,15 +3893,15 @@ def analyze_alias( |
3887 | 3893 | declared_type_vars: TypeVarLikeList | None = None, |
3888 | 3894 | all_declared_type_params_names: list[str] | None = None, |
3889 | 3895 | python_3_12_type_alias: bool = False, |
3890 | | - ) -> tuple[Type | None, list[TypeVarLikeType], set[tuple[str, str]], bool]: |
| 3896 | + ) -> tuple[Type | None, list[TypeVarLikeType], set[str], bool]: |
3891 | 3897 | """Check if 'rvalue' is a valid type allowed for aliasing (e.g. not a type variable). |
3892 | 3898 |
|
3893 | 3899 | If yes, return the corresponding type, a list of type variables for generic aliases, |
3894 | 3900 | a set of names the alias depends on, and True if the original type has empty tuple index. |
3895 | 3901 | An example for the dependencies: |
3896 | 3902 | A = int |
3897 | 3903 | B = str |
3898 | | - analyze_alias(dict[A, B])[2] == {('mod', 'mod.A'), ('mod', 'mod.B')} |
| 3904 | + analyze_alias(dict[A, B])[2] == {'__main__.A', '__main__.B'} |
3899 | 3905 | """ |
3900 | 3906 | dynamic = bool(self.function_stack and self.function_stack[-1].is_dynamic()) |
3901 | 3907 | global_scope = not self.type and not self.function_stack |
@@ -4040,7 +4046,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: |
4040 | 4046 | if self.is_none_alias(rvalue): |
4041 | 4047 | res = NoneType() |
4042 | 4048 | alias_tvars: list[TypeVarLikeType] = [] |
4043 | | - depends_on: set[tuple[str, str]] = set() |
| 4049 | + depends_on: set[str] = set() |
4044 | 4050 | empty_tuple_index = False |
4045 | 4051 | else: |
4046 | 4052 | tag = self.track_incomplete_refs() |
@@ -5929,6 +5935,8 @@ def visit_member_expr(self, expr: MemberExpr) -> None: |
5929 | 5935 | if isinstance(sym.node, PlaceholderNode): |
5930 | 5936 | self.process_placeholder(expr.name, "attribute", expr) |
5931 | 5937 | return |
| 5938 | + if sym.node is not None: |
| 5939 | + self.record_imported_symbol(sym.node) |
5932 | 5940 | expr.kind = sym.kind |
5933 | 5941 | expr.fullname = sym.fullname or "" |
5934 | 5942 | expr.node = sym.node |
@@ -5959,8 +5967,7 @@ def visit_member_expr(self, expr: MemberExpr) -> None: |
5959 | 5967 | if type_info: |
5960 | 5968 | n = type_info.names.get(expr.name) |
5961 | 5969 | if n is not None and isinstance(n.node, (MypyFile, TypeInfo, TypeAlias)): |
5962 | | - if not n: |
5963 | | - return |
| 5970 | + self.record_imported_symbol(n.node) |
5964 | 5971 | expr.kind = n.kind |
5965 | 5972 | expr.fullname = n.fullname or "" |
5966 | 5973 | expr.node = n.node |
@@ -6280,6 +6287,24 @@ def visit_class_pattern(self, p: ClassPattern) -> None: |
6280 | 6287 |
|
6281 | 6288 | def lookup( |
6282 | 6289 | self, name: str, ctx: Context, suppress_errors: bool = False |
| 6290 | + ) -> SymbolTableNode | None: |
| 6291 | + node = self._lookup(name, ctx, suppress_errors) |
| 6292 | + if node is not None and node.node is not None: |
| 6293 | + # This call is unfortunate from performance point of view, but |
| 6294 | + # needed for rare cases like e.g. testIncrementalChangingAlias. |
| 6295 | + self.record_imported_symbol(node.node) |
| 6296 | + return node |
| 6297 | + |
| 6298 | + def record_imported_symbol(self, node: SymbolNode) -> None: |
| 6299 | + fullname = node.fullname |
| 6300 | + if not isinstance(node, MypyFile): |
| 6301 | + while fullname not in self.modules and "." in fullname: |
| 6302 | + fullname = fullname.rsplit(".")[0] |
| 6303 | + if fullname != self.cur_mod_id and fullname not in self.cur_mod_node.module_refs: |
| 6304 | + self.cur_mod_node.module_refs.update(split_module_names(fullname)) |
| 6305 | + |
| 6306 | + def _lookup( |
| 6307 | + self, name: str, ctx: Context, suppress_errors: bool = False |
6283 | 6308 | ) -> SymbolTableNode | None: |
6284 | 6309 | """Look up an unqualified (no dots) name in all active namespaces. |
6285 | 6310 |
|
@@ -6488,6 +6513,8 @@ def lookup_qualified( |
6488 | 6513 | self.name_not_defined(name, ctx, namespace=namespace) |
6489 | 6514 | return None |
6490 | 6515 | sym = nextsym |
| 6516 | + if sym is not None and sym.node is not None: |
| 6517 | + self.record_imported_symbol(sym.node) |
6491 | 6518 | return sym |
6492 | 6519 |
|
6493 | 6520 | def lookup_type_node(self, expr: Expression) -> SymbolTableNode | None: |
@@ -7526,21 +7553,18 @@ def add_plugin_dependency(self, trigger: str, target: str | None = None) -> None |
7526 | 7553 | self.cur_mod_node.plugin_deps.setdefault(trigger, set()).add(target) |
7527 | 7554 |
|
7528 | 7555 | def add_type_alias_deps( |
7529 | | - self, aliases_used: Collection[tuple[str, str]], target: str | None = None |
| 7556 | + self, aliases_used: Collection[str], target: str | None = None |
7530 | 7557 | ) -> None: |
7531 | 7558 | """Add full names of type aliases on which the current node depends. |
7532 | 7559 |
|
7533 | 7560 | This is used by fine-grained incremental mode to re-check the corresponding nodes. |
7534 | | - If `target` is None, then the target node used will be the current scope. For |
7535 | | - coarse-grained mode, add just the module names where aliases are defined. |
| 7561 | + If `target` is None, then the target node used will be the current scope. |
7536 | 7562 | """ |
7537 | 7563 | if not aliases_used: |
7538 | 7564 | return |
7539 | 7565 | if target is None: |
7540 | 7566 | target = self.scope.current_target() |
7541 | | - for mod, fn in aliases_used: |
7542 | | - self.cur_mod_node.alias_deps[target].add(fn) |
7543 | | - self.cur_mod_node.mod_alias_deps.add(mod) |
| 7567 | + self.cur_mod_node.alias_deps[target].update(aliases_used) |
7544 | 7568 |
|
7545 | 7569 | def is_mangled_global(self, name: str) -> bool: |
7546 | 7570 | # A global is mangled if there exists at least one renamed variant. |
|
0 commit comments