Ignore classvars when inspecting fields order (PY-27398)

This commit is contained in:
Semyon Proshev
2018-01-09 14:39:27 +03:00
parent dca4c8fcce
commit 8d6db3fcb1
3 changed files with 33 additions and 6 deletions
@@ -76,7 +76,7 @@ class PyDataclassInspection : PyInspection() {
true
}
PyNamedTupleInspection.inspectFieldsOrder(node, this::registerProblem)
PyNamedTupleInspection.inspectFieldsOrder(node, myTypeEvalContext, this::registerProblem)
}
}
}
@@ -14,13 +14,14 @@ import com.jetbrains.python.psi.LanguageLevel
import com.jetbrains.python.psi.PyClass
import com.jetbrains.python.psi.PyTargetExpression
import com.jetbrains.python.psi.types.PyClassLikeType
import com.jetbrains.python.psi.types.TypeEvalContext
import java.util.*
class PyNamedTupleInspection : PyInspection() {
companion object {
fun inspectFieldsOrder(cls: PyClass, callback: (PsiElement, String, ProblemHighlightType) -> Unit) {
val fieldsProcessor = FieldsProcessor()
fun inspectFieldsOrder(cls: PyClass, context: TypeEvalContext, callback: (PsiElement, String, ProblemHighlightType) -> Unit) {
val fieldsProcessor = FieldsProcessor(context)
cls.processClassLevelDeclarations(fieldsProcessor)
@@ -52,7 +53,7 @@ class PyNamedTupleInspection : PyInspection() {
super.visitPyClass(node)
if (node != null && LanguageLevel.forElement(node).isAtLeast(LanguageLevel.PYTHON36) && isTypingNTInheritor(node)) {
inspectFieldsOrder(node, this::registerProblem)
inspectFieldsOrder(node, myTypeEvalContext, this::registerProblem)
}
}
@@ -64,7 +65,7 @@ class PyNamedTupleInspection : PyInspection() {
}
}
private class FieldsProcessor : PsiScopeProcessor {
private class FieldsProcessor(private val context: TypeEvalContext) : PsiScopeProcessor {
val lastFieldWithoutDefaultValue: PyTargetExpression?
get() = lastFieldWithoutDefaultValueBox.result
@@ -80,6 +81,11 @@ class PyNamedTupleInspection : PyInspection() {
override fun execute(element: PsiElement, state: ResolveState): Boolean {
if (element is PyTargetExpression) {
val annotation = element.annotation
if (annotation != null && PyTypingTypeProvider.isClassVarAnnotation(annotation, context)) {
return true
}
when {
element.findAssignedValue() != null -> fieldsWithDefaultValue.add(element)
else -> lastFieldWithoutDefaultValueBox.apply(element)
@@ -1,4 +1,5 @@
import dataclasses
from typing import ClassVar
@dataclasses.dataclass
@@ -15,4 +16,24 @@ class A1:
class A2:
bar: int
baz: str = ""
foo: int = 5
foo: int = 5
@dataclasses.dataclass
class A3:
bar1: int
baz1: ClassVar[int] = 1
foo1: int
bar2: ClassVar[int] = 2
baz2: int
foo2: int = 3
@dataclasses.dataclass
class A4:
bar1: int
baz1: ClassVar = 1
foo1: int
bar2: ClassVar = 2
baz2: int
foo2: int = 3