From 4d220fd8dfd166c6381410543074a83a8a6f5eff Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Mon, 2 Nov 2015 22:06:56 +0300 Subject: [PATCH] test fix: passing type eval context --- .../src/com/jetbrains/python/psi/PyClass.java | 7 +++-- .../psi/types/PyClassMembersProvider.java | 2 +- .../psi/types/PyClassMembersProviderBase.java | 4 +-- .../codeInsight/PyDunderSlotsReference.java | 2 +- .../imports/ImportCandidateHolder.java | 2 +- .../stdlib/PyStdlibClassMembersProvider.java | 3 +- .../PyUserSkeletonsClassMembersProvider.java | 4 +-- .../PyUserSkeletonsTypeProvider.java | 8 ++--- .../userSkeletons/PyUserSkeletonsUtil.java | 16 +++++++--- .../PySuperTypesHierarchyTreeStructure.java | 2 +- .../PyAttributeOutsideInitInspection.java | 2 +- .../inspections/PyCallByClassInspection.java | 2 +- .../PyExceptClausesOrderInspection.java | 2 +- .../PyMethodParametersInspection.java | 2 +- .../PyPropertyDefinitionInspection.java | 2 +- .../PyProtectedMemberInspection.java | 4 +-- .../PySuperArgumentsInspection.java | 2 +- .../quickfix/AddCallSuperQuickFix.java | 2 +- .../quickfix/AddMethodQuickFix.java | 2 +- .../quickfix/PyMoveExceptQuickFix.java | 2 +- .../PyUnresolvedReferencesInspection.java | 6 ++-- .../psi/impl/PyCallExpressionHelper.java | 14 ++++----- .../python/psi/impl/PyClassImpl.java | 29 +++++++++++++------ .../impl/references/PyQualifiedReference.java | 2 +- .../psi/impl/references/PyReferenceImpl.java | 2 +- .../PyClassInheritorsSearchExecutor.java | 2 +- .../search/PySuperMethodsSearchExecutor.java | 2 +- .../python/psi/types/PyClassTypeImpl.java | 8 ++--- .../python/psi/types/PyTypeChecker.java | 4 +-- .../python/pyi/PyiClassMembersProvider.java | 2 +- .../classes/PyMemberInfoStorage.java | 2 +- .../membersManager/MembersManager.java | 2 +- .../membersManager/MethodsManager.java | 2 +- .../membersManager/SuperClassesManager.java | 2 +- .../classes/pullUp/PyPullUpInfoModel.java | 2 +- 35 files changed, 87 insertions(+), 66 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java index 98c7be60a0d2..0bf5ca3c00ca 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java @@ -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. diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java index 4b034950d422..a491b051702c 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java @@ -30,7 +30,7 @@ public interface PyClassMembersProvider { ExtensionPointName EP_NAME = ExtensionPointName.create("Pythonid.pyClassMembersProvider"); @NotNull - Collection getMembers(final PyClassType clazz, PsiElement location); + Collection getMembers(final PyClassType clazz, PsiElement location, @Nullable TypeEvalContext typeEvalContext); @Nullable PsiElement resolveMember(PyClassType clazz, String name, @Nullable PsiElement location, @Nullable TypeEvalContext context); diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java index a707daf95ae5..7a606ae6ca7f 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java @@ -30,13 +30,13 @@ import java.util.Collections; public class PyClassMembersProviderBase implements PyClassMembersProvider { @NotNull @Override - public Collection getMembers(PyClassType clazz, PsiElement location) { + public Collection getMembers(PyClassType clazz, PsiElement location, TypeEvalContext typeEvalContext) { return Collections.emptyList(); } @Override public PsiElement resolveMember(PyClassType clazz, String name, PsiElement location, TypeEvalContext context) { - final Collection members = getMembers(clazz, location); + final Collection members = getMembers(clazz, location, context); return resolveMemberByName(members, clazz, name); } diff --git a/python/src/com/jetbrains/python/codeInsight/PyDunderSlotsReference.java b/python/src/com/jetbrains/python/codeInsight/PyDunderSlotsReference.java index 1a976cbcabeb..1a2fcf61db73 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyDunderSlotsReference.java +++ b/python/src/com/jetbrains/python/codeInsight/PyDunderSlotsReference.java @@ -44,7 +44,7 @@ public class PyDunderSlotsReference extends PsiReferenceBase { sb.append(((PyFunction)myImportable).getParameterList().getPresentableText(false)); } else if (myImportable instanceof PyClass) { - final List supers = ContainerUtil.mapNotNull(((PyClass)myImportable).getSuperClasses(), new Function() { + final List supers = ContainerUtil.mapNotNull(((PyClass)myImportable).getSuperClasses(null), new Function() { @Override public String fun(PyClass cls) { return PyUtil.isObjectClass(cls) ? null : cls.getName(); diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java index 9cdd1a40c5db..835d8ea8a0f5 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java @@ -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 getMembers(PyClassType classType, PsiElement location) { + public Collection getMembers(PyClassType classType, PsiElement location, TypeEvalContext typeEvalContext) { PyClass clazz = classType.getPyClass(); final String qualifiedName = clazz.getQualifiedName(); if ("socket._socketobject".equals(qualifiedName)) { diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java index 387aa2f81307..c0bcc8e3c7d3 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java @@ -39,7 +39,7 @@ import java.util.List; public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderBase implements PyOverridingAncestorsClassMembersProvider { @NotNull @Override - public Collection getMembers(@NotNull PyClassType classType, PsiElement location) { + public Collection 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()); } diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java index c4409f500781..6551be926f96 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java @@ -35,7 +35,7 @@ public class PyUserSkeletonsTypeProvider extends PyTypeProviderBase { public Ref 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 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); } diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java index 26828421705a..619130fa8eeb 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java @@ -99,11 +99,15 @@ public class PyUserSkeletonsUtil { @Nullable public static T getUserSkeleton(@NotNull T element) { + return getUserSkeletonWithContext(element, null); + } + @Nullable + public static 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 resolveResults = instanceType.resolveMember(name, null, AccessDirection.READ, - PyResolveContext.noImplicits(), false); + resolveContext, false); if (resolveResults != null && !resolveResults.isEmpty()) { return resolveResults.get(0).getElement(); } diff --git a/python/src/com/jetbrains/python/hierarchy/treestructures/PySuperTypesHierarchyTreeStructure.java b/python/src/com/jetbrains/python/hierarchy/treestructures/PySuperTypesHierarchyTreeStructure.java index f0235027fa9b..c07a2c07496e 100644 --- a/python/src/com/jetbrains/python/hierarchy/treestructures/PySuperTypesHierarchyTreeStructure.java +++ b/python/src/com/jetbrains/python/hierarchy/treestructures/PySuperTypesHierarchyTreeStructure.java @@ -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)); } diff --git a/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java b/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java index a39a11da4f20..00e3bc70a405 100644 --- a/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java @@ -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); } } diff --git a/python/src/com/jetbrains/python/inspections/PyCallByClassInspection.java b/python/src/com/jetbrains/python/inspections/PyCallByClassInspection.java index bbce4a658b25..990f65264aca 100644 --- a/python/src/com/jetbrains/python/inspections/PyCallByClassInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyCallByClassInspection.java @@ -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 } diff --git a/python/src/com/jetbrains/python/inspections/PyExceptClausesOrderInspection.java b/python/src/com/jetbrains/python/inspections/PyExceptClausesOrderInspection.java index d331b8d6aa5c..b67848905284 100644 --- a/python/src/com/jetbrains/python/inspections/PyExceptClausesOrderInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyExceptClausesOrderInspection.java @@ -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()); diff --git a/python/src/com/jetbrains/python/inspections/PyMethodParametersInspection.java b/python/src/com/jetbrains/python/inspections/PyMethodParametersInspection.java index 08b7be9f233c..6894c0f5551f 100644 --- a/python/src/com/jetbrains/python/inspections/PyMethodParametersInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyMethodParametersInspection.java @@ -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); diff --git a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java index 80cade67f175..2cd44f53b96b 100644 --- a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java @@ -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, diff --git a/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java b/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java index 869105c1c8c1..22a1d1d56fc9 100644 --- a/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java @@ -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); diff --git a/python/src/com/jetbrains/python/inspections/PySuperArgumentsInspection.java b/python/src/com/jetbrains/python/inspections/PySuperArgumentsInspection.java index 689c5f0fd457..028bc580e6c8 100644 --- a/python/src/com/jetbrains/python/inspections/PySuperArgumentsInspection.java +++ b/python/src/com/jetbrains/python/inspections/PySuperArgumentsInspection.java @@ -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", diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java index 9e88cb75cd24..9fdb22b1a2d3 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java @@ -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]; diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddMethodQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddMethodQuickFix.java index a560d2002d06..ba41ba658f75 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddMethodQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddMethodQuickFix.java @@ -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; diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyMoveExceptQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyMoveExceptQuickFix.java index fc6c52b89689..e2ccf89327de 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/PyMoveExceptQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyMoveExceptQuickFix.java @@ -55,7 +55,7 @@ public class PyMoveExceptQuickFix implements LocalQuickFix { if (statement == null) return; PyExceptPart prevExceptPart = PsiTreeUtil.getPrevSiblingOfType(part, PyExceptPart.class); - final ArrayList superClasses = Lists.newArrayList(((PyClass)exceptClass).getSuperClasses()); + final ArrayList superClasses = Lists.newArrayList(((PyClass)exceptClass).getSuperClasses(null)); while (prevExceptPart != null) { final PyExpression classExpression = prevExceptPart.getExceptClass(); if (classExpression == null) return; diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java index 1bfe00a95fa7..d9d25f5e8d23 100644 --- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java @@ -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 resolveResult = provider.getMembers(type, reference.getElement()); + final Collection resolveResult = provider.getMembers(type, reference.getElement(), typeEvalContext); for (PyCustomMember member : resolveResult) { if (member.getName().equals(name)) return true; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java index 6a04d80900f1..d86a93e53f7c 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java +++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java @@ -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(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(getSuperClassUnionType(containingClass)); + return new Maybe(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 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); diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 3fd8de69e7b5..0bea5262b041 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -267,22 +267,29 @@ public class PyClassImpl extends PyBaseElementImpl 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 implements PyCla } return PyFileImpl.getStringListFromTargetExpression(PyNames.SLOTS, getClassAttributes()); } - @NotNull - public PyClass[] getSuperClasses() { - final List superTypes = getSuperClassTypes(TypeEvalContext.codeInsightFallback(getProject())); + public PyClass[] getSuperClasses(@Nullable TypeEvalContext context) { + if (context == null) { + context = TypeEvalContext.codeInsightFallback(getProject()); + } + final List superTypes = getSuperClassTypes(context); if (superTypes.isEmpty()) { return EMPTY_ARRAY; } @@ -540,7 +549,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla @Nullable public PyFunction findInitOrNew(boolean inherited, final @Nullable TypeEvalContext context) { NameFinder proc; - if (isNewStyleClass(null)) { + if (isNewStyleClass(context)) { proc = new NameFinder(PyNames.INIT, PyNames.NEW); } else { @@ -1508,13 +1517,15 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla private static final class MyAttributesCollector implements Processor { private final List myAttributes = new ArrayList(); + @Override public boolean process(final PyTargetExpression expression) { myAttributes.add(expression); return true; } + @NotNull - List getAttributes() { + List getAttributes() { return Collections.unmodifiableList(myAttributes); } } diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java index 81215f67f96f..7adcf80554b1 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java @@ -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) { diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java index 4f86c439cacf..680fd503bffa 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java @@ -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; } } diff --git a/python/src/com/jetbrains/python/psi/search/PyClassInheritorsSearchExecutor.java b/python/src/com/jetbrains/python/psi/search/PyClassInheritorsSearchExecutor.java index 88c13d16d520..c133946e702d 100644 --- a/python/src/com/jetbrains/python/psi/search/PyClassInheritorsSearchExecutor.java +++ b/python/src/com/jetbrains/python/psi/search/PyClassInheritorsSearchExecutor.java @@ -59,7 +59,7 @@ public class PyClassInheritorsSearchExecutor implements QueryExecutor 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)) { diff --git a/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java b/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java index 50c2abb10c93..87b372b62623 100644 --- a/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java +++ b/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java @@ -44,7 +44,7 @@ public class PySuperMethodsSearchExecutor implements QueryExecutor slots = myClass.isNewStyleClass(null) ? myClass.getSlots( + List slots = myClass.isNewStyleClass(context) ? myClass.getSlots( context) : null; if (slots != null) { processor.setAllowedNames(slots); diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java index ae0450ecee0a..ae860229395c 100644 --- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java +++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java @@ -216,7 +216,7 @@ public class PyTypeChecker { public static Set getClassTypeAttributes(@NotNull PyClassType type, boolean inherited, @NotNull TypeEvalContext context) { final Set attributes = getClassAttributes(type.getPyClass(), inherited, type.isDefinition(), context); for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { - final Collection members = provider.getMembers(type, null); + final Collection 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)) { diff --git a/python/src/com/jetbrains/python/pyi/PyiClassMembersProvider.java b/python/src/com/jetbrains/python/pyi/PyiClassMembersProvider.java index 0b01499d95de..ef2b30808e65 100644 --- a/python/src/com/jetbrains/python/pyi/PyiClassMembersProvider.java +++ b/python/src/com/jetbrains/python/pyi/PyiClassMembersProvider.java @@ -35,7 +35,7 @@ import java.util.Collections; public class PyiClassMembersProvider extends PyClassMembersProviderBase implements PyOverridingAncestorsClassMembersProvider { @NotNull @Override - public Collection getMembers(@NotNull PyClassType classType, PsiElement location) { + public Collection getMembers(@NotNull PyClassType classType, PsiElement location, TypeEvalContext typeEvalContext) { final PyClass cls = classType.getPyClass(); final PsiElement pythonStub = PyiUtil.getPythonStub(cls); if (pythonStub instanceof PyClass) { diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java b/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java index b94592bdf1be..3c34539f87bb 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java +++ b/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java @@ -52,7 +52,7 @@ public class PyMemberInfoStorage extends AbstractMemberInfoStorage 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); diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java index 5dfde0e79076..3eb59ab36380 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java @@ -302,7 +302,7 @@ public abstract class MembersManager implements Function { 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; diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java index 86ad3ae70167..c661c682d51c 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java @@ -62,7 +62,7 @@ class SuperClassesManager extends MembersManager { @NotNull @Override protected List getMembersCouldBeMoved(@NotNull final PyClass pyClass) { - return Lists.newArrayList(Collections2.filter(Arrays.asList(pyClass.getSuperClasses()), NO_FAKE_SUPER_CLASSES)); + return Lists.newArrayList(Collections2.filter(Arrays.asList(pyClass.getSuperClasses(null)), NO_FAKE_SUPER_CLASSES)); } @Override diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpInfoModel.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpInfoModel.java index 7cd9f3e2a1f2..70d18de849cd 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpInfoModel.java +++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpInfoModel.java @@ -58,7 +58,7 @@ class PyPullUpInfoModel extends AbstractUsesDependencyMemberInfoModel