diff --git a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java index 37c7161f6437..8b9f43c4e1ae 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java @@ -276,6 +276,10 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { @Nullable public PsiElement getElementNamed(String name) { + return getElementNamed(name, true); + } + + public PsiElement getElementNamed(String name, boolean withBuiltins) { final List stack = myGetElementNamedStack.get(); if (stack.contains(name)) { return null; @@ -283,7 +287,7 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { stack.add(name); try { PsiElement exportedName = findExportedName(name); - if (exportedName == null) { + if (exportedName == null && withBuiltins) { final PyFile builtins = PyBuiltinCache.getInstance(this).getBuiltinsFile(); if (builtins != null && builtins != this) { exportedName = builtins.findExportedName(name); diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java index c36ac27a3e7e..22f93d53ceea 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java @@ -16,6 +16,7 @@ import com.intellij.util.containers.HashSet; import com.jetbrains.python.PyNames; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyBuiltinCache; +import com.jetbrains.python.psi.impl.PyFileImpl; import com.jetbrains.python.psi.impl.PyImportResolver; import com.jetbrains.python.psi.impl.PyQualifiedName; import com.jetbrains.python.sdk.PythonSdkType; @@ -571,20 +572,22 @@ public class ResolveImportUtil { PsiDirectory dir = null; PsiElement ret = null; PsiElement possible_ret = null; - if (parent instanceof PyFile) { + if (parent instanceof PyFileImpl) { if (PyNames.INIT_DOT_PY.equals(((PyFile)parent).getName())) { // gobject does weird things like '_gobject = sys.modules['gobject._gobject'], so it's preferable to look at // files before looking at names exported from __init__.py dir = ((PyFile)parent).getContainingDirectory(); possible_ret = resolveInDirectory(referencedName, containingFile, dir, root, fileOnly); } + // OTOH, quite often a module named foo exports a class or function named foo, which is used as a fallback // by a module one level higher (e.g. curses.set_key). Prefer it to submodule if possible. - ret = ((PyFile)parent).getElementNamed(referencedName); + ret = ((PyFileImpl)parent).getElementNamed(referencedName, false); if (ret != null && !PyUtil.instanceOf(ret, PsiFile.class, PsiDirectory.class) && PsiTreeUtil.getStubOrPsiParentOfType(ret, PyExceptPart.class) == null) { return ret; } + if (possible_ret != null) return possible_ret; } else if (parent instanceof PsiDirectory) { diff --git a/python/testData/resolve/ModuleToBuiltins.py b/python/testData/resolve/ModuleToBuiltins.py new file mode 100644 index 000000000000..6320ae9bb24f --- /dev/null +++ b/python/testData/resolve/ModuleToBuiltins.py @@ -0,0 +1,3 @@ +import re +re.set +# diff --git a/python/testSrc/com/jetbrains/python/PyResolveTest.java b/python/testSrc/com/jetbrains/python/PyResolveTest.java index b7c650161963..5154e86d6a09 100644 --- a/python/testSrc/com/jetbrains/python/PyResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyResolveTest.java @@ -379,4 +379,9 @@ public class PyResolveTest extends PyResolveTestCase { public void testImportInTryExcept() { // PY-2197 assertResolvesTo(PyFile.class, "sys.py"); } + + public void testModuleToBuiltins() { + final PsiElement element = doResolve(); + assertNull(element); + } } \ No newline at end of file