PY-22899 Fixed: type's __getattribute__ unresolved reference

PY-22937 Fixed: type's __setattr__ unresolved reference

Add `object` as implicit super for all builtin classes except `staticmethod`, `classmethod` and `object`.
This commit is contained in:
Semyon Proshev
2017-04-03 20:55:57 +03:00
parent bba80d6b8b
commit 853ce3be8c
3 changed files with 41 additions and 18 deletions
@@ -1400,35 +1400,24 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
if (PyNames.TYPES_INSTANCE_TYPE.equals(getQualifiedName())) {
return Collections.emptyList();
}
final PyClassStub stub = getStub();
final List<PyClassLikeType> result = new ArrayList<>();
// In some cases stub may not provide all information, so we use stubs only if AST access id disabled
if (!context.maySwitchToAST(this)) {
fillSuperClassesNoSwitchToAst(context, stub, result);
fillSuperClassesNoSwitchToAst(context, getStub(), result);
}
else {
fillSuperClassesSwitchingToAst(context, result);
}
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(this);
PyPsiUtils.assertValid(this);
if (result.isEmpty() && isValid() && !builtinCache.isBuiltin(this)) {
final PyClass implicitSuper;
if (LanguageLevel.forElement(this).isOlderThan(LanguageLevel.PYTHON30) && getMetaClassQName() == null) {
implicitSuper = as(resolveTopLevelMember(QualifiedName.fromDottedString(PyNames.TYPES_INSTANCE_TYPE),
fromFoothold(this)), PyClass.class);
}
else {
implicitSuper = builtinCache.getClass(PyNames.OBJECT);
}
if (implicitSuper != null) {
final PyType type = context.getType(implicitSuper);
if (type instanceof PyClassLikeType) {
result.add((PyClassLikeType)type);
}
}
if (result.isEmpty()) {
return Optional
.ofNullable(getImplicitSuper(context))
.map(Collections::singletonList)
.orElse(Collections.emptyList());
}
return result;
}
@@ -1475,6 +1464,29 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
}
}
@Nullable
private PyClassLikeType getImplicitSuper(@NotNull TypeEvalContext context) {
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(this);
final PyClassType objectType = builtinCache.getObjectType();
if (objectType != null && this == objectType.getPyClass()) {
return null;
}
if (LanguageLevel.forElement(this).isOlderThan(LanguageLevel.PYTHON30) && getMetaClassQName() == null) {
final QualifiedName typesInstanceTypeQName = QualifiedName.fromDottedString(PyNames.TYPES_INSTANCE_TYPE);
final PsiElement typesInstanceType = resolveTopLevelMember(typesInstanceTypeQName, fromFoothold(this));
return Optional
.ofNullable(as(typesInstanceType, PyClass.class))
.map(context::getType)
.map(type -> as(type, PyClassLikeType.class))
.orElse(null);
}
return objectType;
}
@NotNull
@Override
public List<PyClassLikeType> getAncestorTypes(@NotNull TypeEvalContext context) {
@@ -0,0 +1,6 @@
class ConfigMeta(type):
def __getattribute__(self, item):
return super().__getattribute__(item)
def __setattr__(self, key, value):
super().__setattr__(key, value)
@@ -205,4 +205,9 @@ public class Py3UnresolvedReferencesInspectionTest extends PyTestCase {
public void testTypingGenericDunderGetItem() {
doTest();
}
// PY-22899, PY-22937
public void testCallTypeGetAttributeAndSetAttrInInheritor() {
doTest();
}
}