diff --git a/python/psi-api/src/com/jetbrains/python/psi/resolve/PyOverridingReferenceResolveProvider.java b/python/psi-api/src/com/jetbrains/python/psi/resolve/PyOverridingReferenceResolveProvider.java
new file mode 100644
index 000000000000..c8e9948c4c05
--- /dev/null
+++ b/python/psi-api/src/com/jetbrains/python/psi/resolve/PyOverridingReferenceResolveProvider.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.psi.resolve;
+
+public interface PyOverridingReferenceResolveProvider extends PyReferenceResolveProvider {
+}
\ No newline at end of file
diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml
index e0cd72c5a26c..22eaa4acff34 100644
--- a/python/src/META-INF/python-core-common.xml
+++ b/python/src/META-INF/python-core-common.xml
@@ -689,6 +689,7 @@
+
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 d56fcd837910..bca772752ed3 100644
--- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java
@@ -223,6 +223,11 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
*/
@NotNull
protected List resolveInner() {
+ final ResolveResultList overriddenRet = resolveByOverridingReferenceResolveProviders();
+ if (!overriddenRet.isEmpty()) {
+ return overriddenRet;
+ }
+
final ResolveResultList ret = new ResolveResultList();
final String referencedName = myElement.getReferencedName();
@@ -235,27 +240,6 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
}
}
- // resolve implicit __class__ inside class function
- if (myElement instanceof PyReferenceExpression &&
- PyNames.__CLASS__.equals(referencedName) &&
- LanguageLevel.forElement(myElement).isAtLeast(LanguageLevel.PYTHON30)) {
- final PyFunction containingFunction = PsiTreeUtil.getParentOfType(myElement, PyFunction.class);
-
- if (containingFunction != null) {
- final PyClass containingClass = containingFunction.getContainingClass();
-
- if (containingClass != null) {
- final PyResolveProcessor processor = new PyResolveProcessor(referencedName);
- PyResolveUtil.scopeCrawlUp(processor, myElement, referencedName, containingFunction);
-
- if (processor.getElements().isEmpty()) {
- ret.add(new RatedResolveResult(RatedResolveResult.RATE_NORMAL, containingClass));
- return ret;
- }
- }
- }
- }
-
// here we have an unqualified expr. it may be defined:
// ...in current file
final PyResolveProcessor processor = new PyResolveProcessor(referencedName);
@@ -359,11 +343,28 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
return true;
}
+ @NotNull
+ private ResolveResultList resolveByOverridingReferenceResolveProviders() {
+ final ResolveResultList results = new ResolveResultList();
+ final TypeEvalContext context = myContext.getTypeEvalContext();
+
+ Arrays
+ .stream(Extensions.getExtensions(PyReferenceResolveProvider.EP_NAME))
+ .filter(PyOverridingReferenceResolveProvider.class::isInstance)
+ .map(provider -> provider.resolveName(myElement, context))
+ .forEach(results::addAll);
+
+ return results;
+ }
+
@NotNull
private ResolveResultList resolveByReferenceResolveProviders() {
final ResolveResultList results = new ResolveResultList();
final TypeEvalContext context = myContext.getTypeEvalContext();
for (PyReferenceResolveProvider provider : Extensions.getExtensions(PyReferenceResolveProvider.EP_NAME)) {
+ if (provider instanceof PyOverridingReferenceResolveProvider) {
+ continue;
+ }
results.addAll(provider.resolveName(myElement, context));
}
return results;
diff --git a/python/src/com/jetbrains/python/psi/resolve/PythonOverridingBuiltinReferenceResolveProvider.java b/python/src/com/jetbrains/python/psi/resolve/PythonOverridingBuiltinReferenceResolveProvider.java
new file mode 100644
index 000000000000..e176d30d4937
--- /dev/null
+++ b/python/src/com/jetbrains/python/psi/resolve/PythonOverridingBuiltinReferenceResolveProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.psi.resolve;
+
+import com.intellij.psi.util.PsiTreeUtil;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.types.TypeEvalContext;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+public class PythonOverridingBuiltinReferenceResolveProvider implements PyOverridingReferenceResolveProvider {
+
+ @NotNull
+ @Override
+ public List resolveName(@NotNull PyQualifiedExpression element, @NotNull TypeEvalContext context) {
+ final String referencedName = element.getReferencedName();
+
+ // resolve implicit __class__ inside class function
+ if (element instanceof PyReferenceExpression &&
+ PyNames.__CLASS__.equals(referencedName) &&
+ LanguageLevel.forElement(element).isAtLeast(LanguageLevel.PYTHON30)) {
+ final PyFunction containingFunction = PsiTreeUtil.getParentOfType(element, PyFunction.class);
+
+ if (containingFunction != null) {
+ final PyClass containingClass = containingFunction.getContainingClass();
+
+ if (containingClass != null) {
+ final PyResolveProcessor processor = new PyResolveProcessor(referencedName);
+ PyResolveUtil.scopeCrawlUp(processor, element, referencedName, containingFunction);
+
+ if (processor.getElements().isEmpty()) {
+ return Collections.singletonList(new RatedResolveResult(RatedResolveResult.RATE_NORMAL, containingClass));
+ }
+ }
+ }
+ }
+
+ return Collections.emptyList();
+ }
+}