Highlight removing frozen dataclass attribute (PY-28957)

This commit is contained in:
Semyon Proshev
2018-03-20 14:20:25 +03:00
parent b9d34fb91e
commit 5d1e935acb
3 changed files with 30 additions and 5 deletions
@@ -37,9 +37,18 @@ class PyDataclassInspection : PyInspection() {
override fun visitPyTargetExpression(node: PyTargetExpression?) {
super.visitPyTargetExpression(node)
val cls = getInstancePyClass(node?.qualifier) ?: return
if (parseDataclassParameters(cls, myTypeEvalContext)?.frozen == true) {
registerProblem(node, "'${cls.name}' object attribute '${node!!.name}' is read-only", ProblemHighlightType.GENERIC_ERROR)
if (node != null) checkMutatingFrozenAttribute(node)
}
override fun visitPyDelStatement(node: PyDelStatement?) {
super.visitPyDelStatement(node)
if (node != null) {
node
.targets
.asSequence()
.filterIsInstance<PyReferenceExpression>()
.forEach { checkMutatingFrozenAttribute(it) }
}
}
@@ -158,6 +167,13 @@ class PyDataclassInspection : PyInspection() {
}
}
private fun checkMutatingFrozenAttribute(expression: PyQualifiedExpression) {
val cls = getInstancePyClass(expression.qualifier) ?: return
if (parseDataclassParameters(cls, myTypeEvalContext)?.frozen == true) {
registerProblem(expression, "'${cls.name}' object attribute '${expression.name}' is read-only", ProblemHighlightType.GENERIC_ERROR)
}
}
private fun getInstancePyClass(element: PyTypedElement?): PyClass? {
val type = element?.let { myTypeEvalContext.getType(it) } as? PyClassType
return if (type != null && !type.isDefinition) type.pyClass else null
@@ -12,6 +12,9 @@ b1 = B1(1, "2")
b1.x = 2
b1.y = "3"
b1.z = 1.0
del b1.x
del b1.y
del b1.z
@dataclasses.dataclass(frozen=False)
@@ -25,6 +28,9 @@ b2 = B2(1, "2")
b2.x = 2
b2.y = "3"
b2.z = 1.0
del b2.x
del b2.y
del b2.z
@dataclasses.dataclass(frozen=True)
@@ -37,4 +43,7 @@ B3.x = 5
b3 = B3(1, "2")
<error descr="'B3' object attribute 'x' is read-only">b3.x</error> = 2
<error descr="'B3' object attribute 'y' is read-only">b3.y</error> = "3"
<error descr="'B3' object attribute 'z' is read-only">b3.z</error> = 1.0
<error descr="'B3' object attribute 'z' is read-only">b3.z</error> = 1.0
del <error descr="'B3' object attribute 'x' is read-only">b3.x</error>
del <error descr="'B3' object attribute 'y' is read-only">b3.y</error>
del <error descr="'B3' object attribute 'z' is read-only">b3.z</error>
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable;
public class PyDataclassInspectionTest extends PyInspectionTestCase {
// PY-27398
public void testAssignmentsToFrozen() {
public void testMutatingFrozen() {
doTest();
}