Check attrs initializers and validators signatures (PY-26354)

This commit is contained in:
Semyon Proshev
2018-05-29 16:50:01 +03:00
parent 121a1ff678
commit 06e2412069
3 changed files with 68 additions and 0 deletions
@@ -90,6 +90,7 @@ class PyDataclassInspection : PyInspection() {
?.also { processAttrsPostInitDefinition(it, dataclassParameters) }
processAttrsDefaultThroughDecorator(node)
processAttrsInitializersAndValidators(node)
}
PyNamedTupleInspection.inspectFieldsOrder(
@@ -361,6 +362,41 @@ class PyDataclassInspection : PyInspection() {
}
}
private fun processAttrsInitializersAndValidators(cls: PyClass) {
cls.visitMethods(
{ method ->
val decorators = method.decoratorList?.decorators
if (decorators != null) {
decorators
.asSequence()
.mapNotNull { it.qualifiedName }
.filter { it.componentCount == 2 }
.mapNotNull { it.lastComponent }
.forEach {
val expectedParameters = when (it) {
"default" -> 1
"validator" -> 3
else -> return@forEach
}
val actualParameters = method.parameterList
if (actualParameters.parameters.size != expectedParameters) {
val message = "'${method.name}' should take only $expectedParameters parameter" +
if (expectedParameters > 1) "s" else ""
registerProblem(actualParameters, message, ProblemHighlightType.GENERIC_ERROR)
}
}
}
true
},
false,
myTypeEvalContext
)
}
private fun processAsInitVar(field: PyTargetExpression, postInit: PyFunction?): PyTargetExpression? {
if (isInitVar(field)) {
if (postInit == null) {
@@ -0,0 +1,27 @@
import attr
@attr.s
class A:
x = attr.ib()
@x.default
def init_x1(self):
return 10
@x.validator
def check_x1(self, attribute, value):
pass
@attr.s
class A:
x = attr.ib()
@x.default
def init_x2<error descr="'init_x2' should take only 1 parameter">(self, attribute, value)</error>:
return 10
@x.validator
def check_x2<error descr="'check_x2' should take only 3 parameters">(self)</error>:
pass
@@ -161,6 +161,11 @@ public class PyDataclassInspectionTest extends PyInspectionTestCase {
doTest();
}
// PY-26354
public void testAttrsInitializersAndValidators() {
doTest();
}
@Override
protected void doTest() {
runWithLanguageLevel(