@@ -2927,21 +2927,34 @@ def visit_member_expr(self, expr: MemberExpr) -> None:
2927
2927
if full_name in obsolete_name_mapping :
2928
2928
self .fail ("Module%s has no attribute %r (it's now called %r)" % (
2929
2929
mod_name , expr .name , obsolete_name_mapping [full_name ]), expr )
2930
- elif isinstance (base , RefExpr ) and isinstance (base .node , TypeInfo ):
2931
- n = base .node .names .get (expr .name )
2932
- if n is not None and (n .kind == MODULE_REF or isinstance (n .node , TypeInfo )):
2933
- # This branch handles the case C.bar where C is a class and
2934
- # bar is a type definition or a module resulting from
2935
- # `import bar` inside class C. Here base.node is a TypeInfo,
2936
- # and again we look up the name in its namespace.
2937
- # This is done only when bar is a module or a type; other
2938
- # things (e.g. methods) are handled by other code in checkmember.
2939
- n = self .normalize_type_alias (n , expr )
2940
- if not n :
2941
- return
2942
- expr .kind = n .kind
2943
- expr .fullname = n .fullname
2944
- expr .node = n .node
2930
+ elif isinstance (base , RefExpr ):
2931
+ # This branch handles the case C.bar (or cls.bar or self.bar inside
2932
+ # a classmethod/method), where C is a class and bar is a type
2933
+ # definition or a module resulting from `import bar` (or a module
2934
+ # assignment) inside class C. We look up bar in the class' TypeInfo
2935
+ # namespace. This is done only when bar is a module or a type;
2936
+ # other things (e.g. methods) are handled by other code in
2937
+ # checkmember.
2938
+ type_info = None
2939
+ if isinstance (base .node , TypeInfo ):
2940
+ # C.bar where C is a class
2941
+ type_info = base .node
2942
+ elif isinstance (base .node , Var ) and self .type and self .function_stack :
2943
+ # check for self.bar or cls.bar in method/classmethod
2944
+ func_def = self .function_stack [- 1 ]
2945
+ if not func_def .is_static and isinstance (func_def .type , CallableType ):
2946
+ formal_arg = func_def .type .argument_by_name (base .node .name ())
2947
+ if formal_arg and formal_arg .pos == 0 :
2948
+ type_info = self .type
2949
+ if type_info :
2950
+ n = type_info .names .get (expr .name )
2951
+ if n is not None and (n .kind == MODULE_REF or isinstance (n .node , TypeInfo )):
2952
+ n = self .normalize_type_alias (n , expr )
2953
+ if not n :
2954
+ return
2955
+ expr .kind = n .kind
2956
+ expr .fullname = n .fullname
2957
+ expr .node = n .node
2945
2958
2946
2959
def visit_op_expr (self , expr : OpExpr ) -> None :
2947
2960
expr .left .accept (self )
0 commit comments