From fb0520533dc4364d0d448d649f74696673341343 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Tue, 3 Nov 2015 00:41:28 +0300 Subject: [PATCH] test fix: context passed to event more methods, PyClassImpl getSuperClasses fix --- .../python/codeInsight/PyPsiPath.java | 4 +- .../src/com/jetbrains/python/psi/PyClass.java | 5 +- .../actions/PyQualifiedNameProvider.java | 2 +- .../codeInsight/PyGotoSuperHandler.java | 4 +- .../codeInsight/PyLineMarkerProvider.java | 10 +- .../override/PyOverrideImplementUtil.java | 4 +- .../PyUserSkeletonsClassMembersProvider.java | 4 +- .../documentation/PyDocumentationBuilder.java | 4 +- .../DocStringParameterReference.java | 2 +- .../findUsages/PyClassFindUsagesHandler.java | 2 +- .../PyAbstractClassInspection.java | 4 +- .../PyAttributeOutsideInitInspection.java | 4 +- .../PyInitNewSignatureInspection.java | 2 +- .../PyMissingConstructorInspection.java | 4 +- .../PyPropertyAccessInspection.java | 2 +- .../PyPropertyDefinitionInspection.java | 4 +- .../inspections/PyStringFormatInspection.java | 2 +- .../quickfix/AddCallSuperQuickFix.java | 2 +- .../quickfix/AddFieldQuickFix.java | 4 +- .../quickfix/PyChangeSignatureQuickFix.java | 2 +- .../PyUnresolvedReferencesInspection.java | 2 +- .../setupPy/SetupTaskIntrospector.java | 6 +- .../src/com/jetbrains/python/psi/PyUtil.java | 2 +- .../psi/impl/PyCallExpressionHelper.java | 2 +- .../python/psi/impl/PyClassImpl.java | 112 +++++++++++------- .../impl/PySubscriptionExpressionImpl.java | 2 +- .../psi/impl/PyTargetExpressionImpl.java | 2 +- .../KeywordArgumentCompletionUtil.java | 2 +- .../psi/impl/references/PyReferenceImpl.java | 4 +- .../psi/impl/stubs/PyClassElementType.java | 24 ++-- .../PyOverridingMethodsSearchExecutor.java | 2 +- .../search/PySuperMethodsSearchExecutor.java | 2 +- .../jetbrains/python/psi/types/PyABCUtil.java | 41 +++---- .../python/psi/types/PyClassTypeImpl.java | 2 +- .../PyChangeSignatureUsageProcessor.java | 2 +- .../classes/PyClassRefactoringUtil.java | 4 +- .../membersManager/ClassFieldsManager.java | 2 +- .../membersManager/MethodsManager.java | 2 +- .../extractmethod/PyExtractMethodUtil.java | 2 +- .../field/PyIntroduceFieldHandler.java | 4 +- .../rename/RenamePyClassProcessor.java | 2 +- .../rename/RenamePyElementProcessor.java | 4 +- .../python/testing/PythonUnitTestUtil.java | 2 +- .../python/PyClassicPropertyTest.java | 4 +- .../com/jetbrains/python/PyOverrideTest.java | 4 +- .../com/jetbrains/python/PyStubsTest.java | 2 +- .../python/codeInsight/PyClassMROTest.java | 2 +- .../classes/PyClassRefactoringTest.java | 4 +- 48 files changed, 174 insertions(+), 142 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/codeInsight/PyPsiPath.java b/python/psi-api/src/com/jetbrains/python/codeInsight/PyPsiPath.java index c2b7c5f9e581..4369b4cc5d73 100644 --- a/python/psi-api/src/com/jetbrains/python/codeInsight/PyPsiPath.java +++ b/python/psi-api/src/com/jetbrains/python/codeInsight/PyPsiPath.java @@ -125,7 +125,7 @@ public abstract class PyPsiPath { return ((PyFile) parent).findTopLevelFunction(myFunctionName); } if (parent instanceof PyClass) { - return ((PyClass) parent).findMethodByName(myFunctionName, false); + return ((PyClass) parent).findMethodByName(myFunctionName, false, null); } for (PsiElement element : parent.getChildren()) { if (element instanceof PyFunction && myFunctionName.equals(((PyFunction)element).getName())) { @@ -189,7 +189,7 @@ public abstract class PyPsiPath { if (!(parent instanceof PyClass)) { return null; } - return ((PyClass)parent).findClassAttribute(myAttributeName, true); + return ((PyClass)parent).findClassAttribute(myAttributeName, true, null); } } 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 0bf5ca3c00ca..009466f41c89 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java @@ -121,10 +121,11 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine * * @param name what to look for * @param inherited true: search in superclasses; false: only look for methods defined in this class. + * @param context * @return */ @Nullable - PyFunction findMethodByName(@Nullable @NonNls final String name, boolean inherited); + PyFunction findMethodByName(@Nullable @NonNls final String name, boolean inherited, TypeEvalContext context); /** * Finds either __init__ or __new__, whichever is defined for given class. @@ -193,7 +194,7 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine List getClassAttributesInherited(@NotNull TypeEvalContext context); @Nullable - PyTargetExpression findClassAttribute(@NotNull String name, boolean inherited); + PyTargetExpression findClassAttribute(@NotNull String name, boolean inherited, TypeEvalContext context); /** * Effectively collects assignments to attributes of {@code self} in {@code __init__}, {@code __new__} and diff --git a/python/src/com/jetbrains/python/actions/PyQualifiedNameProvider.java b/python/src/com/jetbrains/python/actions/PyQualifiedNameProvider.java index 6d7da2b25da8..024883766c03 100644 --- a/python/src/com/jetbrains/python/actions/PyQualifiedNameProvider.java +++ b/python/src/com/jetbrains/python/actions/PyQualifiedNameProvider.java @@ -67,7 +67,7 @@ public class PyQualifiedNameProvider implements QualifiedNameProvider { final String memberName = StringUtil.getShortName(fqn, '#'); final PyClass nestedClass = aClass.findNestedClass(memberName, false); if (nestedClass != null) return nestedClass; - final PyFunction methodByName = aClass.findMethodByName(memberName, false); + final PyFunction methodByName = aClass.findMethodByName(memberName, false, null); if (methodByName != null) return methodByName; } } diff --git a/python/src/com/jetbrains/python/codeInsight/PyGotoSuperHandler.java b/python/src/com/jetbrains/python/codeInsight/PyGotoSuperHandler.java index f25ec4951979..a71813402bcc 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyGotoSuperHandler.java +++ b/python/src/com/jetbrains/python/codeInsight/PyGotoSuperHandler.java @@ -86,7 +86,7 @@ public class PyGotoSuperHandler implements CodeInsightActionHandler { } final List result = new ArrayList(); for (PyClass aClass: pyClass.getAncestorClasses(null)) { - final PyTargetExpression superAttr = aClass.findClassAttribute(name, false); + final PyTargetExpression superAttr = aClass.findClassAttribute(name, false, null); if (superAttr != null) { result.add(superAttr); } @@ -101,7 +101,7 @@ public class PyGotoSuperHandler implements CodeInsightActionHandler { } final List result = new ArrayList(); for (PyClass aClass: pyClass.getAncestorClasses(null)) { - final PyFunction byName = aClass.findMethodByName(name, false); + final PyFunction byName = aClass.findMethodByName(name, false, null); if (byName != null) { result.add(byName); } diff --git a/python/src/com/jetbrains/python/codeInsight/PyLineMarkerProvider.java b/python/src/com/jetbrains/python/codeInsight/PyLineMarkerProvider.java index 8f48b7f10e8e..66050ee35f48 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyLineMarkerProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/PyLineMarkerProvider.java @@ -92,7 +92,7 @@ public class PyLineMarkerProvider implements LineMarkerProvider, PyLineSeparator builder.append("Has overridden methods"); return false; } - if (pyClass.findMethodByName(pyFunction.getName(), false) != null) { + if (pyClass.findMethodByName(pyFunction.getName(), false, null) != null) { builder.append("
  ").append(pyClass.getName()); } return true; @@ -126,7 +126,7 @@ public class PyLineMarkerProvider implements LineMarkerProvider, PyLineSeparator PyClass containingClass = PsiTreeUtil.getParentOfType(elt, PyClass.class); if (containingClass != null && elt instanceof PyTargetExpression) { for (PyClass ancestor : containingClass.getAncestorClasses(null)) { - final PyTargetExpression attribute = ancestor.findClassAttribute(((PyTargetExpression)elt).getReferencedName(), false); + final PyTargetExpression attribute = ancestor.findClassAttribute(((PyTargetExpression)elt).getReferencedName(), false, null); if (attribute != null) { result.add(attribute); } @@ -180,7 +180,7 @@ public class PyLineMarkerProvider implements LineMarkerProvider, PyLineSeparator if (PyNames.INIT.equals(function.getName())) { return null; } - final TypeEvalContext context = TypeEvalContext.codeAnalysis(element.getProject(), null); + final TypeEvalContext context = TypeEvalContext.codeAnalysis(element.getProject(), (function != null ? function.getContainingFile() : null)); final PsiElement superMethod = PySuperMethodsSearch.search(function, context).findFirst(); if (superMethod != null) { PyClass superClass = null; @@ -206,7 +206,7 @@ public class PyLineMarkerProvider implements LineMarkerProvider, PyLineSeparator if (containingClass == null) return null; for (PyClass ancestor : containingClass .getAncestorClasses(TypeEvalContext.codeAnalysis(element.getProject(), element.getContainingFile()))) { - final PyTargetExpression ancestorAttr = ancestor.findClassAttribute(name, false); + final PyTargetExpression ancestorAttr = ancestor.findClassAttribute(name, false, null); if (ancestorAttr != null) { return new LineMarkerInfo(element, element.getTextRange().getStartOffset(), AllIcons.Gutter.OverridingMethod, Pass.UPDATE_ALL, @@ -254,7 +254,7 @@ public class PyLineMarkerProvider implements LineMarkerProvider, PyLineSeparator public boolean process(final PyClass inheritor) { for (Iterator it = candidates.get(pyClass).iterator(); it.hasNext(); ) { PyFunction func = it.next(); - if (inheritor.findMethodByName(func.getName(), false) != null) { + if (inheritor.findMethodByName(func.getName(), false, null) != null) { overridden.add(func); it.remove(); } diff --git a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java index 8b7e1d9a3599..ba97dd348b3e 100644 --- a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java @@ -115,7 +115,7 @@ public class PyOverrideImplementUtil { if (name == null || PyUtil.isClassPrivateName(name)) { continue; } - if (pyClass.findMethodByName(name, false) == null) { + if (pyClass.findMethodByName(name, false, null) == null) { final PyMethodMember member = new PyMethodMember(function); elements.add(member); } @@ -245,7 +245,7 @@ public class PyOverrideImplementUtil { if (!PyNames.INIT.equals(baseFunction.getName()) && context.getReturnType(baseFunction) != PyNoneType.INSTANCE || overridingNew) { statementBody.append("return "); } - if (baseClass.isNewStyleClass(null)) { + if (baseClass.isNewStyleClass(context)) { statementBody.append(PyNames.SUPER); statementBody.append("("); final LanguageLevel langLevel = ((PyFile)pyClass.getContainingFile()).getLanguageLevel(); diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java index c0bcc8e3c7d3..8c06ef2a3af8 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java @@ -60,7 +60,7 @@ public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderB } public static PsiElement findClassMember(@NotNull PyClass cls, @NotNull String name, boolean isDefinition) { - final PyFunction function = cls.findMethodByName(name, false); + final PyFunction function = cls.findMethodByName(name, false, null); if (function != null) { final PyUtil.MethodFlags methodFlags = PyUtil.MethodFlags.of(function); final boolean instanceMethod = methodFlags == null || methodFlags.isInstanceMethod(); @@ -74,7 +74,7 @@ public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderB return instanceAttribute; } } - final PyTargetExpression classAttribute = cls.findClassAttribute(name, false); + final PyTargetExpression classAttribute = cls.findClassAttribute(name, false, null); if (classAttribute != null) { return classAttribute; } diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java index 4cebb5b3e92c..4caabd03b553 100644 --- a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java +++ b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java @@ -359,7 +359,7 @@ public class PyDocumentationBuilder { isFromClass = true; } else { - inherited = ancestor.findMethodByName(methodName, false); + inherited = ancestor.findMethodByName(methodName, false, null); } if (inherited != null) { docstringElement = inherited.getDocStringExpression(); @@ -403,7 +403,7 @@ public class PyDocumentationBuilder { final PyClassType objectType = PyBuiltinCache.getInstance(fun).getObjectType(); // old- and new-style classes share the __xxx__ stuff if (objectType != null) { final PyClass objectClass = objectType.getPyClass(); - final PyFunction predefinedMethod = objectClass.findMethodByName(mothodName, false); + final PyFunction predefinedMethod = objectClass.findMethodByName(mothodName, false, null); if (predefinedMethod != null) { final PyStringLiteralExpression predefinedDocstring = predefinedMethod.getDocStringExpression(); final String predefinedDoc = predefinedDocstring != null ? predefinedDocstring.getStringValue() : null; diff --git a/python/src/com/jetbrains/python/documentation/docstrings/DocStringParameterReference.java b/python/src/com/jetbrains/python/documentation/docstrings/DocStringParameterReference.java index 42395ef5e111..8a74aeffc9cb 100644 --- a/python/src/com/jetbrains/python/documentation/docstrings/DocStringParameterReference.java +++ b/python/src/com/jetbrains/python/documentation/docstrings/DocStringParameterReference.java @@ -58,7 +58,7 @@ public class DocStringParameterReference extends PsiReferenceBase 0 && !PyABCUtil.isSubclass(type.getPyClass(), PyNames.MAPPING)) { + if (myUsedMappingKeys.size() > 0 && !PyABCUtil.isSubclass(type.getPyClass(), PyNames.MAPPING, null)) { registerProblem(rightExpression, PyBundle.message("INSP.format.requires.mapping")); return; } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java index 9fdb22b1a2d3..ff2f8cebb201 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java @@ -66,7 +66,7 @@ public class AddCallSuperQuickFix implements LocalQuickFix { if (superClasses.length == 0) return; final PyClass superClass = superClasses[0]; - final PyFunction superInit = superClass.findMethodByName(PyNames.INIT, true); + final PyFunction superInit = superClass.findMethodByName(PyNames.INIT, true, null); if (superInit == null) return; final ParametersInfo origInfo = new ParametersInfo(problemFunction.getParameterList()); diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java index 5156205aa82f..75a3ba574a91 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java @@ -146,13 +146,13 @@ public class AddFieldQuickFix implements LocalQuickFix { @Nullable public static PsiElement addFieldToInit(Project project, PyClass cls, String itemName, Function callback) { if (cls != null && itemName != null) { - PyFunction init = cls.findMethodByName(PyNames.INIT, false); + PyFunction init = cls.findMethodByName(PyNames.INIT, false, null); if (init != null) { return appendToMethod(init, callback); } else { // no init! boldly copy ancestor's. for (PyClass ancestor : cls.getAncestorClasses(null)) { - init = ancestor.findMethodByName(PyNames.INIT, false); + init = ancestor.findMethodByName(PyNames.INIT, false, null); if (init != null) break; } PyFunction newInit = createInitMethod(project, cls, init); diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyChangeSignatureQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyChangeSignatureQuickFix.java index 091bd88bc82d..3addc73996c4 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/PyChangeSignatureQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyChangeSignatureQuickFix.java @@ -61,7 +61,7 @@ public class PyChangeSignatureQuickFix implements LocalQuickFix { final String complementaryName = PyNames.NEW.equals(functionName) ? PyNames.INIT : PyNames.NEW; final TypeEvalContext context = TypeEvalContext.userInitiated(project, descriptor.getEndElement().getContainingFile()); final PyFunction complementaryMethod = myOverridenMethod ? (PyFunction)PySuperMethodsSearch.search(function, context).findFirst() - : cls.findMethodByName(complementaryName, true); + : cls.findMethodByName(complementaryName, true, null); assert complementaryMethod != null; final PyMethodDescriptor methodDescriptor = new PyMethodDescriptor(function) { diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java index d9d25f5e8d23..797cc453b82f 100644 --- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java @@ -942,7 +942,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { // if we're in a class context and the class defines a variable with the same name, offer auto-import only as quickfix, // not as popup PyClass containingClass = PsiTreeUtil.getParentOfType(node, PyClass.class); - if (containingClass != null && (containingClass.findMethodByName(importFix.getNameToImport(), true) != null || + if (containingClass != null && (containingClass.findMethodByName(importFix.getNameToImport(), true, null) != null || containingClass.findInstanceAttribute(importFix.getNameToImport(), true) != null)) { return true; } diff --git a/python/src/com/jetbrains/python/packaging/setupPy/SetupTaskIntrospector.java b/python/src/com/jetbrains/python/packaging/setupPy/SetupTaskIntrospector.java index b840d304114c..1b9a1ab3fbe4 100644 --- a/python/src/com/jetbrains/python/packaging/setupPy/SetupTaskIntrospector.java +++ b/python/src/com/jetbrains/python/packaging/setupPy/SetupTaskIntrospector.java @@ -116,7 +116,7 @@ public class SetupTaskIntrospector { ? PyClassNameIndex.findClass("distutils.command.build_ext.build_ext", file.getProject()) : file.findTopLevelClass(name); if (taskClass != null) { - final PyTargetExpression description = taskClass.findClassAttribute("description", true); + final PyTargetExpression description = taskClass.findClassAttribute("description", true, null); if (description != null) { final String descriptionText = PyPsiUtils.strValue(PyPsiUtils.flattenParens(description.findAssignedValue())); if (descriptionText != null) { @@ -133,7 +133,7 @@ public class SetupTaskIntrospector { } } - final PyTargetExpression negativeOpt = taskClass.findClassAttribute("negative_opt", true); + final PyTargetExpression negativeOpt = taskClass.findClassAttribute("negative_opt", true, null); final Map negativeOptMap = negativeOpt == null ? Collections.emptyMap() : parseNegativeOpt(negativeOpt.findAssignedValue()); @@ -152,7 +152,7 @@ public class SetupTaskIntrospector { private static List resolveSequenceValue(PyClass aClass, String name) { List result = new ArrayList(); - collectSequenceElements(aClass.findClassAttribute(name, true), result); + collectSequenceElements(aClass.findClassAttribute(name, true, null), result); return result; } diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index bf32c66b7b60..2a76d7129041 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -689,7 +689,7 @@ public class PyUtil { */ @Nullable public static PyFunction getInitMethod(@NotNull final PyClass pyClass) { - return pyClass.findMethodByName(PyNames.INIT, false); + return pyClass.findMethodByName(PyNames.INIT, false, null); } /** diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java index d86a93e53f7c..c4227fd6ee48 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java +++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java @@ -551,7 +551,7 @@ public class PyCallExpressionHelper { return Ref.create(t); } if (cls != null && t == null) { - final PyFunction newMethod = cls.findMethodByName(PyNames.NEW, true); + final PyFunction newMethod = cls.findMethodByName(PyNames.NEW, true, null); if (newMethod != null && !PyBuiltinCache.getInstance(call).isBuiltin(newMethod)) { return Ref.create(PyUnionType.createWeakType(new PyClassTypeImpl(cls, false))); } diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 0bea5262b041..19a5a8434a86 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -40,6 +40,7 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.documentation.docstrings.DocStringUtil; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.stubs.PyClassElementType; import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.resolve.PyResolveUtil; import com.jetbrains.python.psi.resolve.QualifiedNameFinder; @@ -334,6 +335,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } return PyFileImpl.getStringListFromTargetExpression(PyNames.SLOTS, getClassAttributes()); } + @NotNull public PyClass[] getSuperClasses(@Nullable TypeEvalContext context) { if (context == null) { @@ -530,10 +532,11 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } } - public PyFunction findMethodByName(@Nullable final String name, boolean inherited) { + @Override + public PyFunction findMethodByName(@Nullable final String name, boolean inherited, @Nullable TypeEvalContext context) { if (name == null) return null; NameFinder proc = new NameFinder(name); - visitMethods(proc, inherited, null); + visitMethods(proc, inherited, context); return proc.getResult(); } @@ -657,7 +660,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla if (value == null || PyNames.NONE.equals(value)) { return NONE; } - PyFunction method = findMethodByName(value, true); + PyFunction method = findMethodByName(value, true, null); if (method != null) return new Maybe(method); } return UNKNOWN_CALL; @@ -694,7 +697,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla if (property != null) { return property; } - if (findMethodByName(name, false) != null || findClassAttribute(name, false) != null) { + if (findMethodByName(name, false, null) != null || findClassAttribute(name, false, null) != null) { return null; } if (inherited) { @@ -767,7 +770,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla return local; } if (inherited) { - if (name != null && (findMethodByName(name, false) != null || findClassAttribute(name, false) != null)) { + if (name != null && (findMethodByName(name, false, null) != null || findClassAttribute(name, false, null) != null)) { return null; } for (PyClass cls : getAncestorClasses(null)) { @@ -980,9 +983,9 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } @Override - public PyTargetExpression findClassAttribute(@NotNull String name, boolean inherited) { + public PyTargetExpression findClassAttribute(@NotNull String name, boolean inherited, TypeEvalContext context) { final NameFinder processor = new NameFinder(name); - visitClassAttributes(processor, inherited, null); + visitClassAttributes(processor, inherited, context); return processor.getResult(); } @@ -1017,7 +1020,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla Map result = new HashMap(); collectAttributesInNew(result); - PyFunctionImpl initMethod = (PyFunctionImpl)findMethodByName(PyNames.INIT, false); + PyFunctionImpl initMethod = (PyFunctionImpl)findMethodByName(PyNames.INIT, false, null); if (initMethod != null) { collectInstanceAttributes(initMethod, result); } @@ -1034,7 +1037,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } private void collectAttributesInNew(@NotNull final Map result) { - final PyFunction newMethod = findMethodByName(PyNames.NEW, false); + final PyFunction newMethod = findMethodByName(PyNames.NEW, false, null); if (newMethod != null) { for (PyTargetExpression target : getTargetExpressions(newMethod)) { result.put(target.getName(), target); @@ -1131,7 +1134,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } } } - if (pyClass.findClassAttribute(PyNames.DUNDER_METACLASS, false) != null) { + if (pyClass.findClassAttribute(PyNames.DUNDER_METACLASS, false, null) != null) { return true; } return false; @@ -1244,42 +1247,15 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } final PyClassStub stub = getStub(); final List result = new ArrayList(); + // In some cases stub may not provide all information, so we use stubs only if AST access id disabled - if (!context.maySwitchToAST(this) && stub != null) { - final PsiFile file = getContainingFile(); - if (file instanceof PyFile) { - for (QualifiedName name : stub.getSuperClasses()) { - result.add(name != null ? classTypeFromQName(name, (PyFile)file, context) : null); - } - } + if (!context.maySwitchToAST(this)) { + fillSuperClassesNoSwitchToAst(context, stub, result); } else { - for (PyExpression expression : getSuperClassExpressions()) { - context.getType(expression); - expression = unfoldClass(expression); - if (expression instanceof PyKeywordArgument) { - continue; - } - final PyType type = context.getType(expression); - PyClassLikeType classLikeType = null; - if (type instanceof PyClassLikeType) { - classLikeType = (PyClassLikeType)type; - } - else { - final PsiReference ref = expression.getReference(); - if (ref != null) { - final PsiElement resolved = ref.resolve(); - if (resolved instanceof PyClass) { - final PyType resolvedType = context.getType((PyClass)resolved); - if (resolvedType instanceof PyClassLikeType) { - classLikeType = (PyClassLikeType)resolvedType; - } - } - } - } - result.add(classLikeType); - } + fillSuperClassesSwitchingToAst(context, result); } + final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(this); if (result.isEmpty() && isValid() && !builtinCache.isBuiltin(this)) { final String implicitSuperName = LanguageLevel.forElement(this).isPy3K() ? PyNames.OBJECT : PyNames.FAKE_OLD_BASE; @@ -1294,6 +1270,54 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla return result; } + private void fillSuperClassesSwitchingToAst(@NotNull TypeEvalContext context, List result) { + for (PyExpression expression : getSuperClassExpressions()) { + context.getType(expression); + expression = unfoldClass(expression); + if (expression instanceof PyKeywordArgument) { + continue; + } + final PyType type = context.getType(expression); + PyClassLikeType classLikeType = null; + if (type instanceof PyClassLikeType) { + classLikeType = (PyClassLikeType)type; + } + else { + final PsiReference ref = expression.getReference(); + if (ref != null) { + final PsiElement resolved = ref.resolve(); + if (resolved instanceof PyClass) { + final PyType resolvedType = context.getType((PyClass)resolved); + if (resolvedType instanceof PyClassLikeType) { + classLikeType = (PyClassLikeType)resolvedType; + } + } + } + } + result.add(classLikeType); + } + } + + private void fillSuperClassesNoSwitchToAst(@NotNull final TypeEvalContext context, + @Nullable final PyClassStub stub, + @NotNull final List result) { + final List qualifiedNames; + if (stub != null) { + qualifiedNames = Arrays.asList(stub.getSuperClasses()); + } + else { + qualifiedNames = PyClassElementType.getSuperClassQNames(this); + } + + + final PsiFile file = getContainingFile(); + if (file instanceof PyFile) { + for (QualifiedName name : qualifiedNames) { + result.add(name != null ? classTypeFromQName(name, (PyFile)file, context) : null); + } + } + } + @NotNull @Override public List getAncestorTypes(@NotNull TypeEvalContext context) { @@ -1353,7 +1377,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } } else { - final PyTargetExpression attribute = findClassAttribute(PyNames.DUNDER_METACLASS, false); + final PyTargetExpression attribute = findClassAttribute(PyNames.DUNDER_METACLASS, false, null); if (attribute != null) { return attribute.findAssignedValue(); } @@ -1397,7 +1421,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla if (cls == metaClass) { return false; } - final PyFunction mroMethod = metaClass.findMethodByName(PyNames.MRO, true); + final PyFunction mroMethod = metaClass.findMethodByName(PyNames.MRO, true, null); if (mroMethod != null) { final PyClass mroClass = mroMethod.getContainingClass(); if (mroClass != null && mroClass != typeClass) { diff --git a/python/src/com/jetbrains/python/psi/impl/PySubscriptionExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PySubscriptionExpressionImpl.java index a50bdf3b2d5b..85f711dc353f 100644 --- a/python/src/com/jetbrains/python/psi/impl/PySubscriptionExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PySubscriptionExpressionImpl.java @@ -81,7 +81,7 @@ public class PySubscriptionExpressionImpl extends PyElementImpl implements PySub if (indexExpression != null) { final PyType type = context.getType(getOperand()); final PyClass cls = (type instanceof PyClassType) ? ((PyClassType)type).getPyClass() : null; - if (cls != null && PyABCUtil.isSubclass(cls, PyNames.MAPPING)) { + if (cls != null && PyABCUtil.isSubclass(cls, PyNames.MAPPING, context)) { return res; } if (type instanceof PySubscriptableType) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java index 215118428c6c..4446685fb38a 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java @@ -247,7 +247,7 @@ public class PyTargetExpressionImpl extends PyBaseElementImplemptyMap(), context); if (enterType != null) { diff --git a/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java b/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java index 1723d0c523a3..1c0d45ae6ece 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java +++ b/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java @@ -52,7 +52,7 @@ public class KeywordArgumentCompletionUtil { addKeywordArgumentVariants((PyCallable)def, callExpr, ret); } else if (def instanceof PyClass) { - PyFunction init = ((PyClass)def).findMethodByName(PyNames.INIT, true); // search in superclasses + PyFunction init = ((PyClass)def).findMethodByName(PyNames.INIT, true, null); // search in superclasses if (init != null) { addKeywordArgumentVariants(init, callExpr, ret); } 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 680fd503bffa..2375662fafc0 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java @@ -136,14 +136,14 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference final PsiElement elt = rrr.getElement(); if (elt instanceof PyClass) { PyClass cls = (PyClass)elt; - PyFunction init = cls.findMethodByName(PyNames.INIT, false); + PyFunction init = cls.findMethodByName(PyNames.INIT, false, null); if (init != null) { // replace it.set(rrr.replace(init)); } else { // init not found; maybe it's ancestor's for (PyClass ancestor : cls.getAncestorClasses(myContext.getTypeEvalContext())) { - init = ancestor.findMethodByName(PyNames.INIT, false); + init = ancestor.findMethodByName(PyNames.INIT, false, null); if (init != null) { // add to results as low priority it.add(new RatedResolveResult(RatedResolveResult.RATE_LOW, init)); diff --git a/python/src/com/jetbrains/python/psi/impl/stubs/PyClassElementType.java b/python/src/com/jetbrains/python/psi/impl/stubs/PyClassElementType.java index 54b2f8ecfce4..a62cae8583f4 100644 --- a/python/src/com/jetbrains/python/psi/impl/stubs/PyClassElementType.java +++ b/python/src/com/jetbrains/python/psi/impl/stubs/PyClassElementType.java @@ -53,7 +53,19 @@ public class PyClassElementType extends PyStubElementType } public PyClassStub createStub(@NotNull final PyClass psi, final StubElement parentStub) { - final PyExpression[] exprs = psi.getSuperClassExpressions(); + final List superClasses = getSuperClassQNames(psi); + final PyStringLiteralExpression docStringExpression = psi.getDocStringExpression(); + return new PyClassStubImpl(psi.getName(), parentStub, + superClasses.toArray(new QualifiedName[superClasses.size()]), + PyPsiUtils.asQualifiedName(psi.getMetaClassExpression()), + psi.getOwnSlots(), + PyPsiUtils.strValue(docStringExpression), + getStubElementType()); + } + + @NotNull + public static List getSuperClassQNames(@NotNull final PyClass pyClass) { + final PyExpression[] exprs = pyClass.getSuperClassExpressions(); List superClasses = new ArrayList(); for (PyExpression expression : exprs) { if (expression instanceof PyKeywordArgument) { @@ -62,13 +74,7 @@ public class PyClassElementType extends PyStubElementType expression = PyClassImpl.unfoldClass(expression); superClasses.add(PyPsiUtils.asQualifiedName(expression)); } - final PyStringLiteralExpression docStringExpression = psi.getDocStringExpression(); - return new PyClassStubImpl(psi.getName(), parentStub, - superClasses.toArray(new QualifiedName[superClasses.size()]), - PyPsiUtils.asQualifiedName(psi.getMetaClassExpression()), - psi.getOwnSlots(), - PyPsiUtils.strValue(docStringExpression), - getStubElementType()); + return superClasses; } public void serialize(@NotNull final PyClassStub pyClassStub, @NotNull final StubOutputStream dataStream) throws IOException { @@ -106,7 +112,7 @@ public class PyClassElementType extends PyStubElementType sink.occurrence(PyClassNameIndexInsensitive.KEY, name.toLowerCase()); } final PyClass pyClass = createPsi(stub); - for (String attribute: PyClassAttributesIndex.getAllDeclaredAttributeNames(pyClass)) { + for (String attribute : PyClassAttributesIndex.getAllDeclaredAttributeNames(pyClass)) { sink.occurrence(PyClassAttributesIndex.KEY, attribute); } for (QualifiedName s : stub.getSuperClasses()) { diff --git a/python/src/com/jetbrains/python/psi/search/PyOverridingMethodsSearchExecutor.java b/python/src/com/jetbrains/python/psi/search/PyOverridingMethodsSearchExecutor.java index 908cccd92117..84887c3efa6d 100644 --- a/python/src/com/jetbrains/python/psi/search/PyOverridingMethodsSearchExecutor.java +++ b/python/src/com/jetbrains/python/psi/search/PyOverridingMethodsSearchExecutor.java @@ -34,7 +34,7 @@ public class PyOverridingMethodsSearchExecutor implements QueryExecutor { final PyClass clazz = PyUtil.getContainingClassOrSelf(pyFunction); assert clazz != null : "Refactoring called on function, not method: " + pyFunction; for (final PyClass parentClass : clazz.getSuperClasses(null)) { - final PyFunction parentMethod = parentClass.findMethodByName(pyFunction.getName(), true); + final PyFunction parentMethod = parentClass.findMethodByName(pyFunction.getName(), true, null); if (parentMethod != null) { return true; } diff --git a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java index 21c800a08ee4..2898211f315e 100644 --- a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java +++ b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java @@ -687,7 +687,7 @@ public class PyExtractMethodUtil { ScopeOwner owner = parent; while (owner != null) { if (owner instanceof PyClass) { - if (((PyClass)owner).findMethodByName(s, true) != null) { + if (((PyClass)owner).findMethodByName(s, true, null) != null) { return false; } } diff --git a/python/src/com/jetbrains/python/refactoring/introduce/field/PyIntroduceFieldHandler.java b/python/src/com/jetbrains/python/refactoring/introduce/field/PyIntroduceFieldHandler.java index a3e579d9e268..94474e59a59c 100644 --- a/python/src/com/jetbrains/python/refactoring/introduce/field/PyIntroduceFieldHandler.java +++ b/python/src/com/jetbrains/python/refactoring/introduce/field/PyIntroduceFieldHandler.java @@ -173,7 +173,7 @@ public class PyIntroduceFieldHandler extends IntroduceHandler { PyClass clazz = PyUtil.getContainingClassOrSelf(expr); PsiElement current = PyUtil.getConcealingParent(expression); if (clazz != null && current != null && current instanceof PyFunction) { - PyFunction init = clazz.findMethodByName(PyNames.INIT, false); + PyFunction init = clazz.findMethodByName(PyNames.INIT, false, null); if (current == init) { return true; } @@ -183,7 +183,7 @@ public class PyIntroduceFieldHandler extends IntroduceHandler { @Nullable private static PsiElement addFieldToSetUp(PyClass clazz, final Function callback) { - final PyFunction init = clazz.findMethodByName(PythonUnitTestUtil.TESTCASE_SETUP_NAME, false); + final PyFunction init = clazz.findMethodByName(PythonUnitTestUtil.TESTCASE_SETUP_NAME, false, null); if (init != null) { return AddFieldQuickFix.appendToMethod(init, callback); } diff --git a/python/src/com/jetbrains/python/refactoring/rename/RenamePyClassProcessor.java b/python/src/com/jetbrains/python/refactoring/rename/RenamePyClassProcessor.java index 3f11c0505ee5..0e20885b5751 100644 --- a/python/src/com/jetbrains/python/refactoring/rename/RenamePyClassProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/rename/RenamePyClassProcessor.java @@ -64,7 +64,7 @@ public class RenamePyClassProcessor extends RenamePyElementProcessor { @Override public Collection findReferences(final PsiElement element) { if (element instanceof PyClass) { - final PyFunction initMethod = ((PyClass)element).findMethodByName(PyNames.INIT, true); + final PyFunction initMethod = ((PyClass)element).findMethodByName(PyNames.INIT, true, null); if (initMethod != null) { final List allRefs = Collections.synchronizedList(new ArrayList()); allRefs.addAll(super.findReferences(element)); diff --git a/python/src/com/jetbrains/python/refactoring/rename/RenamePyElementProcessor.java b/python/src/com/jetbrains/python/refactoring/rename/RenamePyElementProcessor.java index 2db1b5ea6fd8..aeb062722008 100644 --- a/python/src/com/jetbrains/python/refactoring/rename/RenamePyElementProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/rename/RenamePyElementProcessor.java @@ -50,11 +50,11 @@ public abstract class RenamePyElementProcessor extends RenamePsiElementProcessor if (conflictingClass != null) { conflicts.putValue(conflictingClass, "A class named '" + newName + "' is already defined in class '" + pyClass.getName() + "'"); } - PyFunction conflictingFunction = pyClass.findMethodByName(newName, true); + PyFunction conflictingFunction = pyClass.findMethodByName(newName, true, null); if (conflictingFunction != null) { conflicts.putValue(conflictingFunction, "A function named '" + newName + "' is already defined in class '" + pyClass.getName() + "'"); } - PyTargetExpression conflictingAttribute = pyClass.findClassAttribute(newName, true); + PyTargetExpression conflictingAttribute = pyClass.findClassAttribute(newName, true, null); if (conflictingAttribute != null) { conflicts.putValue(conflictingAttribute, "An attribute named '" + newName + "' is already defined in class '" + pyClass.getName() + "'"); } diff --git a/python/src/com/jetbrains/python/testing/PythonUnitTestUtil.java b/python/src/com/jetbrains/python/testing/PythonUnitTestUtil.java index 95e139a352dc..210200176a2f 100644 --- a/python/src/com/jetbrains/python/testing/PythonUnitTestUtil.java +++ b/python/src/com/jetbrains/python/testing/PythonUnitTestUtil.java @@ -204,7 +204,7 @@ public class PythonUnitTestUtil { locations.add(new PsiLocation(project, cls)); } else { - final PyFunction method = cls.findMethodByName(methodName, true); + final PyFunction method = cls.findMethodByName(methodName, true, null); if (method == null) { continue; } diff --git a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java index 17a8adc6eb6c..4733134eee6b 100644 --- a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java +++ b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java @@ -132,10 +132,10 @@ public class PyClassicPropertyTest extends PyTestCase { */ public void testGetProperty() { - final PyFunction getter = myClass.findMethodByName("v5getter", false); + final PyFunction getter = myClass.findMethodByName("v5getter", false, null); assertNotNull(getter.getProperty()); - final PyFunction setter = myClass.findMethodByName("v5setter", false); + final PyFunction setter = myClass.findMethodByName("v5setter", false, null); assertNotNull(setter.getProperty()); } diff --git a/python/testSrc/com/jetbrains/python/PyOverrideTest.java b/python/testSrc/com/jetbrains/python/PyOverrideTest.java index 53a5d7f55d12..f08155870735 100644 --- a/python/testSrc/com/jetbrains/python/PyOverrideTest.java +++ b/python/testSrc/com/jetbrains/python/PyOverrideTest.java @@ -111,7 +111,7 @@ public class PyOverrideTest extends PyTestCase { myFixture.configureByFile("override/" + getTestName(true) + ".py"); PyClass dateClass = PyClassNameIndex.findClass("datetime.date", myFixture.getProject()); assertNotNull(dateClass); - PyFunction initMethod = dateClass.findMethodByName(PyNames.INIT, false); + PyFunction initMethod = dateClass.findMethodByName(PyNames.INIT, false, null); assertNotNull(initMethod); PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(0), Collections.singletonList(new PyMethodMember(initMethod)), false); @@ -183,7 +183,7 @@ public class PyOverrideTest extends PyTestCase { public void testInstanceCheck() { myFixture.configureByFile("override/" + getTestName(true) + ".py"); final PyClass cls = getTopLevelClass(0); - final PyFunction method = cls.findMethodByName("__instancecheck__", true); + final PyFunction method = cls.findMethodByName("__instancecheck__", true, null); PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), cls, Collections.singletonList(new PyMethodMember(method)), false); myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true); } diff --git a/python/testSrc/com/jetbrains/python/PyStubsTest.java b/python/testSrc/com/jetbrains/python/PyStubsTest.java index 6b63660f8be5..58735ff2541a 100644 --- a/python/testSrc/com/jetbrains/python/PyStubsTest.java +++ b/python/testSrc/com/jetbrains/python/PyStubsTest.java @@ -399,7 +399,7 @@ public class PyStubsTest extends PyTestCase { final PyFile file = getTestFile(); final PyClass c = file.findTopLevelClass("C"); assertNotNull(c); - final PyTargetExpression foo = c.findClassAttribute("foo", false); + final PyTargetExpression foo = c.findClassAttribute("foo", false, null); final String docString = foo.getDocStringValue(); assertEquals("Foo docstring.", docString); } diff --git a/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java b/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java index dca624adabca..5d053da791b1 100644 --- a/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java +++ b/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java @@ -95,7 +95,7 @@ public class PyClassMROTest extends PyTestCase { } public void assertMRO(@NotNull PyClass cls, @NotNull String... mro) { - final List types = cls.getAncestorTypes(TypeEvalContext.codeInsightFallback(cls.getProject())); + final List types = cls.getAncestorTypes(TypeEvalContext.deepCodeInsight(cls.getProject())); final List classNames = new ArrayList(); for (PyClassLikeType type : types) { if (type != null) { diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyClassRefactoringTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyClassRefactoringTest.java index c47935da9588..dd24256021aa 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyClassRefactoringTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/classes/PyClassRefactoringTest.java @@ -87,7 +87,7 @@ public abstract class PyClassRefactoringTest extends PyTestCase { private PyElement findField(final String className, final String memberName) { final PyClass aClass = findClass(className); - final PyTargetExpression attribute = aClass.findClassAttribute(memberName, false); + final PyTargetExpression attribute = aClass.findClassAttribute(memberName, false, null); if (attribute != null) { return attribute; } @@ -96,7 +96,7 @@ public abstract class PyClassRefactoringTest extends PyTestCase { private PyFunction findMethod(final String className, final String name) { final PyClass clazz = findClass(className); - return clazz.findMethodByName(name, false); + return clazz.findMethodByName(name, false, null); } protected PyClass findClass(final String name) {