diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingClassMembersProvider.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingClassMembersProvider.java
new file mode 100644
index 000000000000..dd042defbc7c
--- /dev/null
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingClassMembersProvider.java
@@ -0,0 +1,7 @@
+package com.jetbrains.python.psi.types;
+
+/**
+ * @author traff
+ */
+public interface PyOverridingClassMembersProvider extends PyClassMembersProvider {
+}
diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index 784334e57ada..1b28061b985b 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -849,6 +849,7 @@
+
diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
index f010f522fc45..a2e66f1bd85a 100644
--- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
+++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
@@ -51,7 +51,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
* Note that classes' and instances' member list can change during execution, so it is important to construct an instance of PyClassType
* right in the place of reference, so that such changes could possibly be accounted for.
*
- * @param source PyClass which defines this type. For builtin or external classes, skeleton files contain the definitions.
+ * @param source PyClass which defines this type. For builtin or external classes, skeleton files contain the definitions.
* @param isDefinition whether this type describes an instance or a definition of the class.
*/
public PyClassTypeImpl(@NotNull PyClass source, boolean isDefinition) {
@@ -77,21 +77,26 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
/**
* @return whether this type refers to an instance or a definition of the class.
*/
- @Override public boolean isDefinition() {
+ @Override
+ public boolean isDefinition() {
return myIsDefinition;
}
- @Override public PyClassType toInstance() {
+ @Override
+ public PyClassType toInstance() {
return myIsDefinition ? new PyClassTypeImpl(myClass, false) : this;
}
- @Override@Nullable
+ @Override
+ @Nullable
public String getClassQName() {
return myClass.getQualifiedName();
}
@Nullable
- public List extends RatedResolveResult> resolveMember(@NotNull final String name, @Nullable PyExpression location, AccessDirection direction,
+ public List extends RatedResolveResult> resolveMember(@NotNull final String name,
+ @Nullable PyExpression location,
+ AccessDirection direction,
PyResolveContext resolveContext) {
final Set> resolving = ourResolveMemberStack.get();
final Pair key = Pair.create(myClass, name);
@@ -112,6 +117,11 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
@Nullable PyExpression location,
@NotNull AccessDirection direction,
@NotNull PyResolveContext resolveContext) {
+ PsiElement classMember = resolveByOverridingMembersProviders(this, name); //overriding members provers have priority to normal resolve
+ if (classMember != null) {
+ return ResolveResultList.to(classMember);
+ }
+
if (resolveContext.allowProperties()) {
Property property = myClass.findProperty(name);
if (property != null) {
@@ -150,7 +160,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
}
}
- PsiElement classMember = resolveClassMember(myClass, myIsDefinition, name, location);
+ classMember = resolveClassMember(myClass, myIsDefinition, name, location);
if (classMember != null) {
return ResolveResultList.to(classMember);
}
@@ -272,7 +282,22 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
}
@Nullable
- private static PsiElement resolveInner(@NotNull PyClass cls, boolean isDefinition, @NotNull String name, @Nullable PyExpression location) {
+ private static PsiElement resolveByOverridingMembersProviders(PyClassType aClass, String name) {
+ for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
+ if (provider instanceof PyOverridingClassMembersProvider) {
+ final PsiElement resolveResult = provider.resolveMember(aClass, name);
+ if (resolveResult != null) return resolveResult;
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ private static PsiElement resolveInner(@NotNull PyClass cls,
+ boolean isDefinition,
+ @NotNull String name,
+ @Nullable PyExpression location) {
final ResolveProcessor processor = new ResolveProcessor(name);
if (!isDefinition) {
if (!cls.processInstanceLevelDeclarations(processor, location)) {