mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
PY-76149 Support descriptor types as annotations for dataclass fields
(cherry picked from commit 78a127e1a0083ece810ad996124ad6ea65887da2) GitOrigin-RevId: 0c33fe51f5f13116f773577056317c537cbc83ef
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4ad6f08f45
commit
c653a43cab
@@ -254,6 +254,12 @@ class PyDataclassTypeProvider : PyTypeProviderBase() {
|
|||||||
if (type is PyCollectionType && type.classQName == Dataclasses.DATACLASSES_INITVAR) {
|
if (type is PyCollectionType && type.classQName == Dataclasses.DATACLASSES_INITVAR) {
|
||||||
return type.elementTypes.firstOrNull()
|
return type.elementTypes.firstOrNull()
|
||||||
}
|
}
|
||||||
|
if (type is PyClassLikeType) {
|
||||||
|
val expectedConstructorArgumentTypeRef = PyDescriptorTypeUtil.getExpectedValueTypeForDunderSet(field, type, context)
|
||||||
|
if (expectedConstructorArgumentTypeRef != null) {
|
||||||
|
return Ref.deref(expectedConstructorArgumentTypeRef)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (type == null && dataclassType.asPredefinedType == PyDataclassParameters.PredefinedType.ATTRS) {
|
if (type == null && dataclassType.asPredefinedType == PyDataclassParameters.PredefinedType.ATTRS) {
|
||||||
methodDecoratedAsAttributeDefault(cls, field.name)
|
methodDecoratedAsAttributeDefault(cls, field.name)
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
from typing import dataclass_transform, TypeVar, Generic
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
@dataclass_transform()
|
||||||
|
def deco(cls):
|
||||||
|
...
|
||||||
|
|
||||||
|
class MyDescriptor(Generic[T]):
|
||||||
|
def __set__(self, obj: object, value: T) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
@deco
|
||||||
|
class MyClass:
|
||||||
|
id: MyDescriptor[int]
|
||||||
|
name: MyDescriptor[str]
|
||||||
|
year: MyDescriptor[int]
|
||||||
|
new: MyDescriptor[bool]
|
||||||
|
|
||||||
|
MyClass(<arg1>)
|
||||||
@@ -1345,6 +1345,12 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
|
|||||||
feignCtrlPWithHintsForHighlightedOnly(marks.get("<arg1>").getTextOffset()).check("a, b, c: str = \"default\"", new String[]{"c: str = \"default\""});
|
feignCtrlPWithHintsForHighlightedOnly(marks.get("<arg1>").getTextOffset()).check("a, b, c: str = \"default\"", new String[]{"c: str = \"default\""});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PY-76149
|
||||||
|
public void testDataclassTransformConstructorSignatureWithFieldsAnnotatedWithGenericDescriptor() {
|
||||||
|
final Map<String, PsiElement> marks = loadTest(1);
|
||||||
|
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("id: int, name: str, year: int, new: bool", new String[]{"id: int, "});
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Collector feignCtrlP(int offset) {
|
private Collector feignCtrlP(int offset) {
|
||||||
return feignCtrlP(offset, myFixture.getFile(), true, myFixture.getEditor());
|
return feignCtrlP(offset, myFixture.getFile(), true, myFixture.getEditor());
|
||||||
|
|||||||
@@ -5970,6 +5970,86 @@ public class PyTypingTest extends PyTestCase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PY-76149
|
||||||
|
public void testDataclassTransformConstructorSignatureWithFieldsAnnotatedWithDescriptor() {
|
||||||
|
doTestExpressionUnderCaret("(id: int, name: str) -> MyClass", """
|
||||||
|
from typing import dataclass_transform
|
||||||
|
|
||||||
|
@dataclass_transform()
|
||||||
|
def deco(cls):
|
||||||
|
...
|
||||||
|
|
||||||
|
class MyIdDescriptor:
|
||||||
|
def __set__(self, obj: object, value: int) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
class MyNameDescriptor:
|
||||||
|
def __set__(self, obj: object, value: str) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
@deco
|
||||||
|
class MyClass:
|
||||||
|
id: MyIdDescriptor
|
||||||
|
name: MyNameDescriptor
|
||||||
|
|
||||||
|
MyCl<caret>ass()
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
// PY-76149
|
||||||
|
public void testDataclassTransformConstructorSignatureWithFieldsAnnotatedWithGenericDescriptor() {
|
||||||
|
doTestExpressionUnderCaret("(id: int, name: str) -> MyClass", """
|
||||||
|
from typing import dataclass_transform, TypeVar, Generic
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
@dataclass_transform()
|
||||||
|
def deco(cls):
|
||||||
|
...
|
||||||
|
|
||||||
|
class MyDescriptor(Generic[T]):
|
||||||
|
def __set__(self, obj: object, value: T) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
@deco
|
||||||
|
class MyClass:
|
||||||
|
id: MyDescriptor[int]
|
||||||
|
name: MyDescriptor[str]
|
||||||
|
|
||||||
|
MyCl<caret>ass()
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
// PY-76149
|
||||||
|
public void testDataclassTransformConstructorSignatureWithFieldsAnnotatedWitExplicitAny() {
|
||||||
|
doTestExpressionUnderCaret("(id: int, name: str, payload: Any, payload_length: int) -> MyClass", """
|
||||||
|
from typing import dataclass_transform, TypeVar, Generic, Any
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
@dataclass_transform()
|
||||||
|
def deco(cls):
|
||||||
|
...
|
||||||
|
|
||||||
|
class MyDescriptor(Generic[T]):
|
||||||
|
def __set__(self, obj: object, value: T) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
class Anything:
|
||||||
|
def __set__(self, obj: object, value: Any) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
@deco
|
||||||
|
class MyClass:
|
||||||
|
id: MyDescriptor[int]
|
||||||
|
name: MyDescriptor[str]
|
||||||
|
payload: Anything
|
||||||
|
payload_length: MyDescriptor[int]
|
||||||
|
|
||||||
|
My<caret>Class()
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
private void doTestNoInjectedText(@NotNull String text) {
|
private void doTestNoInjectedText(@NotNull String text) {
|
||||||
myFixture.configureByText(PythonFileType.INSTANCE, text);
|
myFixture.configureByText(PythonFileType.INSTANCE, text);
|
||||||
final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(myFixture.getProject());
|
final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(myFixture.getProject());
|
||||||
|
|||||||
Reference in New Issue
Block a user