|
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