mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Fixed false positive attribute assignment warning for classes that inherit '__slots__', but don't define their own slots (PY-10158)
This commit is contained in:
@@ -181,6 +181,12 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine
|
||||
|
||||
boolean isSubclass(@NotNull String superClassQName);
|
||||
|
||||
/**
|
||||
* Returns the aggregated list of names defined in __slots__ attributes of the class and its ancestors.
|
||||
*/
|
||||
@Nullable
|
||||
List<String> getSlots();
|
||||
|
||||
/**
|
||||
* Returns the list of names in the class' __slots__ attribute, or null if the class
|
||||
* does not define such an attribute.
|
||||
@@ -188,7 +194,7 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine
|
||||
* @return the list of names or null.
|
||||
*/
|
||||
@Nullable
|
||||
List<String> getSlots();
|
||||
List<String> getOwnSlots();
|
||||
|
||||
@Nullable
|
||||
String getDocStringValue();
|
||||
|
||||
@@ -128,6 +128,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
if (type instanceof PyClassType) {
|
||||
final PyClass pyClass = ((PyClassType)type).getPyClass();
|
||||
if (pyClass.isNewStyleClass()) {
|
||||
if (pyClass.getOwnSlots() == null) {
|
||||
return;
|
||||
}
|
||||
final List<String> slots = pyClass.getSlots();
|
||||
final String attrName = node.getReferencedName();
|
||||
if (slots != null && !slots.contains(attrName) && !slots.contains(PyNames.DICT)) {
|
||||
|
||||
@@ -246,20 +246,25 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
|
||||
@Override
|
||||
public List<String> getSlots() {
|
||||
List<String> slots = getOwnSlots();
|
||||
if (slots != null) {
|
||||
return slots;
|
||||
final Set<String> result = new LinkedHashSet<String>();
|
||||
boolean found = false;
|
||||
final List<String> ownSlots = getOwnSlots();
|
||||
if (ownSlots != null) {
|
||||
found = true;
|
||||
result.addAll(ownSlots);
|
||||
}
|
||||
for (PyClass cls : getAncestorClasses()) {
|
||||
slots = ((PyClassImpl)cls).getOwnSlots();
|
||||
if (slots != null) {
|
||||
return slots;
|
||||
final List<String> ancestorSlots = cls.getOwnSlots();
|
||||
if (ancestorSlots != null) {
|
||||
found = true;
|
||||
result.addAll(ancestorSlots);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return found ? new ArrayList<String>(result) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> getOwnSlots() {
|
||||
final PyClassStub stub = getStub();
|
||||
if (stub != null) {
|
||||
|
||||
@@ -49,7 +49,7 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
|
||||
final PyStringLiteralExpression docStringExpression = psi.getDocStringExpression();
|
||||
return new PyClassStubImpl(psi.getName(), parentStub,
|
||||
superClasses.toArray(new PyQualifiedName[superClasses.size()]),
|
||||
((PyClassImpl)psi).getOwnSlots(),
|
||||
psi.getOwnSlots(),
|
||||
PyPsiUtils.strValue(docStringExpression),
|
||||
getStubElementType());
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ class C(B):
|
||||
pass
|
||||
|
||||
c = C()
|
||||
c.<warning descr="'C' object has no attribute 'bar'">bar</warning> = 1
|
||||
c.bar = 1
|
||||
|
||||
def test_slots_with_dict():
|
||||
class C(object):
|
||||
|
||||
Reference in New Issue
Block a user