From 9b471fb6f0123f69d5c1ab31d7854e57f4d0f4d8 Mon Sep 17 00:00:00 2001 From: Daniil Kalinin Date: Thu, 9 Feb 2023 16:52:41 +0000 Subject: [PATCH] PY-38680 Don't treat class with method which rises `NotImplementedError` as abstract but keep ability to implement them Merge-request: IJ-MR-102462 Merged-by: Daniil Kalinin GitOrigin-RevId: c94b0d90288fd9ff10ef745273110eaaf628dd2e --- .../python/inspections/PyAbstractClassInspection.java | 9 ++++++++- ...chRaisesNotImplementedErrorNotTreatedAsAbstract.py | 11 +++++++++++ .../superMethodRaisesNotImplementerError.py | 6 ------ .../inspections/PyAbstractClassInspectionTest.java | 3 ++- 4 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 python/testData/inspections/PyAbstractClassInspection/classWithMethodWhichRaisesNotImplementedErrorNotTreatedAsAbstract.py delete mode 100644 python/testData/inspections/PyAbstractClassInspection/superMethodRaisesNotImplementerError.py diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java index c77d3bd75ece..e5fe720cb893 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java @@ -9,6 +9,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElementVisitor; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyNames; import com.jetbrains.python.PyPsiBundle; import com.jetbrains.python.PythonUiService; @@ -44,7 +45,13 @@ public class PyAbstractClassInspection extends PyInspection { if (isAbstract(pyClass) || PyProtocolsKt.isProtocol(pyClass, myTypeEvalContext)) { return; } - final List toImplement = PyPsiRefactoringUtil.getAllSuperAbstractMethods(pyClass, myTypeEvalContext); + + /* Do not report problem if class contains only methods that raise NotImplementedError without any abc.* decorators + but keep ability to implement them via quickfix (see PY-38680) */ + final List toImplement = ContainerUtil + .filter(PyPsiRefactoringUtil.getAllSuperAbstractMethods(pyClass, myTypeEvalContext), + function -> PyKnownDecoratorUtil.hasAbstractDecorator(function, myTypeEvalContext)); + final ASTNode nameNode = pyClass.getNameNode(); if (!toImplement.isEmpty() && nameNode != null) { final SmartList quickFixes = new SmartList<>(); diff --git a/python/testData/inspections/PyAbstractClassInspection/classWithMethodWhichRaisesNotImplementedErrorNotTreatedAsAbstract.py b/python/testData/inspections/PyAbstractClassInspection/classWithMethodWhichRaisesNotImplementedErrorNotTreatedAsAbstract.py new file mode 100644 index 000000000000..6715ecbacca2 --- /dev/null +++ b/python/testData/inspections/PyAbstractClassInspection/classWithMethodWhichRaisesNotImplementedErrorNotTreatedAsAbstract.py @@ -0,0 +1,11 @@ +class A(object): + def foo(self): + raise NotImplementedError + + def bar(self): + print("bar() is called") + return + + +class B(A): + pass diff --git a/python/testData/inspections/PyAbstractClassInspection/superMethodRaisesNotImplementerError.py b/python/testData/inspections/PyAbstractClassInspection/superMethodRaisesNotImplementerError.py deleted file mode 100644 index dbfb779ce6b4..000000000000 --- a/python/testData/inspections/PyAbstractClassInspection/superMethodRaisesNotImplementerError.py +++ /dev/null @@ -1,6 +0,0 @@ -class Abstract: - def method(self): - raise NotImplementedError() - -class Concrete(Abstract): - pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java index e2220819b04f..b864587429cf 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java @@ -15,7 +15,8 @@ public class PyAbstractClassInspectionTest extends PyInspectionTestCase { doTest(); } - public void testSuperMethodRaisesNotImplementerError() { + // PY-38680 + public void testClassWithMethodWhichRaisesNotImplementedErrorNotTreatedAsAbstract() { doTest(); }