mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Update inspection for Final variables without assigned values (PEP 591) (PY-34945)
Highlight class level finals that have no assignments in `__init__` GitOrigin-RevId: 28f5f655889df475d6a7b1084cd951a80e31e2cf
This commit is contained in:
committed by
intellij-monorepo-bot
parent
61cbd62808
commit
1dd5ee7103
@@ -5,6 +5,7 @@ import com.intellij.codeInspection.LocalInspectionToolSession
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.impl.source.resolve.FileContextUtil
|
||||
import com.jetbrains.python.PyNames
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil
|
||||
@@ -15,6 +16,7 @@ import com.jetbrains.python.documentation.doctest.PyDocstringFile
|
||||
import com.jetbrains.python.psi.*
|
||||
import com.jetbrains.python.psi.PyKnownDecoratorUtil.KnownDecorator.TYPING_FINAL
|
||||
import com.jetbrains.python.psi.PyKnownDecoratorUtil.KnownDecorator.TYPING_FINAL_EXT
|
||||
import com.jetbrains.python.psi.impl.PyClassImpl
|
||||
import com.jetbrains.python.psi.search.PySuperMethodsSearch
|
||||
import com.jetbrains.python.psi.types.PyClassType
|
||||
import com.jetbrains.python.pyi.PyiUtil
|
||||
@@ -51,6 +53,9 @@ class PyFinalInspection : PyInspection() {
|
||||
myTypeEvalContext
|
||||
)
|
||||
}
|
||||
else {
|
||||
checkClassLevelFinalsAreInitialized(node)
|
||||
}
|
||||
|
||||
checkRedeclarationsInScope(node)
|
||||
}
|
||||
@@ -131,6 +136,28 @@ class PyFinalInspection : PyInspection() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkClassLevelFinalsAreInitialized(cls: PyClass) {
|
||||
val notInitializedFinals = mutableMapOf<String?, PyTargetExpression>()
|
||||
|
||||
cls.classAttributes.forEach {
|
||||
if (!it.hasAssignedValue() && isFinal(it)) {
|
||||
notInitializedFinals[it.name] = it
|
||||
}
|
||||
}
|
||||
|
||||
if (notInitializedFinals.isNotEmpty()) {
|
||||
cls.findMethodByName(PyNames.INIT, false, myTypeEvalContext)?.let {
|
||||
val initializedAttributes = mutableMapOf<String, PyTargetExpression>()
|
||||
PyClassImpl.collectInstanceAttributes(it, initializedAttributes)
|
||||
notInitializedFinals -= initializedAttributes.keys
|
||||
}
|
||||
|
||||
notInitializedFinals.values.forEach {
|
||||
registerProblem(it, "'Final' name should be initialized with a value")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkFinalIsOuterMost(node: PyReferenceExpression) {
|
||||
if (isTopLevelInAnnotationOrTypeComment(node)) return
|
||||
(node.parent as? PySubscriptionExpression)?.let {
|
||||
|
||||
@@ -89,16 +89,19 @@ public class PyFinalInspectionTest extends PyInspectionTestCase {
|
||||
() -> doTestByText("from typing_extensions import Final\n" +
|
||||
"\n" +
|
||||
"class A:\n" +
|
||||
" a: <warning descr=\"If assigned value is omitted, there should be an explicit type argument to 'Final'\">Final</warning>\n" +
|
||||
" b: Final[int]\n" +
|
||||
" <warning descr=\"'Final' name should be initialized with a value\">a</warning>: <warning descr=\"If assigned value is omitted, there should be an explicit type argument to 'Final'\">Final</warning>\n" +
|
||||
" <warning descr=\"'Final' name should be initialized with a value\">b</warning>: Final[int]\n" +
|
||||
" c: int\n" +
|
||||
"\n" +
|
||||
"MY_FINAL = Final\n" +
|
||||
"MY_FINAL_INT = Final[int]\n" +
|
||||
"\n" +
|
||||
"class B:\n" +
|
||||
" с: <warning descr=\"If assigned value is omitted, there should be an explicit type argument to 'Final'\">MY_FINAL</warning>\n" +
|
||||
" d: MY_FINAL_INT")
|
||||
" <warning descr=\"'Final' name should be initialized with a value\">с</warning>: <warning descr=\"If assigned value is omitted, there should be an explicit type argument to 'Final'\">MY_FINAL</warning>\n" +
|
||||
" d: MY_FINAL_INT" +
|
||||
"\n" +
|
||||
" def __init__(self):\n" +
|
||||
" self.d = 10")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user