|
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,16 +639,21 @@ 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 | + if isinstance(dec, RefExpr) and isinstance(dec.node, (Var, FuncDef)): |
642 | 643 | typ = 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, (Decorator, FuncDef)) |
647 | 648 | and isinstance(dec.callee.node.type, CallableType)
|
648 | 649 | ):
|
649 | 650 | typ = get_proper_type(dec.callee.node.type.ret_type)
|
650 | 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) |
| 656 | + |
651 | 657 | if not isinstance(typ, FunctionLike):
|
652 | 658 | return None
|
653 | 659 | for ct in typ.items:
|
|
0 commit comments