|
52 | 52 | SymbolNode, |
53 | 53 | SymbolTable, |
54 | 54 | TypeInfo, |
| 55 | + Var, |
55 | 56 | reverse_builtin_aliases, |
56 | 57 | ) |
57 | 58 | from mypy.options import Options |
58 | 59 | from mypy.plugin import FunctionContext, MethodContext, Plugin |
59 | 60 | from mypy.server.update import FineGrainedBuildManager |
60 | 61 | from mypy.state import state |
61 | 62 | from mypy.traverser import TraverserVisitor |
62 | | -from mypy.typeops import make_simplified_union |
| 63 | +from mypy.typeops import bind_self, make_simplified_union |
63 | 64 | from mypy.types import ( |
64 | 65 | AnyType, |
65 | 66 | CallableType, |
@@ -638,15 +639,20 @@ def find_node_by_file_and_line(self, file: str, line: int) -> tuple[str, SymbolN |
638 | 639 | def extract_from_decorator(self, node: Decorator) -> FuncDef | None: |
639 | 640 | for dec in node.decorators: |
640 | 641 | typ = None |
641 | | - if isinstance(dec, RefExpr) and isinstance(dec.node, FuncDef): |
642 | | - typ = dec.node.type |
| 642 | + if isinstance(dec, RefExpr) and isinstance(dec.node, (Var, FuncDef)): |
| 643 | + typ = get_proper_type(dec.node.type) |
643 | 644 | elif ( |
644 | 645 | isinstance(dec, CallExpr) |
645 | 646 | and isinstance(dec.callee, RefExpr) |
646 | | - and isinstance(dec.callee.node, FuncDef) |
647 | | - and isinstance(dec.callee.node.type, CallableType) |
| 647 | + and isinstance(dec.callee.node, (Decorator, FuncDef, Var)) |
| 648 | + and isinstance((call_tp := get_proper_type(dec.callee.node.type)), CallableType) |
648 | 649 | ): |
649 | | - typ = get_proper_type(dec.callee.node.type.ret_type) |
| 650 | + typ = get_proper_type(call_tp.ret_type) |
| 651 | + |
| 652 | + if isinstance(typ, Instance): |
| 653 | + call_method = typ.type.get_method("__call__") |
| 654 | + if isinstance(call_method, FuncDef) and isinstance(call_method.type, FunctionLike): |
| 655 | + typ = bind_self(call_method.type, None) |
650 | 656 |
|
651 | 657 | if not isinstance(typ, FunctionLike): |
652 | 658 | return None |
|
0 commit comments