diff --git a/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml b/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml
index 2abed09efa7c..f509d1cb2d4f 100644
--- a/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml
+++ b/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml
@@ -125,7 +125,6 @@
-
diff --git a/python/python-psi-impl/resources/inspectionDescriptions/PyCallByClassInspection.html b/python/python-psi-impl/resources/inspectionDescriptions/PyCallByClassInspection.html
deleted file mode 100644
index b26d096f33f9..000000000000
--- a/python/python-psi-impl/resources/inspectionDescriptions/PyCallByClassInspection.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-This inspection checks for calls of a method by class while passing an instance of a different class
-as self parameter:
-
- foo = Foo()
- Bar.baz(foo, *more)
-
-Sometimes this may be intentional and correct.
-But when unintentional, this leads to subtle bugs.
-
-
diff --git a/python/python-psi-impl/resources/messages/PyPsiBundle.properties b/python/python-psi-impl/resources/messages/PyPsiBundle.properties
index 7b767a61cbc4..a8745ed2cefe 100644
--- a/python/python-psi-impl/resources/messages/PyPsiBundle.properties
+++ b/python/python-psi-impl/resources/messages/PyPsiBundle.properties
@@ -808,11 +808,6 @@ INSP.async.call=Coroutine is not awaited
INSP.NAME.attribute.outside.init=Instance attribute defined outside __init__
INSP.attribute.outside.init=Instance attribute {0} defined outside __init__
-# PyCallByClassInspection
-INSP.NAME.different.class.call=Calling a method by class using an instance of a different class
-INSP.different.class.call.instance.of.class.expected.not.class.itself=An instance of {0} expected, not the class itself
-INSP.different.class.call.passing.class.instead.class=Passing {0} instead of {1}. Is this intentional?
-
# PyMissingOrEmptyDocstringInspection
INSP.NAME.missing.or.empty.docstring=Missing or empty docstring
INSP.no.docstring=Missing docstring
diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyCallByClassInspection.java b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyCallByClassInspection.java
deleted file mode 100644
index db2efa129ab9..000000000000
--- a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyCallByClassInspection.java
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2000-2017 JetBrains s.r.o.
-// Use of this source code is governed by the Apache 2.0 license that can be
-// found in the LICENSE file.
-package com.jetbrains.python.inspections;
-
-import com.intellij.codeHighlighting.HighlightDisplayLevel;
-import com.intellij.codeInspection.LocalInspectionToolSession;
-import com.intellij.codeInspection.ProblemsHolder;
-import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.containers.ContainerUtil;
-import com.jetbrains.python.PyPsiBundle;
-import com.jetbrains.python.psi.*;
-import com.jetbrains.python.psi.types.PyCallableParameter;
-import com.jetbrains.python.psi.types.PyCallableType;
-import com.jetbrains.python.psi.types.PyClassType;
-import com.jetbrains.python.psi.types.PyType;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Map;
-
-import static com.jetbrains.python.psi.PyFunction.Modifier.CLASSMETHOD;
-import static com.jetbrains.python.psi.PyFunction.Modifier.STATICMETHOD;
-
-/**
- * Checks for for calls like {@code X.method(y,...)}, where y is not an instance of X.
- *
- * Not marked are cases of inheritance calls in old-style classes, like:
- * class B(A):
- * def foo(self):
- * A.foo(self)
- *
- *
- * User: dcheryasov
- */
-public class PyCallByClassInspection extends PyInspection {
-
- @Override
- public boolean isEnabledByDefault() {
- return true;
- }
-
- @NotNull
- @Override
- public HighlightDisplayLevel getDefaultLevel() {
- return HighlightDisplayLevel.WEAK_WARNING;
- }
-
- @NotNull
- @Override
- public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly, @NotNull LocalInspectionToolSession session) {
- return new Visitor(holder, session);
- }
-
- public static class Visitor extends PyInspectionVisitor {
-
- public Visitor(final ProblemsHolder holder, LocalInspectionToolSession session) {
- super(holder, session);
- }
-
-
- @Override
- public void visitPyCallExpression(@NotNull PyCallExpression call) {
- PyExpression callee = call.getCallee();
- if (callee instanceof PyQualifiedExpression) {
- PyExpression qualifier = ((PyQualifiedExpression)callee).getQualifier();
- if (qualifier != null) {
- PyType qual_type = myTypeEvalContext.getType(qualifier);
- if (qual_type instanceof PyClassType) {
- final PyClassType qual_class_type = (PyClassType)qual_type;
- if (qual_class_type.isDefinition()) {
- PyClass qual_class = qual_class_type.getPyClass();
- final PyCallExpression.PyArgumentsMapping mapping = ContainerUtil.getFirstItem(call.multiMapArguments(getResolveContext()));
- final PyCallableType callableType = mapping == null ? null : mapping.getCallableType();
- if (callableType != null && callableType.getModifier() != STATICMETHOD) {
- final PyCallableParameter firstParameter =
- ContainerUtil.getFirstItem(callableType.getParameters(myTypeEvalContext));
- if (firstParameter != null) {
- for (Map.Entry entry : mapping.getMappedParameters().entrySet()) {
- // we ignore *arg and **arg which we cannot analyze
- if (firstParameter.equals(entry.getValue())) {
- PyExpression first_arg = entry.getKey();
- assert first_arg != null;
- PyType first_arg_type = myTypeEvalContext.getType(first_arg);
- if (first_arg_type instanceof PyClassType) {
- final PyClassType first_arg_class_type = (PyClassType)first_arg_type;
- if (first_arg_class_type.isDefinition() && callableType.getModifier() != CLASSMETHOD) {
- registerProblem(
- first_arg,
- PyPsiBundle.message("INSP.different.class.call.instance.of.class.expected.not.class.itself", qual_class.getQualifiedName())
- );
- }
- PyClass first_arg_class = first_arg_class_type.getPyClass();
- if (first_arg_class != qual_class) {
- // delegating to a parent is fine
- if (callableType.getCallable() instanceof PyFunction) {
- PyCallable callable = PsiTreeUtil.getParentOfType(call, PyCallable.class);
- if (callable != null) {
- PyFunction method = callable.asMethod();
- if (method != null) {
- PyClass calling_class = method.getContainingClass();
- assert calling_class != null; // it's a method
- if (first_arg_class.isSubclass(qual_class, myTypeEvalContext) &&
- calling_class.isSubclass(qual_class, myTypeEvalContext)) {
- break;
- // TODO: might propose to switch to super() here
- }
- }
- }
- }
- // otherwise, it's not
- registerProblem(
- first_arg,
- PyPsiBundle.message(
- "INSP.different.class.call.passing.class.instead.class",
- first_arg_class.getQualifiedName(), qual_class.getQualifiedName()
- )
- );
- }
- }
- break; // once we found the first parameter, we don't need the rest
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/python/testData/inspections/PyCallByClassInspection/test.py b/python/testData/inspections/PyCallByClassInspection/test.py
deleted file mode 100644
index 902e32dea3de..000000000000
--- a/python/testData/inspections/PyCallByClassInspection/test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-class Z(object):
- def method(self):
- pass
-
-class A(object):
- def method(self, *args, **kwargs):
- Z.method(self) # passing wrong instance
- Z.method(Z) # passing class instead of instance
- Z.method(A) # passing class instead of instance AND wrong class
- Z.method(Z()) #pass
-
- def __init__(self):
- pass
-
-class B(A):
- def __init__(self):
- A.__init__(self) # pass
-
-A.method(B())
-
-
-# PY-21083
-float.fromhex('A')
\ No newline at end of file
diff --git a/python/testData/inspections/PyTypeCheckerInspection/CallByClass.py b/python/testData/inspections/PyTypeCheckerInspection/CallByClass.py
new file mode 100644
index 000000000000..ac58d747bdef
--- /dev/null
+++ b/python/testData/inspections/PyTypeCheckerInspection/CallByClass.py
@@ -0,0 +1,19 @@
+class Z:
+ def method(self):
+ pass
+
+class A:
+ def method(self):
+ Z.method(self) # passing wrong instance
+ Z.method(Z) # passing class instead of instance
+ Z.method(A) # passing class instead of instance AND wrong class
+ Z.method(Z()) #pass
+
+ def __init__(self):
+ pass
+
+class B(A):
+ def __init__(self):
+ A.__init__(self) # pass
+
+A.method(B())
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java
index 5f24dc6e0be7..7854edfa0c46 100644
--- a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java
@@ -4,7 +4,6 @@ package com.jetbrains.python;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
-import com.jetbrains.python.inspections.PyNonAsciiCharInspection;
import com.jetbrains.python.documentation.docstrings.DocStringFormat;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.inspections.*;
@@ -159,10 +158,6 @@ public class PythonInspectionsTest extends PyTestCase {
myFixture.checkHighlighting(true, false, true);
}
- public void testPyCallByClassInspection() {
- doHighlightingTest(PyCallByClassInspection.class); // ok, we can handle insanely long lines :)
- }
-
private void doHighlightingTest(final Class extends PyInspection> inspectionClass) {
myFixture.configureByFile("inspections/" + getTestName(false) + "/test.py");
myFixture.enableInspections(inspectionClass);
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java
index efed8f262f98..24e1c2216152 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java
@@ -1255,4 +1255,8 @@ public class PyTypeCheckerInspectionTest extends PyInspectionTestCase {
"func(42, None' (matched generic type '(T) -> None'), got '(x: str) -> None' instead\">accepts_anything)")
);
}
+
+ public void testCallByClass() {
+ doTest();
+ }
}