From 315b33c41fd0030bd83eb4bcb957f246ff8902f1 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Thu, 11 Jan 2018 17:58:03 +0300 Subject: [PATCH] Highlight the case when `default` and `default_factory` are specified (PY-27398) --- .../python/inspections/PyDataclassInspection.kt | 15 +++++++++++++-- .../fieldDefaultAndDefaultFactory.py | 7 +++++++ .../inspections/PyDataclassInspectionTest.java | 5 +++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 python/testData/inspections/PyDataclassInspection/fieldDefaultAndDefaultFactory.py diff --git a/python/src/com/jetbrains/python/inspections/PyDataclassInspection.kt b/python/src/com/jetbrains/python/inspections/PyDataclassInspection.kt index bb267e2a357e..d5e2d8058b4e 100644 --- a/python/src/com/jetbrains/python/inspections/PyDataclassInspection.kt +++ b/python/src/com/jetbrains/python/inspections/PyDataclassInspection.kt @@ -16,6 +16,7 @@ import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider import com.jetbrains.python.psi.* import com.jetbrains.python.psi.impl.PyBuiltinCache import com.jetbrains.python.psi.impl.PyCallExpressionHelper +import com.jetbrains.python.psi.impl.stubs.PyDataclassFieldStubImpl import com.jetbrains.python.psi.resolve.PyResolveContext import com.jetbrains.python.psi.types.* @@ -55,8 +56,9 @@ class PyDataclassInspection : PyInspection() { node.processClassLevelDeclarations { element, _ -> if (element is PyTargetExpression && !PyTypingTypeProvider.isClassVar(element, myTypeEvalContext)) { - processDefaultFieldValue(element) - processAsInitVar(element, postInit)?.let { initVars.add(it) } + processDefaultFieldValue(element) + processAsInitVar(element, postInit)?.let { initVars.add(it) } + processFieldFunctionCall(element) } true @@ -189,6 +191,15 @@ class PyDataclassInspection : PyInspection() { return null } + private fun processFieldFunctionCall(field: PyTargetExpression) { + val fieldStub = PyDataclassFieldStubImpl.create(field) + if (fieldStub != null && fieldStub.hasDefault() && fieldStub.hasDefaultFactory()) { + val call = field.findAssignedValue() as? PyCallExpression ?: return + + registerProblem(call.argumentList, "cannot specify both default and default_factory", ProblemHighlightType.GENERIC_ERROR) + } + } + private fun processPostInitDefinition(postInit: PyFunction, dataclassParameters: DataclassParameters, initVars: List) { diff --git a/python/testData/inspections/PyDataclassInspection/fieldDefaultAndDefaultFactory.py b/python/testData/inspections/PyDataclassInspection/fieldDefaultAndDefaultFactory.py new file mode 100644 index 000000000000..e4b41db46488 --- /dev/null +++ b/python/testData/inspections/PyDataclassInspection/fieldDefaultAndDefaultFactory.py @@ -0,0 +1,7 @@ +import dataclasses + +@dataclasses.dataclass +class E1: + a: int = dataclasses.field(default=1) + b: int = dataclasses.field(default_factory=int) + c: int = dataclasses.field(default=1, default_factory=int) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyDataclassInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyDataclassInspectionTest.java index acb0fb96a129..68d4c47141dd 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyDataclassInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyDataclassInspectionTest.java @@ -71,6 +71,11 @@ public class PyDataclassInspectionTest extends PyInspectionTestCase { doTest(); } + // PY-27398 + public void testFieldDefaultAndDefaultFactory() { + doTest(); + } + @Override protected void doTest() { runWithLanguageLevel(