Highlight init-only fields when __post_init__ is not declared (PY-27398)

This commit is contained in:
Semyon Proshev
2018-01-22 22:52:05 +03:00
parent ce63287531
commit 47b5e556b8
3 changed files with 28 additions and 6 deletions
@@ -8,6 +8,7 @@ import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElementVisitor
import com.jetbrains.python.codeInsight.stdlib.DATACLASSES_INITVAR_TYPE
import com.jetbrains.python.codeInsight.stdlib.DUNDER_POST_INIT
import com.jetbrains.python.codeInsight.stdlib.parseDataclassParameters
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider
import com.jetbrains.python.psi.*
@@ -52,25 +53,35 @@ class PyDataclassInspection : PyInspection() {
}
}
val hasPostInit = node.findMethodByName(DUNDER_POST_INIT, false, myTypeEvalContext) != null
node.processClassLevelDeclarations { element, _ ->
if (element is PyTargetExpression && element.annotationValue != null) {
val annotation = element.annotation
if (annotation != null && !PyTypingTypeProvider.isClassVarAnnotation(annotation, myTypeEvalContext)) {
val value = element.findAssignedValue()
val cls = getInstancePyClass(value)
val valueClass = getInstancePyClass(value)
if (cls != null) {
if (valueClass != null) {
val builtinCache = PyBuiltinCache.getInstance(node)
if (cls == builtinCache.listType?.pyClass ||
cls == builtinCache.setType?.pyClass ||
cls == builtinCache.tupleType?.pyClass) {
if (valueClass == builtinCache.listType?.pyClass ||
valueClass == builtinCache.setType?.pyClass ||
valueClass == builtinCache.tupleType?.pyClass) {
registerProblem(value,
"mutable default '${cls.name}' is not allowed",
"mutable default '${valueClass.name}' is not allowed",
ProblemHighlightType.GENERIC_ERROR)
}
}
else if (!hasPostInit) {
val type = myTypeEvalContext.getType(element)
if (type is PyClassType && type.classQName == DATACLASSES_INITVAR_TYPE) {
registerProblem(element,
"attribute '${element.name}' is useless until '${DUNDER_POST_INIT}' is declared",
ProblemHighlightType.LIKE_UNUSED_SYMBOL)
}
}
}
}
@@ -0,0 +1,6 @@
import dataclasses
@dataclasses.dataclass
class A:
a: int
<warning descr="attribute 'b' is useless until '__post_init__' is declared">b</warning>: dataclasses.InitVar[str]
@@ -56,6 +56,11 @@ public class PyDataclassInspectionTest extends PyInspectionTestCase {
doTest();
}
// PY-27398
public void testUselessInitVar() {
doTest();
}
@Override
protected void doTest() {
runWithLanguageLevel(