From 21d063d58ea0cd619ab1210b2271dfb1fa3c45ad Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 14 Dec 2011 14:55:19 +0100 Subject: [PATCH] honor fileOnly flag correctly when resolving import references (PY-1896) --- .../PyUnresolvedReferencesInspection.java | 20 +++++++++---------- .../psi/impl/PyImportReferenceImpl.java | 10 ++++++++++ .../python/psi/resolve/ResolveImportUtil.java | 7 +++++-- .../importFunction.py | 1 + .../unresolvedImport.py | 2 +- .../unresolvedImportedModule.py | 2 +- .../python/PyMultiFileResolveTest.java | 9 --------- .../PyUnresolvedReferencesInspectionTest.java | 4 ++++ 8 files changed, 32 insertions(+), 23 deletions(-) create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/importFunction.py diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java index 13a9c1ee892b..321569cb010d 100644 --- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java @@ -323,7 +323,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } private void registerUnresolvedReferenceProblem(final PyElement node, final PsiReference reference, HighlightSeverity severity) { - final StringBuilder description_buf = new StringBuilder(""); // TODO: clear description_buf logic. maybe a flag is needed instead. + final StringBuilder descriptionBuf = new StringBuilder(""); // TODO: clear descriptionBuf logic. maybe a flag is needed instead. final String text = reference.getElement().getText(); final String ref_text = reference.getRangeInElement().substring(text); // text of the part we're working with final PsiElement element = reference.getElement(); @@ -393,7 +393,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { )) { severity = HighlightSeverity.WEAK_WARNING; String errmsg = PyBundle.message("INSP.module.$0.not.found", ref_text); - description_buf.append(errmsg); + descriptionBuf.append(errmsg); // TODO: mark the node so that future references pointing to it won't result in a error, but in a warning } } @@ -401,11 +401,11 @@ public class PyUnresolvedReferencesInspection extends PyInspection { if (myIgnoredIdentifiers.contains(reference.getCanonicalText())) return; } - if (reference instanceof PsiReferenceEx) { + if (reference instanceof PsiReferenceEx && descriptionBuf.length() == 0) { final String s = ((PsiReferenceEx)reference).getUnresolvedDescription(); - if (s != null) description_buf.append(s); + if (s != null) descriptionBuf.append(s); } - if (description_buf.length() == 0) { + if (descriptionBuf.length() == 0) { boolean marked_qualified = false; if (element instanceof PyQualifiedExpression) { final PyQualifiedExpression qexpr = (PyQualifiedExpression)element; @@ -441,12 +441,12 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } } if (reference instanceof PyOperatorReferenceImpl) { - description_buf.append(PyBundle.message("INSP.unresolved.operator.ref", + descriptionBuf.append(PyBundle.message("INSP.unresolved.operator.ref", qtype.getName(), refname, ((PyOperatorReferenceImpl)reference).getReadableOperatorName())); } else { - description_buf.append(PyBundle.message("INSP.unresolved.ref.$0.for.class.$1", ref_text, qtype.getName())); + descriptionBuf.append(PyBundle.message("INSP.unresolved.ref.$0.for.class.$1", ref_text, qtype.getName())); } marked_qualified = true; } @@ -461,14 +461,14 @@ public class PyUnresolvedReferencesInspection extends PyInspection { return; } else { - description_buf.append(PyBundle.message("INSP.cannot.find.$0.in.$1", ref_text, qtype.getName())); + descriptionBuf.append(PyBundle.message("INSP.cannot.find.$0.in.$1", ref_text, qtype.getName())); marked_qualified = true; } } } } if (! marked_qualified) { - description_buf.append(PyBundle.message("INSP.unresolved.ref.$0", ref_text)); + descriptionBuf.append(PyBundle.message("INSP.unresolved.ref.$0", ref_text)); if (ref_text.equals("true") || ref_text.equals("false")) actions.add(new UnresolvedRefTrueFalseQuickFix(element)); @@ -509,7 +509,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } } } - String description = description_buf.toString(); + String description = descriptionBuf.toString(); ProblemHighlightType hl_type; if (severity == HighlightSeverity.WARNING) { hl_type = ProblemHighlightType.GENERIC_ERROR_OR_WARNING; diff --git a/python/src/com/jetbrains/python/psi/impl/PyImportReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/PyImportReferenceImpl.java index 63d79ee80359..b63cfd09a901 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyImportReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyImportReferenceImpl.java @@ -37,6 +37,16 @@ public class PyImportReferenceImpl extends PyReferenceImpl { myElement = element; } + + @Override + public String getUnresolvedDescription() { + final PyImportStatement importStatement = PsiTreeUtil.getParentOfType(myElement, PyImportStatement.class); + if (importStatement != null) { + return "No module named " + myElement.getReferencedName(); + } + return super.getUnresolvedDescription(); + } + @NotNull @Override protected List resolveInner() { diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java index 506f66ee2ee8..3b3bb4689d61 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java @@ -615,7 +615,7 @@ public class ResolveImportUtil { module = null; break; } - module = resolveChild(module, component, foothold_file, root, false, checkForPackage); // only files, we want a module + module = resolveChild(module, component, foothold_file, root, true, checkForPackage); // only files, we want a module } return module; } @@ -685,7 +685,10 @@ public class ResolveImportUtil { // 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 = ((PyFileImpl)parent).getElementNamed(referencedName, false); + PsiElement elementNamed = ((PyFileImpl)parent).getElementNamed(referencedName, false); + if (!fileOnly || PyUtil.instanceOf(elementNamed, PsiFile.class, PsiDirectory.class)) { + ret = elementNamed; + } if (ret != null && !PyUtil.instanceOf(ret, PsiFile.class, PsiDirectory.class) && PsiTreeUtil.getStubOrPsiParentOfType(ret, PyExceptPart.class) == null) { return ret; diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/importFunction.py b/python/testData/inspections/PyUnresolvedReferencesInspection/importFunction.py new file mode 100644 index 000000000000..2bfbaa3d0ee9 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/importFunction.py @@ -0,0 +1 @@ +import collections.OrderedDict diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/unresolvedImport.py b/python/testData/inspections/PyUnresolvedReferencesInspection/unresolvedImport.py index 853423274bc8..6920e61d6f58 100644 --- a/python/testData/inspections/PyUnresolvedReferencesInspection/unresolvedImport.py +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/unresolvedImport.py @@ -1 +1 @@ -import wurm +import wurm diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/unresolvedImportedModule.py b/python/testData/inspections/PyUnresolvedReferencesInspection/unresolvedImportedModule.py index 9a9bd1864596..536498f81fad 100644 --- a/python/testData/inspections/PyUnresolvedReferencesInspection/unresolvedImportedModule.py +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/unresolvedImportedModule.py @@ -1,2 +1,2 @@ -import deliverance.proxycommand +import deliverance.proxycommand deliverance.proxycommand.main() diff --git a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java index 196c45ead729..053781491a75 100644 --- a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java @@ -1,7 +1,6 @@ package com.jetbrains.python; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileFilter; import com.intellij.psi.*; @@ -210,14 +209,6 @@ public class PyMultiFileResolveTest extends PyResolveTestCase { assertResolvesTo(PyTargetExpression.class, "__all__"); } - public void testDunderAllImport() { - assertResolvesTo(PyTargetExpression.class, "__all__"); - } - - public void testDunderAllImportResolve() { - assertResolvesTo(PyTargetExpression.class, "__all__"); - } - public void testDunderAllConflict() { assertResolvesTo(PyFunction.class, "do_stuff", "/src/mypackage1.py"); } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index fc8bf9acbbbb..33a3e270252d 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -73,6 +73,10 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase { doTest(); } + public void testImportFunction() { // PY-1896 + doTest(); + } + public void testImportToContainingFile() { // PY-4372 myFixture.copyFileToProject("inspections/PyUnresolvedReferencesInspection/__init__.py", "PyUnresolvedReferencesInspection/__init__.py"); myFixture.copyFileToProject("inspections/PyUnresolvedReferencesInspection/importToContainingFile.py", "PyUnresolvedReferencesInspection/importToContainingFile.py");