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 <Daniil.Kalinin@jetbrains.com>

GitOrigin-RevId: c94b0d90288fd9ff10ef745273110eaaf628dd2e
This commit is contained in:
Daniil Kalinin
2023-02-09 16:52:41 +00:00
committed by intellij-monorepo-bot
parent 50d3b9fca1
commit 9b471fb6f0
4 changed files with 21 additions and 8 deletions

View File

@@ -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<PyFunction> 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<PyFunction> toImplement = ContainerUtil
.filter(PyPsiRefactoringUtil.getAllSuperAbstractMethods(pyClass, myTypeEvalContext),
function -> PyKnownDecoratorUtil.hasAbstractDecorator(function, myTypeEvalContext));
final ASTNode nameNode = pyClass.getNameNode();
if (!toImplement.isEmpty() && nameNode != null) {
final SmartList<LocalQuickFix> quickFixes = new SmartList<>();

View File

@@ -0,0 +1,11 @@
class A(object):
def foo(self):
raise NotImplementedError
def bar(self):
print("bar() is called")
return
class B(A):
pass

View File

@@ -1,6 +0,0 @@
class Abstract:
def method(self):
raise NotImplementedError()
class <weak_warning descr="Class Concrete must implement all abstract methods">Concrete</weak_warning>(Abstract):
pass

View File

@@ -15,7 +15,8 @@ public class PyAbstractClassInspectionTest extends PyInspectionTestCase {
doTest();
}
public void testSuperMethodRaisesNotImplementerError() {
// PY-38680
public void testClassWithMethodWhichRaisesNotImplementedErrorNotTreatedAsAbstract() {
doTest();
}