mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Moved Python ABC utils into a separate class
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user