Fix processing mixed dataclass hierarchy when non-dataclass has __init__ (PY-28506, PY-31762, PY-33173)

This commit is contained in:
Semyon Proshev
2018-12-28 12:41:07 +03:00
parent a349fad10c
commit 6f6b19252c
6 changed files with 80 additions and 12 deletions
@@ -115,10 +115,12 @@ class PyDataclassTypeProvider : PyTypeProviderBase() {
var seenInit = false
for (currentType in StreamEx.of(clsType).append(cls.getAncestorTypes(context))) {
if (currentType == null) break
if (!currentType.resolveMember(PyNames.INIT, null, AccessDirection.READ, resolveContext, false).isNullOrEmpty()) break
if (!currentType.resolveMember(PyNames.NEW, null, AccessDirection.READ, resolveContext, false).isNullOrEmpty()) break
if (currentType !is PyClassType) break
if (currentType == null ||
!currentType.resolveMember(PyNames.INIT, null, AccessDirection.READ, resolveContext, false).isNullOrEmpty() ||
!currentType.resolveMember(PyNames.NEW, null, AccessDirection.READ, resolveContext, false).isNullOrEmpty() ||
currentType !is PyClassType) {
if (seenInit) continue else break
}
val current = currentType.pyClass
if (PyKnownDecoratorUtil.hasUnknownDecorator(current, context)) break
@@ -39,4 +39,19 @@ class A4:
class B4(A4):
b: str
evolve(B4(), <arg4>)
evolve(B4(), <arg4>)
@dataclass
class A5:
x: int
class B5(A5):
def __init__(self):
pass
@dataclass
class C5(B5):
z: str
evolve(C5(1, "2"), <arg5>)
@@ -39,4 +39,19 @@ class A4:
class B4(A4):
b: str
replace(B4(), <arg4>)
replace(B4(), <arg4>)
@dataclass
class A5:
x: int
class B5(A5):
def __init__(self):
pass
@dataclass
class C5(B5):
z: str
replace(C5(1, "2"), <arg5>)
@@ -39,4 +39,19 @@ class A4:
class B4(A4):
b: str
B4(<arg4>)
B4(<arg4>)
@dataclass
class A5:
x: int
class B5(A5):
def __init__(self):
pass
@dataclass
class C5(B5):
z: str
C5(<arg5>)
@@ -39,4 +39,19 @@ class A4:
class B4(A4):
b: str
B4(<arg4>)
B4(<arg4>)
@dataclass
class A5:
x: int
class B5(A5):
def __init__(self):
pass
@dataclass
class C5(B5):
z: str
C5(<arg5>)
@@ -786,7 +786,7 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
runWithLanguageLevel(
LanguageLevel.PYTHON37,
() -> {
final Map<String, PsiElement> marks = loadMultiFileTest(4);
final Map<String, PsiElement> marks = loadMultiFileTest(5);
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("a: int", new String[]{"a: int"});
feignCtrlP(marks.get("<arg2>").getTextOffset()).check("b: str", new String[]{"b: str"});
@@ -795,6 +795,8 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
feignCtrlP(marks.get("<arg4>").getTextOffset()).check(Arrays.asList("self: object", "cls: object"),
Arrays.asList(ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY),
Arrays.asList(new String[]{"self: object"}, new String[]{"cls: object"}));
feignCtrlP(marks.get("<arg5>").getTextOffset()).check("x: int, z: str", new String[]{"x: int, "});
}
);
}
@@ -871,7 +873,7 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
runWithLanguageLevel(
LanguageLevel.PYTHON37,
() -> {
final Map<String, PsiElement> marks = loadTest(4);
final Map<String, PsiElement> marks = loadTest(5);
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("a: int", new String[]{"a: int"});
feignCtrlP(marks.get("<arg2>").getTextOffset()).check("b: str", new String[]{"b: str"});
@@ -880,6 +882,8 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
feignCtrlP(marks.get("<arg4>").getTextOffset()).check(Arrays.asList("self: object", "cls: object"),
Arrays.asList(ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY),
Arrays.asList(new String[]{"self: object"}, new String[]{"cls: object"}));
feignCtrlP(marks.get("<arg5>").getTextOffset()).check("x: int, z: str", new String[]{"x: int, "});
}
);
}
@@ -920,12 +924,13 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
runWithLanguageLevel(
LanguageLevel.PYTHON37,
() -> {
final Map<String, PsiElement> marks = loadMultiFileTest(4);
final Map<String, PsiElement> marks = loadMultiFileTest(5);
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("obj: B1, *, a: int=...", ArrayUtil.EMPTY_STRING_ARRAY);
feignCtrlP(marks.get("<arg2>").getTextOffset()).check("obj: B2, *, b: str=...", ArrayUtil.EMPTY_STRING_ARRAY);
feignCtrlP(marks.get("<arg3>").getTextOffset()).check("obj, **changes", new String[]{"**changes"});
feignCtrlP(marks.get("<arg4>").getTextOffset()).check("obj, **changes", new String[]{"**changes"});
feignCtrlP(marks.get("<arg5>").getTextOffset()).check("obj: C5, *, x: int=..., z: str=...", ArrayUtil.EMPTY_STRING_ARRAY);
}
);
}
@@ -975,12 +980,13 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
runWithLanguageLevel(
LanguageLevel.PYTHON37,
() -> {
final Map<String, PsiElement> marks = loadTest(4);
final Map<String, PsiElement> marks = loadTest(5);
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("inst: B1, *, a: int=...", ArrayUtil.EMPTY_STRING_ARRAY);
feignCtrlP(marks.get("<arg2>").getTextOffset()).check("inst: B2, *, b: str=...", ArrayUtil.EMPTY_STRING_ARRAY);
feignCtrlP(marks.get("<arg3>").getTextOffset()).check("inst: _T, **changes", new String[]{"**changes"});
feignCtrlP(marks.get("<arg4>").getTextOffset()).check("inst: _T, **changes", new String[]{"**changes"});
feignCtrlP(marks.get("<arg5>").getTextOffset()).check("inst: C5, *, x: int=..., z: str=...", ArrayUtil.EMPTY_STRING_ARRAY);
}
);
}