Revert "PY-79480 Resolve attribute reference to ancestor attributes in constructors if they contain type annotations"

Fixes PY-79997 performance regression

GitOrigin-RevId: 9bccec0543fcdf7970311c187bd9fd9b1357c058
This commit is contained in:
evgeny.bovykin
2025-03-30 20:17:51 +02:00
committed by intellij-monorepo-bot
parent aad1ea1876
commit aaa808c3b4
6 changed files with 19 additions and 188 deletions

View File

@@ -2154,28 +2154,6 @@ public abstract class PyCommonResolveTest extends PyCommonResolveTestCase {
""", PyTargetExpression.class, "Alias");
}
// PY-79480
public void testInheritedAttributeWithTypeAnnotationInParentConstructor() {
runWithLanguageLevel(LanguageLevel.PYTHON312, () -> {
PyTargetExpression resolved = assertResolvesTo(PyTargetExpression.class, "_some_var");
assertEquals("FakeBase", resolved.getContainingClass().getName());
});
}
public void testInheritedAttributeWithTypeAnnotationInParent() {
runWithLanguageLevel(LanguageLevel.PYTHON312, () -> {
PyTargetExpression resolved = assertResolvesTo(PyTargetExpression.class, "_some_var");
assertEquals("Fake", resolved.getContainingClass().getName());
});
}
public void testInheritedAttributeWithTypeAnnotationInChild() {
runWithLanguageLevel(LanguageLevel.PYTHON312, () -> {
PyTargetExpression resolved = assertResolvesTo(PyTargetExpression.class, "_some_var");
assertEquals("Fake", resolved.getContainingClass().getName());
});
}
private void assertResolvedElement(@NotNull LanguageLevel languageLevel, @NotNull String text, @NotNull Consumer<PsiElement> assertion) {
runWithLanguageLevel(languageLevel, () -> {
myFixture.configureByText(PythonFileType.INSTANCE, text);

View File

@@ -172,24 +172,6 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
}
}
if (inherited) {
List<PyClassLikeType> typesToSearch = new ArrayList<>();
typesToSearch.add(this);
typesToSearch.addAll(myClass.getAncestorTypes(context));
Condition<RatedResolveResult> membersWithAnnotationsFilter = member -> {
PsiElement element = member.getElement();
if (element == null) return false;
if (element instanceof PyTargetExpression target) {
return target.getAnnotationValue() != null && target.hasAssignedValue();
}
return false;
};
List<? extends RatedResolveResult> membersWithTypeAnnotation =
findMembersInClasses(name, location, direction, resolveContext, typesToSearch, context, membersWithAnnotationsFilter);
if (!membersWithTypeAnnotation.isEmpty()) return membersWithTypeAnnotation;
}
final List<? extends RatedResolveResult> classMembers = resolveInner(myClass, myIsDefinition, name, location, context);
if (!classMembers.isEmpty()) {
return classMembers;
@@ -206,11 +188,25 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
return list;
}
if (inherited) {
List<? extends RatedResolveResult> superMembers =
findMembersInClasses(name, location, direction, resolveContext, myClass.getAncestorTypes(context), context, null);
if (!superMembers.isEmpty()) {
return superMembers;
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
if (type instanceof PyClassType) {
if (!myIsDefinition) {
type = type.toInstance();
}
final List<? extends RatedResolveResult> superMembers =
resolveInner(((PyClassType)type).getPyClass(), myIsDefinition, name, location, context);
if (!superMembers.isEmpty()) {
return superMembers;
}
}
if (type != null) {
final List<? extends RatedResolveResult> results = type.resolveMember(name, location, direction, resolveContext, false);
if (results != null && !results.isEmpty()) {
return results;
}
}
}
}
@@ -248,54 +244,6 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
return Collections.emptyList();
}
private @NotNull List<? extends RatedResolveResult> findMembersInClasses(
@NotNull String name,
@Nullable PyExpression location,
@NotNull AccessDirection direction,
@NotNull PyResolveContext resolveContext,
@NotNull List<PyClassLikeType> typesToSearch,
@NotNull TypeEvalContext context,
@Nullable Condition<RatedResolveResult> membersFilter
) {
for (PyClassLikeType type : typesToSearch) {
if (type instanceof PyClassType) {
if (!myIsDefinition) {
type = type.toInstance();
}
List<? extends RatedResolveResult> members =
resolveInner(((PyClassType)type).getPyClass(), myIsDefinition, name, location, context);
final List<? extends RatedResolveResult> filteredMembers;
if (membersFilter != null) {
filteredMembers = ContainerUtil.filter(
members,
membersFilter);
} else {
filteredMembers = members;
}
if (!filteredMembers.isEmpty()) {
return filteredMembers;
}
}
if (type != null) {
final List<? extends RatedResolveResult> results = type.resolveMember(name, location, direction, resolveContext, false);
if (results != null) {
List<? extends RatedResolveResult> filteredResults;
if (membersFilter != null) {
filteredResults = ContainerUtil.filter(results, membersFilter);
} else {
filteredResults = results;
}
if (!filteredResults.isEmpty()) {
return results;
}
}
}
}
return Collections.emptyList();
}
private @Nullable List<? extends RatedResolveResult> resolveMetaClassMember(@NotNull String name,
@Nullable PyExpression location,
@NotNull AccessDirection direction,

View File

@@ -1,14 +0,0 @@
import typing
class FakeBase:
def __init__(self):
_some_var = 1
class Fake(FakeBase):
def __init__(self):
super().__init__()
self._some_var: typing.Optional[str] = None
def some_method(self):
expr = self._some_var
# <ref>

View File

@@ -1,13 +0,0 @@
import typing
class FakeBase:
_some_var: typing.Optional[str]
class Fake(FakeBase):
def __init__(self):
super().__init__()
self._some_var = None
def some_method(self):
expr = self._some_var
# <ref>

View File

@@ -1,14 +0,0 @@
import typing
class FakeBase:
def __init__(self):
self._some_var: typing.Optional[str] = ""
class Fake(FakeBase):
def __init__(self):
super().__init__()
self._some_var = None
def some_method(self):
expr = self._some_var
# <ref>

View File

@@ -1959,7 +1959,7 @@ public class PyTypingTest extends PyTestCase {
if issubclass(a, str | dict | int):
expr = a""");
}
// PY-79861
public void testWalrusIsSubclass() {
doTest("Type[str | dict | int]",
@@ -6370,60 +6370,6 @@ public class PyTypingTest extends PyTestCase {
""");
}
// PY-79480
public void testInheritedAttributeWithTypeAnnotationInParentConstructor() {
doTest("str | None", """
import typing
class FakeBase:
def __init__(self):
self._some_var: typing.Optional[str] = ""
class Fake(FakeBase):
def __init__(self):
super().__init__()
self._some_var = None
def some_method(self):
expr = self._some_var
""");
}
public void testInheritedAttributeWithTypeAnnotationInParent() {
doTest("str | None", """
import typing
class FakeBase:
_some_var: typing.Optional[str]
class Fake(FakeBase):
def __init__(self):
super().__init__()
self._some_var = None
def some_method(self):
expr = self._some_var
""");
}
public void testInheritedAttributeWithTypeAnnotationInChild() {
doTest("str | None", """
import typing
class FakeBase:
def __init__(self):
self._some_var = 1
class Fake(FakeBase):
def __init__(self):
super().__init__()
self._some_var: typing.Optional[str] = None
def some_method(self):
expr = self._some_var
""");
}
// PY-43122
public void testPropertyOfImportedClass() {
doMultiFileStubAwareTest("str",