Moved Python ABC utils into a separate class

This commit is contained in:
Andrey Vlasovskikh
2011-07-01 17:49:50 +04:00
parent e5ef82f029
commit e8aabad5b2
4 changed files with 57 additions and 41 deletions
@@ -10,6 +10,7 @@ import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
import com.jetbrains.python.psi.types.PyABCUtil;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.Nls;
@@ -57,7 +58,7 @@ public class PyCallingNonCallableInspection extends PyInspection {
if (isMethodType(node, classType)) {
return;
}
if (cls != null && !cls.isSubclass(PyNames.CALLABLE)) {
if (cls != null && !PyABCUtil.isSubclass(cls, PyNames.CALLABLE)) {
registerProblem(node, String.format("'%s' object is not callable", cls.getName()));
}
}
@@ -178,7 +178,7 @@ public class PyTypeCheckerInspection extends PyInspection {
}
private static boolean matchClasses(@Nullable PyClass superClass, @Nullable PyClass subClass) {
if (superClass == null || subClass == null || subClass.isSubclass(superClass)) {
if (superClass == null || subClass == null || subClass.isSubclass(superClass) || PyABCUtil.isSubclass(subClass, superClass)) {
return true;
}
else {
@@ -157,7 +157,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
}
public boolean isSubclass(PyClass parent) {
if (this == parent || isSubclassOfABC(new PyClassRef(parent))) {
if (this == parent) {
return true;
}
for (PyClass superclass : iterateAncestorClasses()) {
@@ -168,7 +168,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
@Override
public boolean isSubclass(String superClassQName) {
if (getQualifiedName().equals(superClassQName) || isSubclassOfABC(new PyClassRef(superClassQName))) {
if (getQualifiedName().equals(superClassQName)) {
return true;
}
for (PyClassRef superclass : iterateAncestors()) {
@@ -567,43 +567,6 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
return null;
}
private boolean isSubclassOfABC(PyClassRef superRef) {
final String superQName = superRef.getQualifiedName();
final PyClass superClass = superRef.getPyClass();
final String superName = superClass != null ? superClass.getName() : superQName;
if (superName != null) {
final boolean isContainer = hasMethod(PyNames.CONTAINS);
if (PyNames.CONTAINER.equals(superName)) {
return isContainer;
}
if (PyNames.HASHABLE.equals(superName)) {
return hasMethod(PyNames.HASH);
}
final boolean isIterable = hasMethod(PyNames.ITER);
if (PyNames.ITERABLE.equals(superName)) {
return isIterable;
}
if (PyNames.ITERATOR.equals(superName)) {
return isIterable && hasMethod(PyNames.NEXT);
}
final boolean isSized = hasMethod(PyNames.LEN);
if (PyNames.SIZED.equals(superName)) {
return isSized;
}
if (PyNames.CALLABLE.equals(superName)) {
return hasMethod(PyNames.CALL);
}
if (PyNames.SEQUENCE.equals(superName)) {
return isSized && isIterable && isContainer && hasMethod(PyNames.GETITEM);
}
}
return false;
}
private boolean hasMethod(String name) {
return findMethodByName(name, true) != null;
}
private static class PropertyImpl extends PropertyBunch<PyFunction> implements Property {
private PropertyImpl(Maybe<PyFunction> getter, Maybe<PyFunction> setter, Maybe<PyFunction> deleter, String doc, PyTargetExpression site) {
@@ -0,0 +1,52 @@
package com.jetbrains.python.psi.types;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyClassRef;
import org.jetbrains.annotations.NotNull;
/**
* @author vlan
*/
public class PyABCUtil {
public static boolean isSubclass(@NotNull PyClass subClass, @NotNull PyClass superClass) {
final String superName = superClass.getName();
if (superName != null) {
return isSubclass(subClass, superName);
}
return false;
}
public static boolean isSubclass(@NotNull PyClass subClass, @NotNull String superClassName) {
if (PyNames.CALLABLE.equals(superClassName)) {
return hasMethod(subClass, PyNames.CALL);
}
if (PyNames.HASHABLE.equals(superClassName)) {
return hasMethod(subClass, PyNames.HASH);
}
final boolean isIterable = hasMethod(subClass, PyNames.ITER);
if (PyNames.ITERABLE.equals(superClassName)) {
return isIterable;
}
if (PyNames.ITERATOR.equals(superClassName)) {
return isIterable && hasMethod(subClass, PyNames.NEXT);
}
final boolean isSized = hasMethod(subClass, PyNames.LEN);
if (PyNames.SIZED.equals(superClassName)) {
return isSized;
}
final boolean isContainer = hasMethod(subClass, PyNames.CONTAINS);
if (PyNames.CONTAINER.equals(superClassName)) {
return isContainer;
}
if (PyNames.SEQUENCE.equals(superClassName)) {
return isSized && isIterable && isContainer && hasMethod(subClass, PyNames.GETITEM);
}
return false;
}
private static boolean hasMethod(PyClass cls, String name) {
return cls.findMethodByName(name, true) != null;
}
}