-
Notifications
You must be signed in to change notification settings - Fork 190
Description
Summary
astral-sh/ruff#18444 added fantastic subdiagnostic suggestions for unresolved-reference diagnostics in methods. They work great for most cases, but for several edge cases they result in incorrect suggestions.
We should not add the subdiagnostic if the method is a staticmethod: the subdiagnostic does not make much sense here:
class Foo:
def __init__(self):
self.x = 42
@staticmethod
def static_method():
print(x)Our diagnostic is currently:
error[unresolved-reference]: Name `x` used when not defined
--> foo.py:9:15
|
7 | @staticmethod
8 | def static_method():
9 | print(x)
| ^
10 |
11 | @classmethod
|
info: An attribute `x` is available: consider using `self.x`
info: rule `unresolved-reference` is enabled by default
We should not suggest attributes only available on instances if the method is a classmethod: the subdiagnostic does not make much sense here:
class Foo:
def __init__(self):
self.x = 42
@classmethod
def class_method(cls):
print(x)Our diagnostic is currently:
error[unresolved-reference]: Name `x` used when not defined
--> bar.py:7:15
|
5 | @classmethod
6 | def class_method(cls):
7 | print(x)
| ^
|
info: An attribute `x` is available: consider using `self.x`
info: rule `unresolved-reference` is enabled by default
This should be fixed by using SubclassOf::from(self.db(), class.default_specialization(self.db())) here if it's a classmethod (but still using Type::instance(self.db(), class.default_specialization(self.db())) if it's an instance method).
The subdiagnostic message always says "consider using self.<attribute>". But we should inspect the function to check what the name of the first parameter is rather than assuming it's self. Even for instance methods, the name of the first parameter is often not self if it's an instance method on a metaclass, for example:
class Foo:
Y = 42
@classmethod
def class_method(cls):
print(Y)
class Meta(type):
Z = 42
def instance_metaclass_method(cls):
print(Z)Our current diagnostics:
error[unresolved-reference]: Name `Y` used when not defined
--> baz.py:6:15
|
4 | @classmethod
5 | def class_method(cls):
6 | print(Y)
| ^
|
info: An attribute `Y` is available: consider using `self.Y`
info: rule `unresolved-reference` is enabled by default
error[unresolved-reference]: Name `Z` used when not defined
--> baz.py:13:15
|
12 | def instance_metaclass_method(cls):
13 | print(Z)
| ^
|
info: An attribute `Z` is available: consider using `self.Z`
info: rule `unresolved-reference` is enabled by default