Added 'inherited' flag for PyType.resolveMember

Do not try class members providers for ancestor classes before class
members providers for the current class.
This commit is contained in:
Andrey Vlasovskikh
2013-04-23 18:05:17 +04:00
parent e9fccfb338
commit 4d04cfc792
22 changed files with 66 additions and 51 deletions
@@ -34,7 +34,8 @@ public class PyJavaClassType implements PyClassLikeType {
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext,
boolean inherited) {
final PsiMethod[] methods = myClass.findMethodsByName(name, true);
if (methods.length > 0) {
ResolveResultList resultList = new ResolveResultList();
@@ -43,7 +43,8 @@ public class PyJavaMethodType implements PyCallableType {
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
@Nullable PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext,
boolean inherited) {
return Collections.emptyList();
}
@@ -38,7 +38,8 @@ public class PyJavaPackageType implements PyType {
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
@Nullable PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext,
boolean inherited) {
Project project = myPackage.getProject();
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
String childName = myPackage.getQualifiedName() + "." + name;
@@ -22,18 +22,18 @@ public interface PyType {
/**
* Resolves an attribute of type.
*
*
* @param name attribute name
* @param location the expression of type qualifierType on which the member is being resolved (optional)
* @param direction
* @param resolveContext
* @param inherited look up inherited members and members provided by class providers
* @return null if name definitely cannot be found (e.g. in a qualified reference),
* or an empty list if name is not found but other contexts are worth looking at,
* or a list of elements that define the name, a la multiResolve().
*/
@Nullable
List<? extends RatedResolveResult> resolveMember(@NotNull final String name, @Nullable PyExpression location, AccessDirection direction,
PyResolveContext resolveContext);
PyResolveContext resolveContext, boolean inherited);
/**
* Proposes completion variants from type's attributes.
@@ -45,8 +45,9 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
@Nullable PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
final List<? extends RatedResolveResult> classMembers = super.resolveMember(name, location, direction, resolveContext);
PyResolveContext resolveContext,
boolean inherited) {
final List<? extends RatedResolveResult> classMembers = super.resolveMember(name, location, direction, resolveContext, inherited);
if (classMembers != null && !classMembers.isEmpty()) {
return classMembers;
}
@@ -123,7 +123,7 @@ public class PyStatementEffectInspection extends PyInspection {
PyType type = myTypeEvalContext.getType(binary.getLeftExpression());
if (type != null &&
!type.isBuiltin(myTypeEvalContext) &&
type.resolveMember(method, null, AccessDirection.READ, resolveWithoutImplicits()) != null) {
type.resolveMember(method, null, AccessDirection.READ, resolveWithoutImplicits(), true) != null) {
return true;
}
final PyExpression rhs = binary.getRightExpression();
@@ -131,7 +131,8 @@ public class PyStatementEffectInspection extends PyInspection {
type = myTypeEvalContext.getType(rhs);
if (type != null) {
String rmethod = "__r" + method.substring(2); // __add__ -> __radd__
if (!type.isBuiltin(myTypeEvalContext) && type.resolveMember(rmethod, null, AccessDirection.READ, resolveWithoutImplicits()) != null) {
if (!type.isBuiltin(myTypeEvalContext) && type.resolveMember(rmethod, null, AccessDirection.READ, resolveWithoutImplicits(),
true) != null) {
return true;
}
}
@@ -805,7 +805,8 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
final PyType type = context.getType(cls);
if (type != null) {
final List<? extends RatedResolveResult> results = type.resolveMember(name, null, AccessDirection.READ,
PyResolveContext.noImplicits().withTypeEvalContext(context));
PyResolveContext.noImplicits().withTypeEvalContext(context),
true);
if (results != null && !results.isEmpty()) {
return results.get(0).getElement();
}
@@ -450,7 +450,7 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
final PyType type = TypeEvalContext.fastStubOnly(null).getType((PyClass)parent);
if (type != null) {
final List<? extends RatedResolveResult> results = type.resolveMember(name, null, AccessDirection.READ,
PyResolveContext.noImplicits());
PyResolveContext.noImplicits(), true);
if (results != null && !results.isEmpty()) {
return results.get(0).getElement();
}
@@ -131,7 +131,7 @@ public class PyOperatorReference extends PyReferenceImpl {
final PyType type = typeEvalContext.getType(object);
typeEvalContext.trace("Side text is %s, type is %s", object.getText(), type);
if (type != null && !(type instanceof PyTypeReference)) {
List<? extends RatedResolveResult> res = type.resolveMember(name, object, AccessDirection.of(myElement), myContext);
List<? extends RatedResolveResult> res = type.resolveMember(name, object, AccessDirection.of(myElement), myContext, true);
if (res != null && res.size() > 0) {
results.addAll(res);
}
@@ -141,7 +141,7 @@ public class PyOperatorReference extends PyReferenceImpl {
final PyClass pyClass = ((PyClassType)type).getPyClass();
vFile = pyClass.getContainingFile().getVirtualFile();
}
type.resolveMember(name, object, AccessDirection.of(myElement), myContext);
type.resolveMember(name, object, AccessDirection.of(myElement), myContext, true);
typeEvalContext.trace("Could not resolve member %s in type %s from file %s", name, type, vFile);
}
}
@@ -71,7 +71,8 @@ public class PyQualifiedReference extends PyReferenceImpl {
qualifierType.assertValid("qualifier: " + qualifier);
// resolve within the type proper
AccessDirection ctx = AccessDirection.of(myElement);
final List<? extends RatedResolveResult> membersOfQualifier = qualifierType.resolveMember(referencedName, qualifier, ctx, myContext);
final List<? extends RatedResolveResult> membersOfQualifier = qualifierType.resolveMember(referencedName, qualifier, ctx, myContext,
true);
if (membersOfQualifier == null) {
return ret; // qualifier is positive that such name cannot exist in it
}
@@ -302,7 +302,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
if (PyModuleType.MODULE_MEMBERS.contains(name)) {
PyType otype = builtins_cache.getObjectType(); // "object" as a closest kin to "module"
if (otype != null && name != null) {
ret.addAll(otype.resolveMember(name, null, AccessDirection.READ, myContext));
ret.addAll(otype.resolveMember(name, null, AccessDirection.READ, myContext, true));
}
}
}
@@ -274,7 +274,7 @@ public class ResolveImportUtil {
PyType refType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(parent, TypeEvalContext.fast(), null);
if (refType != null) {
final List<? extends RatedResolveResult> result = refType.resolveMember(referencedName, null, AccessDirection.READ,
PyResolveContext.defaultContext());
PyResolveContext.defaultContext(), true);
if (result != null && !result.isEmpty()) {
return result.get(0).getElement();
}
@@ -102,7 +102,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
@Nullable PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext,
boolean inherited) {
final Set<Pair<PyClass, String>> resolving = ourResolveMemberStack.get();
final Pair<PyClass, String> key = Pair.create(myClass, name);
if (resolving.contains(key)) {
@@ -110,7 +111,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
}
resolving.add(key);
try {
return doResolveMember(name, location, direction, resolveContext);
return doResolveMember(name, location, direction, resolveContext, inherited);
}
finally {
resolving.remove(key);
@@ -121,7 +122,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
private List<? extends RatedResolveResult> doResolveMember(@NotNull String name,
@Nullable PyExpression location,
@NotNull AccessDirection direction,
@NotNull PyResolveContext resolveContext) {
@NotNull PyResolveContext resolveContext,
boolean inherited) {
final TypeEvalContext context = resolveContext.getTypeEvalContext();
PsiElement classMember = resolveByOverridingMembersProviders(this, name); //overriding members provers have priority to normal resolve
if (classMember != null) {
@@ -157,7 +159,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
PyClass derived_class = ((PyClassType)first_arg_type).getPyClass();
final Iterator<PyClass> base_it = derived_class.getAncestorClasses(context).iterator();
if (base_it.hasNext()) {
return new PyClassTypeImpl(base_it.next(), true).resolveMember(name, location, direction, resolveContext);
return new PyClassTypeImpl(base_it.next(), true).resolveMember(name, location, direction, resolveContext, true);
}
else {
return null; // no base classes = super() cannot proxy anything meaningful from a base class
@@ -171,17 +173,19 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
return ResolveResultList.to(classMember);
}
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
if (type instanceof PyClassType) {
PsiElement superMember = resolveClassMember(((PyClassType)type).getPyClass(), myIsDefinition, name, null);
if (superMember != null) {
return ResolveResultList.to(superMember);
if (inherited) {
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
if (type instanceof PyClassType) {
PsiElement superMember = resolveClassMember(((PyClassType)type).getPyClass(), myIsDefinition, name, null);
if (superMember != null) {
return ResolveResultList.to(superMember);
}
}
}
if (type != null) {
final List<? extends RatedResolveResult> results = type.resolveMember(name, location, direction, resolveContext);
if (results != null && !results.isEmpty()) {
return results;
if (type != null) {
final List<? extends RatedResolveResult> results = type.resolveMember(name, location, direction, resolveContext, false);
if (results != null && !results.isEmpty()) {
return results;
}
}
}
}
@@ -189,27 +193,31 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
if (isDefinition() && myClass.isNewStyleClass()) {
PyClassType typeType = getMetaclassType();
if (typeType != null) {
List<? extends RatedResolveResult> typeMembers = typeType.resolveMember(name, location, direction, resolveContext);
List<? extends RatedResolveResult> typeMembers = typeType.resolveMember(name, location, direction, resolveContext, true);
if (typeMembers != null && !typeMembers.isEmpty()) {
return typeMembers;
}
}
}
classMember = resolveByMembersProviders(this, name); //ask providers after real class introspection as providers have less priority
if (inherited) {
classMember = resolveByMembersProviders(this, name); //ask providers after real class introspection as providers have less priority
}
if (classMember != null) {
return ResolveResultList.to(classMember);
}
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
if (type instanceof PyClassType) {
final PyClass pyClass = ((PyClassType)type).getPyClass();
if (pyClass != null) {
PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name);
if (inherited) {
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
if (type instanceof PyClassType) {
final PyClass pyClass = ((PyClassType)type).getPyClass();
if (pyClass != null) {
PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name);
if (superMember != null) {
return ResolveResultList.to(superMember);
if (superMember != null) {
return ResolveResultList.to(superMember);
}
}
}
}
@@ -37,7 +37,7 @@ public class PyFunctionType implements PyCallableType {
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
@Nullable PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext, boolean inherited) {
return Collections.emptyList();
}
@@ -25,7 +25,7 @@ public class PyGenericType implements PyType {
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
@Nullable PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext, boolean inherited) {
return null;
}
@@ -38,11 +38,11 @@ public class PyImportedModuleType implements PyType {
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext, boolean inherited) {
final PsiElement resolved = myImportedModule.resolve();
if (resolved instanceof PyFile) {
final PyFile file = (PyFile)resolved;
return new PyModuleType(file, myImportedModule).resolveMember(name, location, direction, resolveContext);
return new PyModuleType(file, myImportedModule).resolveMember(name, location, direction, resolveContext, true);
}
else if (resolved instanceof PsiDirectory) {
final List<PsiElement> elements = Collections.singletonList(ResolveImportUtil.resolveChild(resolved, name, null, true, true));
@@ -62,7 +62,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
@Nullable PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext, boolean inherited) {
for (PyModuleMembersProvider provider : Extensions.getExtensions(PyModuleMembersProvider.EP_NAME)) {
final PsiElement element = provider.resolveMember(myModule, name);
if (element != null) {
@@ -24,7 +24,7 @@ public class PyNoneType implements PyType { // TODO must extend ClassType. It's
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext, boolean inherited) {
return null;
}
@@ -7,7 +7,6 @@ import com.intellij.psi.ResolveResult;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.stdlib.PyStdlibTypeProvider;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import org.jetbrains.annotations.NotNull;
@@ -465,7 +464,8 @@ public class PyTypeChecker {
for (PyType member : unionType.getMembers()) {
if (member != null) {
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
final List<? extends RatedResolveResult> results = member.resolveMember(name, callee, AccessDirection.READ, resolveContext);
final List<? extends RatedResolveResult> results = member.resolveMember(name, callee, AccessDirection.READ, resolveContext,
true);
if (results != null && !results.isEmpty()) {
sameNameCount++;
}
@@ -241,7 +241,7 @@ public class PyTypeParser {
final String shortName = classRange.substring(qName);
if (moduleType != null) {
final PyResolveContext context = PyResolveContext.defaultContext();
final List<? extends RatedResolveResult> results = moduleType.resolveMember(shortName, null, AccessDirection.READ, context);
final List<? extends RatedResolveResult> results = moduleType.resolveMember(shortName, null, AccessDirection.READ, context, true);
if (results != null && !results.isEmpty()) {
final RatedResolveResult result = results.get(0);
final PsiElement resolved = result.getElement();
@@ -23,7 +23,7 @@ public abstract class PyTypeReferenceImpl implements PyTypeReference {
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext, boolean inherited) {
return Collections.emptyList();
}
@@ -27,12 +27,12 @@ public class PyUnionType implements PyType {
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
PyResolveContext resolveContext, boolean inherited) {
SmartList<RatedResolveResult> ret = new SmartList<RatedResolveResult>();
boolean all_nulls = true;
for (PyType member : myMembers) {
if (member != null) {
List<? extends RatedResolveResult> result = member.resolveMember(name, null, direction, resolveContext);
List<? extends RatedResolveResult> result = member.resolveMember(name, null, direction, resolveContext, true);
if (result != null) {
all_nulls = false;
ret.addAll(result);