Fix highlighting classes that use 'Final' classes as metaclasses (PEP 591) (PY-34945)

GitOrigin-RevId: dce7e7f371a46f00b0e6847b417a477842d4e709
This commit is contained in:
Semyon Proshev
2019-07-02 06:52:16 +03:00
committed by intellij-monorepo-bot
parent 19d5784874
commit 9094332d2e
3 changed files with 33 additions and 8 deletions
@@ -30,11 +30,11 @@ class PyFinalInspection : PyInspection() {
override fun visitPyClass(node: PyClass) {
super.visitPyClass(node)
node.superClassExpressions.forEach {
val cls = (myTypeEvalContext.getType(it) as? PyClassType)?.pyClass
if (cls != null && isFinal(cls)) {
registerProblem(it, "'${cls.name}' is marked as '@final' and should not be subclassed")
}
node.getSuperClasses(myTypeEvalContext).filter { isFinal(it) }.let { finalSuperClasses ->
if (finalSuperClasses.isEmpty()) return@let
val postfix = " ${if (finalSuperClasses.size == 1) "is" else "are"} marked as '@final' and should not be subclassed"
registerProblem(node.nameIdentifier, finalSuperClasses.joinToString(postfix = postfix) { "'${it.name}'" ?: "" })
}
if (PyiUtil.isInsideStub(node)) {
@@ -1,3 +1,3 @@
from b import A
class B(<warning descr="'A' is marked as '@final' and should not be subclassed">A</warning>):
class <warning descr="'A' is marked as '@final' and should not be subclassed">B</warning>(A):
pass
@@ -16,8 +16,33 @@ public class PyFinalInspectionTest extends PyInspectionTestCase {
"@final\n" +
"class A:\n" +
" pass\n" +
"class B(<warning descr=\"'A' is marked as '@final' and should not be subclassed\">A</warning>):\n" +
"class <warning descr=\"'A' is marked as '@final' and should not be subclassed\">B</warning>(A):\n" +
" pass");
doTestByText("from typing_extensions import final\n" +
"@final\n" +
"class A:\n" +
" pass\n" +
"@final\n" +
"class B:\n" +
" pass\n" +
"class <warning descr=\"'A', 'B' are marked as '@final' and should not be subclassed\">C</warning>(A, B):\n" +
" pass");
}
// PY-34945
public void testFinalClassAsMetaclass() {
runWithLanguageLevel(
LanguageLevel.PYTHON30,
() -> doTestByText("from typing_extensions import final\n" +
"\n" +
"@final\n" +
"class MT(type):\n" +
" pass\n" +
"\n" +
"class A(metaclass=MT):\n" +
" pass")
);
}
// PY-34945
@@ -416,7 +441,7 @@ public class PyFinalInspectionTest extends PyInspectionTestCase {
" <warning descr=\"'a' is 'Final' and could not be reassigned\">a</warning> = 2")
);
}
// PY-34945
public void testNonLocalReassignment() {
runWithLanguageLevel(