mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
test fix: passing type eval context
This commit is contained in:
@@ -77,9 +77,10 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine
|
||||
*
|
||||
* @see #getSuperClassTypes(TypeEvalContext) for the full list of super classes.
|
||||
* @see #getAncestorTypes(TypeEvalContext) for the full list of ancestors.
|
||||
* @param context
|
||||
*/
|
||||
@NotNull
|
||||
PyClass[] getSuperClasses();
|
||||
PyClass[] getSuperClasses(@Nullable TypeEvalContext context);
|
||||
|
||||
/**
|
||||
* Returns a PSI element for the super classes list.
|
||||
@@ -239,9 +240,9 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine
|
||||
* @param parent
|
||||
* @return True iff this and parent are the same or parent is one of our superclasses.
|
||||
*/
|
||||
boolean isSubclass(PyClass parent);
|
||||
boolean isSubclass(PyClass parent, @Nullable TypeEvalContext context);
|
||||
|
||||
boolean isSubclass(@NotNull String superClassQName);
|
||||
boolean isSubclass(@NotNull String superClassQName, @Nullable TypeEvalContext context);
|
||||
|
||||
/**
|
||||
* Returns the aggregated list of names defined in __slots__ attributes of the class and its ancestors.
|
||||
|
||||
@@ -30,7 +30,7 @@ public interface PyClassMembersProvider {
|
||||
ExtensionPointName<PyClassMembersProvider> EP_NAME = ExtensionPointName.create("Pythonid.pyClassMembersProvider");
|
||||
|
||||
@NotNull
|
||||
Collection<PyCustomMember> getMembers(final PyClassType clazz, PsiElement location);
|
||||
Collection<PyCustomMember> getMembers(final PyClassType clazz, PsiElement location, @Nullable TypeEvalContext typeEvalContext);
|
||||
|
||||
@Nullable
|
||||
PsiElement resolveMember(PyClassType clazz, String name, @Nullable PsiElement location, @Nullable TypeEvalContext context);
|
||||
|
||||
@@ -30,13 +30,13 @@ import java.util.Collections;
|
||||
public class PyClassMembersProviderBase implements PyClassMembersProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PyCustomMember> getMembers(PyClassType clazz, PsiElement location) {
|
||||
public Collection<PyCustomMember> getMembers(PyClassType clazz, PsiElement location, TypeEvalContext typeEvalContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement resolveMember(PyClassType clazz, String name, PsiElement location, TypeEvalContext context) {
|
||||
final Collection<PyCustomMember> members = getMembers(clazz, location);
|
||||
final Collection<PyCustomMember> members = getMembers(clazz, location, context);
|
||||
return resolveMemberByName(members, clazz, name);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public class PyDunderSlotsReference extends PsiReferenceBase<PyStringLiteralExpr
|
||||
if (element instanceof PyExpression && PyUtil.isInstanceAttribute((PyExpression)element)) {
|
||||
PyClass elementClass = PsiTreeUtil.getParentOfType(element, PyClass.class);
|
||||
PyClass referenceClass = PsiTreeUtil.getParentOfType(myElement, PyClass.class);
|
||||
if (referenceClass != null && referenceClass.isSubclass(elementClass)) {
|
||||
if (referenceClass != null && referenceClass.isSubclass(elementClass, null)) {
|
||||
String elementName = ((PyTargetExpression) element).getReferencedName();
|
||||
String referenceName = myElement.getStringValue();
|
||||
if (Comparing.equal(elementName, referenceName)) {
|
||||
|
||||
@@ -141,7 +141,7 @@ class ImportCandidateHolder implements Comparable<ImportCandidateHolder> {
|
||||
sb.append(((PyFunction)myImportable).getParameterList().getPresentableText(false));
|
||||
}
|
||||
else if (myImportable instanceof PyClass) {
|
||||
final List<String> supers = ContainerUtil.mapNotNull(((PyClass)myImportable).getSuperClasses(), new Function<PyClass, String>() {
|
||||
final List<String> supers = ContainerUtil.mapNotNull(((PyClass)myImportable).getSuperClasses(null), new Function<PyClass, String>() {
|
||||
@Override
|
||||
public String fun(PyClass cls) {
|
||||
return PyUtil.isObjectClass(cls) ? null : cls.getName();
|
||||
|
||||
+2
-1
@@ -24,6 +24,7 @@ import com.jetbrains.python.psi.PyTargetExpression;
|
||||
import com.jetbrains.python.psi.PyUtil;
|
||||
import com.jetbrains.python.psi.types.PyClassMembersProviderBase;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -39,7 +40,7 @@ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PyCustomMember> getMembers(PyClassType classType, PsiElement location) {
|
||||
public Collection<PyCustomMember> getMembers(PyClassType classType, PsiElement location, TypeEvalContext typeEvalContext) {
|
||||
PyClass clazz = classType.getPyClass();
|
||||
final String qualifiedName = clazz.getQualifiedName();
|
||||
if ("socket._socketobject".equals(qualifiedName)) {
|
||||
|
||||
+2
-2
@@ -39,7 +39,7 @@ import java.util.List;
|
||||
public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderBase implements PyOverridingAncestorsClassMembersProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PyCustomMember> getMembers(@NotNull PyClassType classType, PsiElement location) {
|
||||
public Collection<PyCustomMember> getMembers(@NotNull PyClassType classType, PsiElement location, TypeEvalContext typeEvalContext) {
|
||||
final PyClass cls = classType.getPyClass();
|
||||
final PyClass skeleton = PyUserSkeletonsUtil.getUserSkeleton(cls);
|
||||
if (skeleton != null) {
|
||||
@@ -52,7 +52,7 @@ public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderB
|
||||
@Override
|
||||
public PsiElement resolveMember(@NotNull PyClassType classType, @NotNull String name, PsiElement location, TypeEvalContext context) {
|
||||
final PyClass cls = classType.getPyClass();
|
||||
final PyClass skeleton = PyUserSkeletonsUtil.getUserSkeleton(cls);
|
||||
final PyClass skeleton = PyUserSkeletonsUtil.getUserSkeletonWithContext(cls, context);
|
||||
if (skeleton != null) {
|
||||
return findClassMember(skeleton, name, classType.isDefinition());
|
||||
}
|
||||
|
||||
+4
-4
@@ -35,7 +35,7 @@ public class PyUserSkeletonsTypeProvider extends PyTypeProviderBase {
|
||||
public Ref<PyType> getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) {
|
||||
final String name = param.getName();
|
||||
if (name != null) {
|
||||
final PyFunction functionSkeleton = PyUserSkeletonsUtil.getUserSkeleton(func);
|
||||
final PyFunction functionSkeleton = PyUserSkeletonsUtil.getUserSkeletonWithContext(func, context);
|
||||
if (functionSkeleton != null) {
|
||||
final PyNamedParameter paramSkeleton = functionSkeleton.getParameterList().findParameterByName(name);
|
||||
if (paramSkeleton != null) {
|
||||
@@ -52,7 +52,7 @@ public class PyUserSkeletonsTypeProvider extends PyTypeProviderBase {
|
||||
@Nullable
|
||||
@Override
|
||||
public Ref<PyType> getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) {
|
||||
final PyCallable callableSkeleton = PyUserSkeletonsUtil.getUserSkeleton(callable);
|
||||
final PyCallable callableSkeleton = PyUserSkeletonsUtil.getUserSkeletonWithContext(callable, context);
|
||||
if (callableSkeleton != null) {
|
||||
final PyType type = context.getReturnType(callableSkeleton);
|
||||
if (type != null) {
|
||||
@@ -65,7 +65,7 @@ public class PyUserSkeletonsTypeProvider extends PyTypeProviderBase {
|
||||
@Override
|
||||
public PyType getReferenceType(@NotNull PsiElement target, TypeEvalContext context, @Nullable PsiElement anchor) {
|
||||
if (target instanceof PyTargetExpression) {
|
||||
final PyTargetExpression targetSkeleton = PyUserSkeletonsUtil.getUserSkeleton((PyTargetExpression)target);
|
||||
final PyTargetExpression targetSkeleton = PyUserSkeletonsUtil.getUserSkeletonWithContext((PyTargetExpression)target, context);
|
||||
if (targetSkeleton != null) {
|
||||
return context.getType(targetSkeleton);
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public class PyUserSkeletonsTypeProvider extends PyTypeProviderBase {
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getCallableType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) {
|
||||
final PyCallable callableSkeleton = PyUserSkeletonsUtil.getUserSkeleton(callable);
|
||||
final PyCallable callableSkeleton = PyUserSkeletonsUtil.getUserSkeletonWithContext(callable, context);
|
||||
if (callableSkeleton != null) {
|
||||
return context.getType(callableSkeleton);
|
||||
}
|
||||
|
||||
@@ -99,11 +99,15 @@ public class PyUserSkeletonsUtil {
|
||||
|
||||
@Nullable
|
||||
public static <T extends PyElement> T getUserSkeleton(@NotNull T element) {
|
||||
return getUserSkeletonWithContext(element, null);
|
||||
}
|
||||
@Nullable
|
||||
public static <T extends PyElement> T getUserSkeletonWithContext(@NotNull T element, @Nullable final TypeEvalContext context) {
|
||||
final PsiFile file = element.getContainingFile();
|
||||
if (file instanceof PyFile) {
|
||||
final PyFile skeletonFile = getUserSkeletonForFile((PyFile)file);
|
||||
if (skeletonFile != null && skeletonFile != file) {
|
||||
final PsiElement skeletonElement = getUserSkeleton(element, skeletonFile);
|
||||
final PsiElement skeletonElement = getUserSkeleton(element, skeletonFile, context);
|
||||
if (element.getClass().isInstance(skeletonElement) && skeletonElement != element) {
|
||||
//noinspection unchecked
|
||||
return (T)skeletonElement;
|
||||
@@ -152,7 +156,7 @@ public class PyUserSkeletonsUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getUserSkeleton(@NotNull PyElement element, @NotNull PyFile skeletonFile) {
|
||||
private static PsiElement getUserSkeleton(@NotNull PyElement element, @NotNull PyFile skeletonFile, @Nullable TypeEvalContext context) {
|
||||
if (element instanceof PyFile) {
|
||||
return skeletonFile;
|
||||
}
|
||||
@@ -160,15 +164,19 @@ public class PyUserSkeletonsUtil {
|
||||
final String name = element.getName();
|
||||
if (owner != null && name != null) {
|
||||
assert owner != element;
|
||||
final PsiElement originalOwner = getUserSkeleton(owner, skeletonFile);
|
||||
final PsiElement originalOwner = getUserSkeleton(owner, skeletonFile, context);
|
||||
if (originalOwner instanceof PyClass) {
|
||||
final PyClass classOwner = (PyClass)originalOwner;
|
||||
final PyType type = TypeEvalContext.codeInsightFallback(classOwner.getProject()).getType(classOwner);
|
||||
if (type instanceof PyClassLikeType) {
|
||||
final PyClassLikeType classType = (PyClassLikeType)type;
|
||||
final PyClassLikeType instanceType = classType.toInstance();
|
||||
PyResolveContext resolveContext = PyResolveContext.noImplicits();
|
||||
if (context != null) {
|
||||
resolveContext = resolveContext.withTypeEvalContext(context);
|
||||
}
|
||||
final List<? extends RatedResolveResult> resolveResults = instanceType.resolveMember(name, null, AccessDirection.READ,
|
||||
PyResolveContext.noImplicits(), false);
|
||||
resolveContext, false);
|
||||
if (resolveResults != null && !resolveResults.isEmpty()) {
|
||||
return resolveResults.get(0).getElement();
|
||||
}
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public class PySuperTypesHierarchyTreeStructure extends HierarchyTreeStructure {
|
||||
final PsiElement element = pyDescriptor.getPsiElement();
|
||||
if (element instanceof PyClass) {
|
||||
final PyClass cls = (PyClass)element;
|
||||
final PyClass[] superClasses = cls.getSuperClasses();
|
||||
final PyClass[] superClasses = cls.getSuperClasses(null);
|
||||
for (PyClass superClass : superClasses) {
|
||||
res.add(new PyHierarchyNodeDescriptor(descriptor, superClass, false));
|
||||
}
|
||||
|
||||
@@ -112,6 +112,6 @@ public class PyAttributeOutsideInitInspection extends PyInspection {
|
||||
}
|
||||
|
||||
private static boolean isApplicable(@NotNull final PyClass containingClass) {
|
||||
return !PythonUnitTestUtil.isUnitTestCaseClass(containingClass) && !containingClass.isSubclass("django.db.models.base.Model");
|
||||
return !PythonUnitTestUtil.isUnitTestCaseClass(containingClass) && !containingClass.isSubclass("django.db.models.base.Model", null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ public class PyCallByClassInspection extends PyInspection {
|
||||
if (method != null) {
|
||||
PyClass calling_class = method.getContainingClass();
|
||||
assert calling_class != null; // it's a method
|
||||
if (first_arg_class.isSubclass(qual_class) && calling_class.isSubclass(qual_class)) {
|
||||
if (first_arg_class.isSubclass(qual_class, null) && calling_class.isSubclass(qual_class, null)) {
|
||||
break;
|
||||
// TODO: might propose to switch to super() here
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class PyExceptClausesOrderInspection extends PyInspection {
|
||||
if (exceptClasses.contains(pyClass)) {
|
||||
registerProblem(exceptClass, PyBundle.message("INSP.class.$0.already.caught", pyClass.getName()));
|
||||
} else {
|
||||
for (PyClass superClass: pyClass.getSuperClasses()) {
|
||||
for (PyClass superClass: pyClass.getSuperClasses(null)) {
|
||||
if (exceptClasses.contains(superClass)) {
|
||||
registerProblem(exceptClass, PyBundle.message("INSP.class.$0.superclass.$1.already.caught", superClass.getName(), pyClass.getName()),
|
||||
new PyMoveExceptQuickFix());
|
||||
|
||||
@@ -92,7 +92,7 @@ public class PyMethodParametersInspection extends PyInspection {
|
||||
PsiElement zope_interface = findZopeInterface(node);
|
||||
final PyClass cls = node.getContainingClass();
|
||||
if (zope_interface instanceof PyClass) {
|
||||
if (cls != null && cls.isSubclass((PyClass) zope_interface)) return; // it can have any params
|
||||
if (cls != null && cls.isSubclass((PyClass) zope_interface, null)) return; // it can have any params
|
||||
}
|
||||
// analyze function itself
|
||||
PyUtil.MethodFlags flags = PyUtil.MethodFlags.of(node);
|
||||
|
||||
@@ -290,7 +290,7 @@ public class PyPropertyDefinitionInspection extends PyInspection {
|
||||
private void checkForSelf(PyParameterList paramList) {
|
||||
PyParameter[] parameters = paramList.getParameters();
|
||||
final PyClass cls = PsiTreeUtil.getParentOfType(paramList, PyClass.class);
|
||||
if (cls != null && cls.isSubclass("type")) return;
|
||||
if (cls != null && cls.isSubclass("type", null)) return;
|
||||
if (parameters.length > 0 && !PyNames.CANONICAL_SELF.equals(parameters[0].getName())) {
|
||||
registerProblem(
|
||||
parameters[0], PyBundle.message("INSP.accessor.first.param.is.$0", PyNames.CANONICAL_SELF), ProblemHighlightType.WEAK_WARNING,
|
||||
|
||||
@@ -128,12 +128,12 @@ public class PyProtectedMemberInspection extends PyInspection {
|
||||
if (parentClass != null) {
|
||||
if (PyTestUtil.isPyTestClass(parentClass) && ignoreTestFunctions) return;
|
||||
|
||||
if (parentClass.isSubclass(resolvedClass))
|
||||
if (parentClass.isSubclass(resolvedClass, null))
|
||||
return;
|
||||
|
||||
PyClass outerClass = getClassOwner(parentClass);
|
||||
while (outerClass != null) {
|
||||
if (outerClass.isSubclass(resolvedClass))
|
||||
if (outerClass.isSubclass(resolvedClass, null))
|
||||
return;
|
||||
|
||||
outerClass = getClassOwner(outerClass);
|
||||
|
||||
@@ -65,7 +65,7 @@ public class PySuperArgumentsInspection extends PyInspection {
|
||||
PyClass firstClass = findClassOf(arguments[0]);
|
||||
PyClass secondClass = findClassOf(arguments[1]);
|
||||
if (firstClass != null && secondClass != null) {
|
||||
if (!secondClass.isSubclass(firstClass)) {
|
||||
if (!secondClass.isSubclass(firstClass, null)) {
|
||||
registerProblem(
|
||||
node.getArgumentList(),
|
||||
PyBundle.message("INSP.$0.is.not.superclass.of.$1",
|
||||
|
||||
@@ -62,7 +62,7 @@ public class AddCallSuperQuickFix implements LocalQuickFix {
|
||||
final StringBuilder superCall = new StringBuilder();
|
||||
final PyClass klass = problemFunction.getContainingClass();
|
||||
if (klass == null) return;
|
||||
final PyClass[] superClasses = klass.getSuperClasses();
|
||||
final PyClass[] superClasses = klass.getSuperClasses(null);
|
||||
if (superClasses.length == 0) return;
|
||||
|
||||
final PyClass superClass = superClasses[0];
|
||||
|
||||
@@ -97,7 +97,7 @@ public class AddMethodQuickFix implements LocalQuickFix {
|
||||
if (callByClass) {
|
||||
if (args.length > 0) {
|
||||
PyType firstArgType = TypeEvalContext.userInitiated(cls.getProject(), cls.getContainingFile()).getType(args[0]);
|
||||
if (firstArgType instanceof PyClassType && ((PyClassType)firstArgType).getPyClass().isSubclass(cls)) {
|
||||
if (firstArgType instanceof PyClassType && ((PyClassType)firstArgType).getPyClass().isSubclass(cls, null)) {
|
||||
// class, first arg ok: instance method
|
||||
builder.parameter("self"); // NOTE: might use a name other than 'self', according to code style.
|
||||
madeInstance = true;
|
||||
|
||||
@@ -55,7 +55,7 @@ public class PyMoveExceptQuickFix implements LocalQuickFix {
|
||||
if (statement == null) return;
|
||||
|
||||
PyExceptPart prevExceptPart = PsiTreeUtil.getPrevSiblingOfType(part, PyExceptPart.class);
|
||||
final ArrayList<PyClass> superClasses = Lists.newArrayList(((PyClass)exceptClass).getSuperClasses());
|
||||
final ArrayList<PyClass> superClasses = Lists.newArrayList(((PyClass)exceptClass).getSuperClasses(null));
|
||||
while (prevExceptPart != null) {
|
||||
final PyExpression classExpression = prevExceptPart.getExceptClass();
|
||||
if (classExpression == null) return;
|
||||
|
||||
+3
-3
@@ -779,7 +779,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
if (isDecoratedAsDynamic(cls, true)) {
|
||||
return true;
|
||||
}
|
||||
if (hasUnresolvedDynamicMember((PyClassType)type, reference, name)) return true;
|
||||
if (hasUnresolvedDynamicMember((PyClassType)type, reference, name, myTypeEvalContext)) return true;
|
||||
}
|
||||
if (type instanceof PyFunctionTypeImpl) {
|
||||
final PyCallable callable = ((PyFunctionTypeImpl)type).getCallable();
|
||||
@@ -797,9 +797,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
|
||||
private static boolean hasUnresolvedDynamicMember(@NotNull final PyClassType type,
|
||||
PsiReference reference,
|
||||
@NotNull final String name) {
|
||||
@NotNull final String name, TypeEvalContext typeEvalContext) {
|
||||
for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
|
||||
final Collection<PyCustomMember> resolveResult = provider.getMembers(type, reference.getElement());
|
||||
final Collection<PyCustomMember> resolveResult = provider.getMembers(type, reference.getElement(), typeEvalContext);
|
||||
for (PyCustomMember member : resolveResult) {
|
||||
if (member.getName().equals(name)) return true;
|
||||
}
|
||||
|
||||
@@ -366,7 +366,7 @@ public class PyCallExpressionHelper {
|
||||
PyClass resolvedParent = PsiTreeUtil.getStubOrPsiParentOfType(resolved, PyClass.class);
|
||||
if (resolvedParent != null) {
|
||||
final PyClass qualifierClass = ((PyClassType)qualifierType).getPyClass();
|
||||
if ((qualifierClass.isSubclass(resolvedParent) || resolvedParent.isSubclass(qualifierClass))) {
|
||||
if ((qualifierClass.isSubclass(resolvedParent, null) || resolvedParent.isSubclass(qualifierClass, null))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -599,7 +599,7 @@ public class PyCallExpressionHelper {
|
||||
}
|
||||
}
|
||||
PsiElement possible_class = firstArgRef.getReference().resolve();
|
||||
if (possible_class instanceof PyClass && ((PyClass)possible_class).isNewStyleClass(null)) {
|
||||
if (possible_class instanceof PyClass && ((PyClass)possible_class).isNewStyleClass(context)) {
|
||||
final PyClass first_class = (PyClass)possible_class;
|
||||
return new Maybe<PyType>(getSuperCallTypeForArguments(context, first_class, args[1]));
|
||||
}
|
||||
@@ -608,7 +608,7 @@ public class PyCallExpressionHelper {
|
||||
else if ((call.getContainingFile() instanceof PyFile) &&
|
||||
((PyFile)call.getContainingFile()).getLanguageLevel().isPy3K() &&
|
||||
(containingClass != null)) {
|
||||
return new Maybe<PyType>(getSuperClassUnionType(containingClass));
|
||||
return new Maybe<PyType>(getSuperClassUnionType(containingClass, context));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,9 +626,9 @@ public class PyCallExpressionHelper {
|
||||
// imitate isinstance(second_arg, possible_class)
|
||||
PyClass secondClass = ((PyClassType)second_type).getPyClass();
|
||||
if (CompletionUtil.getOriginalOrSelf(firstClass) == secondClass) {
|
||||
return getSuperClassUnionType(firstClass);
|
||||
return getSuperClassUnionType(firstClass,context);
|
||||
}
|
||||
if (secondClass.isSubclass(firstClass)) {
|
||||
if (secondClass.isSubclass(firstClass, context)) {
|
||||
final Iterator<PyClass> iterator = firstClass.getAncestorClasses(context).iterator();
|
||||
if (iterator.hasNext()) {
|
||||
return new PyClassTypeImpl(iterator.next(), false); // super(Foo, self) has type of Foo, modulo __get__()
|
||||
@@ -640,11 +640,11 @@ public class PyCallExpressionHelper {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyType getSuperClassUnionType(@NotNull PyClass pyClass) {
|
||||
private static PyType getSuperClassUnionType(@NotNull PyClass pyClass, TypeEvalContext context) {
|
||||
// TODO: this is closer to being correct than simply taking first superclass type but still not entirely correct;
|
||||
// super can also delegate to sibling types
|
||||
// TODO handle __mro__ here
|
||||
final PyClass[] supers = pyClass.getSuperClasses();
|
||||
final PyClass[] supers = pyClass.getSuperClasses(context);
|
||||
if (supers.length > 0) {
|
||||
if (supers.length == 1) {
|
||||
return new PyClassTypeImpl(supers[0], false);
|
||||
|
||||
@@ -267,22 +267,29 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
return results;
|
||||
}
|
||||
|
||||
public boolean isSubclass(PyClass parent) {
|
||||
public boolean isSubclass(PyClass parent, @Nullable TypeEvalContext context) {
|
||||
if (this == parent) {
|
||||
return true;
|
||||
}
|
||||
for (PyClass superclass : getAncestorClasses(null)) {
|
||||
for (PyClass superclass : getAncestorClasses(context)) {
|
||||
if (parent == superclass) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSubclass(PyClass parent) {
|
||||
return isSubclass(parent, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSubclass(@NotNull String superClassQName) {
|
||||
public boolean isSubclass(@NotNull String superClassQName, @Nullable TypeEvalContext context) {
|
||||
if (context == null) {
|
||||
context = TypeEvalContext.codeInsightFallback(getProject());
|
||||
}
|
||||
if (superClassQName.equals(getQualifiedName())) {
|
||||
return true;
|
||||
}
|
||||
for (PyClassLikeType type : getAncestorTypes(TypeEvalContext.codeInsightFallback(getProject()))) {
|
||||
for (PyClassLikeType type : getAncestorTypes(context)) {
|
||||
if (type != null && superClassQName.equals(type.getClassQName())) {
|
||||
return true;
|
||||
}
|
||||
@@ -327,10 +334,12 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
}
|
||||
return PyFileImpl.getStringListFromTargetExpression(PyNames.SLOTS, getClassAttributes());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyClass[] getSuperClasses() {
|
||||
final List<PyClassLikeType> superTypes = getSuperClassTypes(TypeEvalContext.codeInsightFallback(getProject()));
|
||||
public PyClass[] getSuperClasses(@Nullable TypeEvalContext context) {
|
||||
if (context == null) {
|
||||
context = TypeEvalContext.codeInsightFallback(getProject());
|
||||
}
|
||||
final List<PyClassLikeType> superTypes = getSuperClassTypes(context);
|
||||
if (superTypes.isEmpty()) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
@@ -540,7 +549,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
@Nullable
|
||||
public PyFunction findInitOrNew(boolean inherited, final @Nullable TypeEvalContext context) {
|
||||
NameFinder<PyFunction> proc;
|
||||
if (isNewStyleClass(null)) {
|
||||
if (isNewStyleClass(context)) {
|
||||
proc = new NameFinder<PyFunction>(PyNames.INIT, PyNames.NEW);
|
||||
}
|
||||
else {
|
||||
@@ -1508,13 +1517,15 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
|
||||
private static final class MyAttributesCollector implements Processor<PyTargetExpression> {
|
||||
private final List<PyTargetExpression> myAttributes = new ArrayList<PyTargetExpression>();
|
||||
|
||||
@Override
|
||||
public boolean process(final PyTargetExpression expression) {
|
||||
myAttributes.add(expression);
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
List<PyTargetExpression> getAttributes() {
|
||||
List<PyTargetExpression> getAttributes() {
|
||||
return Collections.unmodifiableList(myAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,7 +505,7 @@ public class PyQualifiedReference extends PyReferenceImpl {
|
||||
if (aClass == null || bClass == null) {
|
||||
return false;
|
||||
}
|
||||
return bClass.isSubclass(aClass);
|
||||
return bClass.isSubclass(aClass, null);
|
||||
}
|
||||
|
||||
private static boolean isLocalScope(PsiElement element) {
|
||||
|
||||
@@ -471,7 +471,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
|
||||
if (PyUtil.isClassAttribute(myElement) && (PyUtil.isClassAttribute(expr) || PyUtil.isInstanceAttribute(expr))) {
|
||||
final PyClass c1 = PsiTreeUtil.getParentOfType(element, PyClass.class);
|
||||
final PyClass c2 = PsiTreeUtil.getParentOfType(myElement, PyClass.class);
|
||||
if (c1 != null && c2 != null && (c1.isSubclass(c2) || c2.isSubclass(c1))) {
|
||||
if (c1 != null && c2 != null && (c1.isSubclass(c2, null) || c2.isSubclass(c1, null))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class PyClassInheritorsSearchExecutor implements QueryExecutor<PyClass, P
|
||||
final Collection<PyClass> candidates = StubIndex.getElements(PySuperClassIndex.KEY, superClassName, project,
|
||||
ProjectScope.getAllScope(project), PyClass.class);
|
||||
for (PyClass candidate : candidates) {
|
||||
final PyClass[] classes = candidate.getSuperClasses();
|
||||
final PyClass[] classes = candidate.getSuperClasses(null);
|
||||
for (PyClass superClassCandidate : classes) {
|
||||
if (superClassCandidate.isEquivalentTo(superClass)) {
|
||||
if (!consumer.process(candidate)) {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class PySuperMethodsSearchExecutor implements QueryExecutor<PsiElement, P
|
||||
if (!queryParameters.isDeepSearch()) {
|
||||
boolean isAlreadyFound = false;
|
||||
for (PyClass alreadyFound : foundMethodContainingClasses) {
|
||||
if (alreadyFound.isSubclass(superClass)) {
|
||||
if (alreadyFound.isSubclass(superClass, null)) {
|
||||
isAlreadyFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
|
||||
// from providers
|
||||
for (final PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
|
||||
for (final PyCustomMember member : provider.getMembers(this, location)) {
|
||||
for (final PyCustomMember member : provider.getMembers(this, location, typeEvalContext)) {
|
||||
final String name = member.getName();
|
||||
if (!namesAlready.contains(name)) {
|
||||
ret.add(PyCustomMemberUtils.toLookUpElement(member, getName()));
|
||||
@@ -452,7 +452,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
}
|
||||
}
|
||||
|
||||
if (!myClass.isNewStyleClass(null)) {
|
||||
if (!myClass.isNewStyleClass(typeEvalContext)) {
|
||||
final PyBuiltinCache cache = PyBuiltinCache.getInstance(myClass);
|
||||
final PyClassType classobjType = cache.getOldstyleClassobjType();
|
||||
if (classobjType != null) {
|
||||
@@ -460,7 +460,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefinition() && myClass.isNewStyleClass(null)) {
|
||||
if (isDefinition() && myClass.isNewStyleClass(typeEvalContext)) {
|
||||
final PyClassLikeType typeType = getMetaClassType(typeEvalContext, true);
|
||||
if (typeType != null) {
|
||||
Collections.addAll(ret, typeType.getCompletionVariants(prefix, location, context));
|
||||
@@ -510,7 +510,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
// We are here because of completion (see call stack), so we use code complete here
|
||||
final TypeEvalContext context =
|
||||
(expressionHook != null ? TypeEvalContext.codeCompletion(myClass.getProject(), myClass.getContainingFile()) : null);
|
||||
List<String> slots = myClass.isNewStyleClass(null) ? myClass.getSlots(
|
||||
List<String> slots = myClass.isNewStyleClass(context) ? myClass.getSlots(
|
||||
context) : null;
|
||||
if (slots != null) {
|
||||
processor.setAllowedNames(slots);
|
||||
|
||||
@@ -216,7 +216,7 @@ public class PyTypeChecker {
|
||||
public static Set<String> getClassTypeAttributes(@NotNull PyClassType type, boolean inherited, @NotNull TypeEvalContext context) {
|
||||
final Set<String> attributes = getClassAttributes(type.getPyClass(), inherited, type.isDefinition(), context);
|
||||
for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
|
||||
final Collection<PyCustomMember> members = provider.getMembers(type, null);
|
||||
final Collection<PyCustomMember> members = provider.getMembers(type, null, context);
|
||||
for (PyCustomMember member : members) {
|
||||
attributes.add(member.getName());
|
||||
}
|
||||
@@ -455,7 +455,7 @@ public class PyTypeChecker {
|
||||
}
|
||||
|
||||
private static boolean matchClasses(@Nullable PyClass superClass, @Nullable PyClass subClass, @NotNull TypeEvalContext context) {
|
||||
if (superClass == null || subClass == null || subClass.isSubclass(superClass) || PyABCUtil.isSubclass(subClass, superClass)) {
|
||||
if (superClass == null || subClass == null || subClass.isSubclass(superClass, null) || PyABCUtil.isSubclass(subClass, superClass)) {
|
||||
return true;
|
||||
}
|
||||
else if (PyUtil.hasUnresolvedAncestors(subClass, context)) {
|
||||
|
||||
@@ -35,7 +35,7 @@ import java.util.Collections;
|
||||
public class PyiClassMembersProvider extends PyClassMembersProviderBase implements PyOverridingAncestorsClassMembersProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PyCustomMember> getMembers(@NotNull PyClassType classType, PsiElement location) {
|
||||
public Collection<PyCustomMember> getMembers(@NotNull PyClassType classType, PsiElement location, TypeEvalContext typeEvalContext) {
|
||||
final PyClass cls = classType.getPyClass();
|
||||
final PsiElement pythonStub = PyiUtil.getPythonStub(cls);
|
||||
if (pythonStub instanceof PyClass) {
|
||||
|
||||
@@ -52,7 +52,7 @@ public class PyMemberInfoStorage extends AbstractMemberInfoStorage<PyElement, Py
|
||||
|
||||
private void buildSubClassesMapImpl(PyClass aClass, HashSet<PyClass> visited) {
|
||||
visited.add(aClass);
|
||||
for (PyClass clazz : aClass.getSuperClasses()) {
|
||||
for (PyClass clazz : aClass.getSuperClasses(null)) {
|
||||
getSubclasses(clazz).add(aClass);
|
||||
if (!visited.contains(clazz)) {
|
||||
buildSubClassesMapImpl(clazz, visited);
|
||||
|
||||
+1
-1
@@ -302,7 +302,7 @@ public abstract class MembersManager<T extends PyElement> implements Function<T,
|
||||
while (classesIterator.hasNext()) {
|
||||
final PyClass memberClass = classesIterator.next();
|
||||
if (memberClass.equals(destinationClass) ||
|
||||
ArrayUtil.contains(memberClass, destinationClass.getSuperClasses())) { // IF still would be available
|
||||
ArrayUtil.contains(memberClass, destinationClass.getSuperClasses(null))) { // IF still would be available
|
||||
classesIterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -222,7 +222,7 @@ class MethodsManager extends MembersManager<PyFunction> {
|
||||
private static Boolean isOverrides(final PyFunction pyFunction) {
|
||||
final PyClass clazz = PyUtil.getContainingClassOrSelf(pyFunction);
|
||||
assert clazz != null : "Refactoring called on function, not method: " + pyFunction;
|
||||
for (final PyClass parentClass : clazz.getSuperClasses()) {
|
||||
for (final PyClass parentClass : clazz.getSuperClasses(null)) {
|
||||
final PyFunction parentMethod = parentClass.findMethodByName(pyFunction.getName(), true);
|
||||
if (parentMethod != null) {
|
||||
return true;
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ class SuperClassesManager extends MembersManager<PyClass> {
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<PyElement> getMembersCouldBeMoved(@NotNull final PyClass pyClass) {
|
||||
return Lists.<PyElement>newArrayList(Collections2.filter(Arrays.asList(pyClass.getSuperClasses()), NO_FAKE_SUPER_CLASSES));
|
||||
return Lists.<PyElement>newArrayList(Collections2.filter(Arrays.asList(pyClass.getSuperClasses(null)), NO_FAKE_SUPER_CLASSES));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -58,7 +58,7 @@ class PyPullUpInfoModel extends AbstractUsesDependencyMemberInfoModel<PyElement,
|
||||
if (member.getMember() instanceof PyClass) {
|
||||
//TODO: Delegate to Memebers Managers
|
||||
final PyClass memberClass = (PyClass)member.getMember();
|
||||
if (memberClass.isSubclass(currentSuperClass) || currentSuperClass.isSubclass(memberClass)) {
|
||||
if (memberClass.isSubclass(currentSuperClass, null) || currentSuperClass.isSubclass(memberClass, null)) {
|
||||
return false; //Class is already parent of superclass
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user