From 60ee2f37bcd8382c47a79dabbf37a93737738bfe Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 20 Jul 2012 15:36:10 +0400 Subject: [PATCH 1/8] Fixed NPE in PyPackageRequirementsInspection (EA-37562) --- .../inspections/PyPackageRequirementsInspection.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java b/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java index b9b1455cbbcb..8f6d721dc6bb 100644 --- a/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java @@ -184,9 +184,11 @@ public class PyPackageRequirementsInspection extends PyInspection { final PsiElement element = reference.resolve(); if (element != null) { final PsiFile file = element.getContainingFile(); - final VirtualFile virtualFile = file.getVirtualFile(); - if (ModuleUtil.moduleContainsFile(module, virtualFile, false)) { - return; + if (file != null) { + final VirtualFile virtualFile = file.getVirtualFile(); + if (ModuleUtil.moduleContainsFile(module, virtualFile, false)) { + return; + } } } } From df48e4dddf54612f5662474d86d6ba0b0d8b7841 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 23 Jul 2012 17:14:20 +0400 Subject: [PATCH 2/8] Known signature of itertools.groupby() for Jython 2.x (PY-6816) --- python/helpers/generator3.py | 3 ++- python/helpers/required_gen_version | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/python/helpers/generator3.py b/python/helpers/generator3.py index f9a30d9b3f59..a27ff1003ebc 100644 --- a/python/helpers/generator3.py +++ b/python/helpers/generator3.py @@ -24,7 +24,7 @@ but seemingly no one uses them in C extensions yet anyway. # * re.search-bound, ~30% time, in likes of builtins and _gtk with complex docstrings. # None of this can seemingly be easily helped. Maybe there's a simpler and faster parser library? -VERSION = "1.114" # Must be a number-dot-number string, updated with each change that affects generated skeletons +VERSION = "1.115" # Must be a number-dot-number string, updated with each change that affects generated skeletons # Note: DON'T FORGET TO UPDATE! VERSION_CONTROL_HEADER_FORMAT = '# from %s by generator %s' @@ -911,6 +911,7 @@ class ModuleRedeclarator(object): ("_thread", None, "start_new"): ("(function, args, kwargs=None)", INT_LIT), ("itertools", "groupby", "__init__"): ("(self, iterable, key=None)", None), + ("itertools", None, "groupby"): ("(iterable, key=None)", LIST_LIT), # NOTE: here we stand on shaky ground providing sigs for 3rd-party modules, though well-known ("numpy.core.multiarray", "ndarray", "__array__") : ("(self, dtype=None)", None), diff --git a/python/helpers/required_gen_version b/python/helpers/required_gen_version index 025e1df82847..2957b9e4cbc7 100644 --- a/python/helpers/required_gen_version +++ b/python/helpers/required_gen_version @@ -6,7 +6,7 @@ (default) 1.92 # anything not explicitly marked -(built-in) 1.114 # skeletons of all built-in modules are built together +(built-in) 1.115 # skeletons of all built-in modules are built together # Note: modules like itertools, etc are "(built-in)" and are ignored if given separately _fileio 1.101 From f304907e7d23c69c9f4c23162d0a98e2f487ac6b Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 23 Jul 2012 17:56:07 +0400 Subject: [PATCH 3/8] Resolve os.path to ntpath or posixpath based on the current platform (PY-7024) --- .../stdlib/PyStdlibModuleMembersProvider.java | 16 ++++++++++++++-- .../python/psi/resolve/ResolveImportUtil.java | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibModuleMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibModuleMembersProvider.java index a84b9664c693..3c51c14a3dc6 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibModuleMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibModuleMembersProvider.java @@ -1,7 +1,10 @@ package com.jetbrains.python.codeInsight.stdlib; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.psi.PsiElement; import com.jetbrains.python.codeInsight.PyDynamicMember; import com.jetbrains.python.psi.PyFile; +import com.jetbrains.python.psi.impl.PyQualifiedName; import com.jetbrains.python.psi.resolve.ResolveImportUtil; import com.jetbrains.python.psi.types.PyModuleMembersProvider; @@ -14,8 +17,17 @@ import java.util.Collections; public class PyStdlibModuleMembersProvider extends PyModuleMembersProvider { @Override protected Collection getMembersByQName(PyFile module, String qName, ResolveImportUtil.PointInImport point) { - if (qName.equals("os") && point == ResolveImportUtil.PointInImport.AS_MODULE) { - return Collections.singletonList(new PyDynamicMember("path")); + if (qName.equals("os")) { + if (point == ResolveImportUtil.PointInImport.AS_MODULE) { + return Collections.singletonList(new PyDynamicMember("path")); + } + else if (point == ResolveImportUtil.PointInImport.NONE && module != null) { + final String name = SystemInfo.isWindows ? "ntpath" : "posixpath"; + final PsiElement resolved = ResolveImportUtil.resolveModuleInRoots(PyQualifiedName.fromDottedString(name), module); + if (resolved != null) { + return Collections.singletonList(new PyDynamicMember("path", resolved)); + } + } } return Collections.emptyList(); } diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java index 0dae8fef1d9a..5fa0c29893c9 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java @@ -565,7 +565,7 @@ public class ResolveImportUtil { components.set(0, "datetime"); return PyQualifiedName.fromComponents(components); } - else if (head.equals("ntpath")) { + else if (head.equals("ntpath") | head.equals("posixpath")) { final List result = new ArrayList(); result.add("os"); components.set(0, "path"); From 55383be8505113144f9b8ac6a621fbc180724f51 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 23 Jul 2012 20:15:22 +0400 Subject: [PATCH 4/8] Fixed unresolved reference for reassignment of a variable after star import (PY-7026) --- .../codeInsight/dataflow/scope/ScopeUtil.java | 15 +++++++++++++++ .../dataflow/scope/impl/ScopeImpl.java | 6 +++--- .../PyUnboundLocalVariableInspection.java | 6 ++++-- .../psi/impl/references/PyQualifiedReference.java | 5 +---- .../python/psi/resolve/PyResolveUtil.java | 12 +++++++++--- .../python/psi/resolve/ResolveProcessor.java | 9 ++++----- .../FromImportStarReassignment.py | 4 ++++ .../multiFile/fromImportStarReassignment/m1.py | 2 ++ .../jetbrains/python/PyMultiFileResolveTest.java | 9 ++++++--- 9 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 python/testData/resolve/multiFile/fromImportStarReassignment/FromImportStarReassignment.py create mode 100644 python/testData/resolve/multiFile/fromImportStarReassignment/m1.py diff --git a/python/src/com/jetbrains/python/codeInsight/dataflow/scope/ScopeUtil.java b/python/src/com/jetbrains/python/codeInsight/dataflow/scope/ScopeUtil.java index 4bd865e1ea90..d0890f168832 100644 --- a/python/src/com/jetbrains/python/codeInsight/dataflow/scope/ScopeUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/dataflow/scope/ScopeUtil.java @@ -3,6 +3,8 @@ package com.jetbrains.python.codeInsight.dataflow.scope; import com.intellij.codeInsight.controlflow.ControlFlow; import com.intellij.codeInsight.controlflow.Instruction; import com.intellij.psi.PsiElement; +import com.intellij.psi.StubBasedPsiElement; +import com.intellij.psi.stubs.StubElement; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache; import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction; @@ -52,6 +54,19 @@ public class ScopeUtil { @Nullable public static ScopeOwner getScopeOwner(PsiElement element) { + if (element instanceof StubBasedPsiElement) { + final StubElement stub = ((StubBasedPsiElement)element).getStub(); + if (stub != null) { + StubElement parentStub = stub.getParentStub(); + while (parentStub != null) { + final PsiElement parent = parentStub.getPsi(); + if (parent instanceof ScopeOwner) { + return (ScopeOwner)parent; + } + parentStub = parentStub.getParentStub(); + } + } + } return PsiTreeUtil.getParentOfType(element, ScopeOwner.class); } diff --git a/python/src/com/jetbrains/python/codeInsight/dataflow/scope/impl/ScopeImpl.java b/python/src/com/jetbrains/python/codeInsight/dataflow/scope/impl/ScopeImpl.java index b4b3520605d5..3b48330d3443 100644 --- a/python/src/com/jetbrains/python/codeInsight/dataflow/scope/impl/ScopeImpl.java +++ b/python/src/com/jetbrains/python/codeInsight/dataflow/scope/impl/ScopeImpl.java @@ -6,6 +6,7 @@ import com.intellij.codeInsight.dataflow.map.DFAMap; import com.intellij.codeInsight.dataflow.map.DFAMapEngine; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; +import com.jetbrains.cython.psi.CythonIncludeStatement; import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.PyReachingDefsDfaInstance; @@ -181,9 +182,8 @@ public class ScopeImpl implements Scope { if (node instanceof PsiNamedElement) { namedElements.put(node.getName(), (PsiNamedElement)node); } - // TODO: NameDefiners should be used only for defining lazily evaluated names - if (node instanceof NameDefiner && !(node instanceof PsiNamedElement || - node instanceof PyParameterList)) { + // TODO: Cython-specific code + if (node instanceof PyStarImportElement || node instanceof PyImportElement || node instanceof CythonIncludeStatement) { nameDefiners.add((NameDefiner)node); } if (node instanceof ScopeOwner) { diff --git a/python/src/com/jetbrains/python/inspections/PyUnboundLocalVariableInspection.java b/python/src/com/jetbrains/python/inspections/PyUnboundLocalVariableInspection.java index a29ea8076462..91e161dd625c 100644 --- a/python/src/com/jetbrains/python/inspections/PyUnboundLocalVariableInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyUnboundLocalVariableInspection.java @@ -110,8 +110,10 @@ public class PyUnboundLocalVariableInspection extends PyInspection { } } if (owner instanceof PyFile) { - // Ignore builtins and variables that are not named elements, i. e. are defined by name definers - if (isBuiltin || scope.getNamedElement(name) == null) { + if (isBuiltin) { + return; + } + if (resolved != null && !PyUtil.inSameFile(node, resolved)) { return; } registerProblem(node, PyBundle.message("INSP.unbound.name.not.defined", name)); diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java index 824a4f7f8f6e..ca621f8df4a1 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java @@ -23,7 +23,6 @@ import com.intellij.util.indexing.FileBasedIndex; import com.jetbrains.cython.types.CythonStructType; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; -import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyBuiltinCache; import com.jetbrains.python.psi.impl.PyImportedModule; @@ -363,9 +362,7 @@ public class PyQualifiedReference extends PyReferenceImpl { PyQualifiedName qualifierPath = PyQualifiedName.fromReferenceChain(PyResolveUtil.unwindQualifiers(qualifier)); if (qualifierPath != null) { AssignmentCollectProcessor proc = new AssignmentCollectProcessor(qualifierPath); - final ScopeOwner roof = ScopeUtil.getResolveScopeOwner(qualifier); - PyResolveUtil.scopeCrawlUp(proc, qualifier, null, roof); - //PyResolveUtil.treeCrawlUp(proc, qualifier); + PyResolveUtil.treeCrawlUp(proc, qualifier); return proc.getResult(); } else { diff --git a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java index 1998b6bd11a4..b3b8d3273bde 100644 --- a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java @@ -112,26 +112,32 @@ public class PyResolveUtil { while (scopeOwner != null) { if (!(scopeOwner instanceof PyClass) || scopeOwner == originalScopeOwner) { final Scope scope = ControlFlowCache.getScope(scopeOwner); + boolean found = false; if (name != null) { final PsiElement resolved = scope.getNamedElement(name); if (resolved != null) { if (!processor.execute(resolved, ResolveState.initial())) { - return; + found = true; } } } else { for (PsiNamedElement element : scope.getNamedElements()) { if (!processor.execute(element, ResolveState.initial())) { - return; + found = true; + break; } } } for (NameDefiner definer : scope.getNameDefiners()) { if (!processor.execute(definer, ResolveState.initial())) { - return; + found = true; + break; } } + if (found) { + return; + } } if (scopeOwner == roof) { return; diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveProcessor.java b/python/src/com/jetbrains/python/psi/resolve/ResolveProcessor.java index ff96a2e379a9..2ddfd4f965f7 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveProcessor.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveProcessor.java @@ -17,6 +17,8 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +import static com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil.getScopeOwner; + public class ResolveProcessor implements PsiScopeProcessor { @NotNull private final String myName; private PsiElement myResult = null; @@ -147,13 +149,10 @@ public class ResolveProcessor implements PsiScopeProcessor { } private boolean setResult(PsiElement result, @Nullable PsiElement definer) { - if (myResult == null || getScope(myResult) == getScope(result) || (definer != null && getScope(myResult) == getScope(definer))) { + if (myResult == null || getScopeOwner(myResult) == getScopeOwner(result) || + (definer != null && getScopeOwner(myResult) == getScopeOwner(definer))) { myResult = result; } return false; } - - private static PsiElement getScope(PsiElement result) { - return PsiTreeUtil.getParentOfType(result, PyFunction.class, PyClass.class, PyFile.class); - } } diff --git a/python/testData/resolve/multiFile/fromImportStarReassignment/FromImportStarReassignment.py b/python/testData/resolve/multiFile/fromImportStarReassignment/FromImportStarReassignment.py new file mode 100644 index 000000000000..6c200d5daaf9 --- /dev/null +++ b/python/testData/resolve/multiFile/fromImportStarReassignment/FromImportStarReassignment.py @@ -0,0 +1,4 @@ +from m1 import * + +foo = foo +# \ No newline at end of file diff --git a/python/testData/resolve/multiFile/fromImportStarReassignment/m1.py b/python/testData/resolve/multiFile/fromImportStarReassignment/m1.py new file mode 100644 index 000000000000..7ed9b98baf42 --- /dev/null +++ b/python/testData/resolve/multiFile/fromImportStarReassignment/m1.py @@ -0,0 +1,2 @@ +def foo(): + return 'foo' \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java index 7b0a50192206..1d1f9e605105 100644 --- a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java @@ -318,9 +318,7 @@ public class PyMultiFileResolveTest extends PyResolveTestCase { assertResolvesTo(CythonVariable.class, "foo"); } - public void _testCythonCdefClassForwardInclude() { - // TODO: Currently we resolve named elements first and then ask name definers, so the result is the forward decl instead of the - // includeded class + public void testCythonCdefClassForwardInclude() { final PyTargetExpression target = assertResolvesTo(PyTargetExpression.class, "bar"); final PyExpression value = target.findAssignedValue(); assertNotNull(value); @@ -386,6 +384,11 @@ public class PyMultiFileResolveTest extends PyResolveTestCase { assertResolvesTo(PyFunction.class, "m1"); } + // PY-7026 + public void testFromImportStarReassignment() { + assertResolvesTo(PyFunction.class, "foo"); + } + private void prepareTestDirectory() { final String testName = getTestName(true); myFixture.copyDirectoryToProject(testName, ""); From ad37ddbc67a4efcd58702f160f23efd4d6ce288b Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 23 Jul 2012 21:03:38 +0400 Subject: [PATCH 5/8] Try to resolve a class-level name in the outer context if it exists, but it is not found in the latest defs (PY-6540) --- .../com/jetbrains/python/psi/impl/PyClassImpl.java | 2 +- .../psi/impl/references/PyReferenceImpl.java | 14 +++++++++++--- .../python/psi/resolve/PyResolveUtil.java | 5 +++-- .../jetbrains/python/psi/types/PyModuleType.java | 2 +- python/testData/resolve/ClassRedefinedField.py | 7 +++++++ .../com/jetbrains/python/PyResolveTest.java | 5 +++++ 6 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 python/testData/resolve/ClassRedefinedField.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index e67f44c05c4e..543260805f80 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -998,7 +998,7 @@ public class PyClassImpl extends PyPresentableElementImpl implement } } else { - PyResolveUtil.scopeCrawlUp(processor, this, this); + PyResolveUtil.scopeCrawlUp(processor, this, null, this); } return true; } 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 05922e81ed67..7369d4aa42ef 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java @@ -221,7 +221,15 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference if (!latest.isEmpty()) { return latest; } - if (!isCythonLevel(myElement)) { + if (owner instanceof PyClass) { + final ScopeOwner classOwner = ScopeUtil.getScopeOwner(owner); + if (classOwner != null) { + final ResolveProcessor outerProcessor = new ResolveProcessor(referencedName); + PyResolveUtil.scopeCrawlUp(outerProcessor, classOwner, referencedName, roof); + uexpr = outerProcessor.getResult(); + } + } + else if (!isCythonLevel(myElement)) { uexpr = null; } } @@ -511,7 +519,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference final CompletionVariantsProcessor processor = new CompletionVariantsProcessor(element); final ScopeOwner owner = realContext instanceof ScopeOwner ? (ScopeOwner)realContext : ScopeUtil.getScopeOwner(realContext); if (owner != null) { - PyResolveUtil.scopeCrawlUp(processor, owner, null); + PyResolveUtil.scopeCrawlUp(processor, owner, null, null); } // in a call, include function's arg names @@ -520,7 +528,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference // include builtin names final PyFile builtinsFile = PyBuiltinCache.getInstance(element).getBuiltinsFile(); if (builtinsFile != null) { - PyResolveUtil.scopeCrawlUp(processor, builtinsFile, null); + PyResolveUtil.scopeCrawlUp(processor, builtinsFile, null, null); } if (underscores >= 2) { diff --git a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java index b3b8d3273bde..bd696ee2751e 100644 --- a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java @@ -103,8 +103,9 @@ public class PyResolveUtil { scopeCrawlUp(processor, owner, originalOwner, name, roof); } - public static void scopeCrawlUp(@NotNull PsiScopeProcessor processor, @NotNull ScopeOwner scopeOwner, @Nullable PsiElement roof) { - scopeCrawlUp(processor, scopeOwner, scopeOwner, null, roof); + public static void scopeCrawlUp(@NotNull PsiScopeProcessor processor, @NotNull ScopeOwner scopeOwner, @Nullable String name, + @Nullable PsiElement roof) { + scopeCrawlUp(processor, scopeOwner, scopeOwner, name, roof); } private static void scopeCrawlUp(@NotNull PsiScopeProcessor processor, @Nullable ScopeOwner scopeOwner, diff --git a/python/src/com/jetbrains/python/psi/types/PyModuleType.java b/python/src/com/jetbrains/python/psi/types/PyModuleType.java index 9e5026bea2f6..3baebf8100bd 100644 --- a/python/src/com/jetbrains/python/psi/types/PyModuleType.java +++ b/python/src/com/jetbrains/python/psi/types/PyModuleType.java @@ -186,7 +186,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje @Override public void handleEvent(Event event, @Nullable Object associated) { } - }, owner, null); + }, owner, null, null); return visibleImports; } diff --git a/python/testData/resolve/ClassRedefinedField.py b/python/testData/resolve/ClassRedefinedField.py new file mode 100644 index 000000000000..a38216d8f86c --- /dev/null +++ b/python/testData/resolve/ClassRedefinedField.py @@ -0,0 +1,7 @@ +class Foo(object): + pass + +class Bar(object): + Foo = Foo +# + diff --git a/python/testSrc/com/jetbrains/python/PyResolveTest.java b/python/testSrc/com/jetbrains/python/PyResolveTest.java index d0fde0cc6b62..ae4a4eb87245 100644 --- a/python/testSrc/com/jetbrains/python/PyResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyResolveTest.java @@ -467,4 +467,9 @@ public class PyResolveTest extends PyResolveTestCase { public void testLambdaParameterInDefaultValue() { assertResolvesTo(PyNamedParameter.class, "xx"); } + + // PY-6540 + public void testClassRedefinedField() { + assertResolvesTo(PyClass.class, "Foo"); + } } From af7301f11c52fb3267cba86bef4b9d8c63e4b8cd Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 23 Jul 2012 22:36:22 +0400 Subject: [PATCH 6/8] Fixed false positive in unresolved references for qualified references of values returned by imported functions (PY-7022) --- .../inspections/PyUnresolvedReferencesInspection.java | 5 ++--- .../python/psi/impl/references/PyQualifiedReference.java | 2 +- .../ReturnedQualifiedReferenceUnionType/a.py | 8 ++++++++ .../ReturnedQualifiedReferenceUnionType/b.py | 5 +++++ .../inspections/PyUnresolvedReferencesInspectionTest.java | 5 +++++ 5 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/ReturnedQualifiedReferenceUnionType/a.py create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/ReturnedQualifiedReferenceUnionType/b.py diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java index a51d12ec7e3d..22eedc8d9084 100644 --- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java @@ -508,9 +508,8 @@ public class PyUnresolvedReferencesInspection extends PyInspection { registerProblem(point, description, hl_type, null, range, actions.toArray(new LocalQuickFix[actions.size()])); } - private static boolean ignoreUnresolvedMemberForType(PyType qtype, PsiReference reference, String refText) { - if (qtype instanceof PyNoneType || qtype instanceof PyTypeReference || - (qtype instanceof PyUnionType && ((PyUnionType)qtype).isWeak())) { + private static boolean ignoreUnresolvedMemberForType(@NotNull PyType qtype, PsiReference reference, String refText) { + if (qtype instanceof PyNoneType || PyTypeChecker.isUnknown(qtype)) { // this almost always means that we don't know the type, so don't show an error in this case return true; } diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java index ca621f8df4a1..dccce365d14b 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java @@ -84,7 +84,7 @@ public class PyQualifiedReference extends PyReferenceImpl { } } - if ((qualifierType == null || qualifierType instanceof PyTypeReference) && + if (PyTypeChecker.isUnknown(qualifierType) && myContext.allowImplicits() && canQualifyAnImplicitName(qualifier, qualifierType)) { addImplicitResolveResults(referencedName, ret); } diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/ReturnedQualifiedReferenceUnionType/a.py b/python/testData/inspections/PyUnresolvedReferencesInspection/ReturnedQualifiedReferenceUnionType/a.py new file mode 100644 index 000000000000..ac077d6faded --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/ReturnedQualifiedReferenceUnionType/a.py @@ -0,0 +1,8 @@ +from b import f, g + +def test(x): + if x > 0: + out = f() + else: + out = g() + out.startswith('foo') # pass \ No newline at end of file diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/ReturnedQualifiedReferenceUnionType/b.py b/python/testData/inspections/PyUnresolvedReferencesInspection/ReturnedQualifiedReferenceUnionType/b.py new file mode 100644 index 000000000000..6e8cf6cb5e4a --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/ReturnedQualifiedReferenceUnionType/b.py @@ -0,0 +1,5 @@ +def f(): + return 1 + +def g(): + return 'foo' diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index 30564a9e5020..21e7cfafe602 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -131,6 +131,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase { doMultiFileTest("a.py"); } + // PY-7022 + public void testReturnedQualifiedReferenceUnionType() { + doMultiFileTest("a.py"); + } + private void doTest() { myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py"); myFixture.enableInspections(PyUnresolvedReferencesInspection.class); From 45523931355d2f87ed4726c2ac259fd11e440678 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 24 Jul 2012 13:27:01 +0400 Subject: [PATCH 7/8] Don't show warnings for unused imports of sub-modules inside a package (PY-2668) --- .../PyUnresolvedReferencesInspection.java | 21 +++++++++++++++++-- .../UnusedImportsInPackage/a.py | 5 +++++ .../UnusedImportsInPackage/p1/__init__.py | 6 ++++++ .../UnusedImportsInPackage/p1/m1.py | 2 ++ .../PyUnresolvedReferencesInspectionTest.java | 5 +++++ 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/a.py create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/__init__.py create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/m1.py diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java index 22eedc8d9084..641deb5d0d13 100644 --- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java @@ -714,7 +714,14 @@ public class PyUnresolvedReferencesInspection extends PyInspection { Set unusedStatements = new HashSet(); final PyUnresolvedReferencesInspection suppressableInspection = new PyUnresolvedReferencesInspection(); + PyQualifiedName packageQName = null; for (NameDefiner unusedImport : unusedImports) { + if (packageQName == null) { + final PsiFile file = unusedImport.getContainingFile(); + if (file != null && PyUtil.isPackage(file)) { + packageQName = ResolveImportUtil.findShortestImportableQName(file); + } + } PyImportStatementBase importStatement = PsiTreeUtil.getParentOfType(unusedImport, PyImportStatementBase.class); if (importStatement != null && !unusedStatements.contains(importStatement) && !myUsedImports.contains(importStatement)) { if (suppressableInspection.isSuppressedFor(importStatement)) { @@ -736,14 +743,24 @@ public class PyUnresolvedReferencesInspection extends PyInspection { continue; } } + PsiFileSystemItem importedElement; if (unusedImport instanceof PyImportElement) { - if (ResolveImportUtil.resolveImportElement((PyImportElement)unusedImport) == null) { + final PsiElement element = ResolveImportUtil.resolveImportElement((PyImportElement)unusedImport); + if (element == null) { continue; } + importedElement = element.getContainingFile(); } else { assert importStatement instanceof PyFromImportStatement; - if (((PyFromImportStatement)importStatement).resolveImportSource() == null) { + importedElement = ((PyFromImportStatement)importStatement).resolveImportSource(); + if (importedElement == null) { + continue; + } + } + if (packageQName != null && importedElement instanceof PsiFileSystemItem) { + final PyQualifiedName importedQName = ResolveImportUtil.findShortestImportableQName(importedElement); + if (importedQName != null && importedQName.matchesPrefix(packageQName)) { continue; } } diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/a.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/a.py new file mode 100644 index 000000000000..5ce53ef9d963 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/a.py @@ -0,0 +1,5 @@ +def g(x): + return x + +def h(x): + return x \ No newline at end of file diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/__init__.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/__init__.py new file mode 100644 index 000000000000..4de71c372110 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/__init__.py @@ -0,0 +1,6 @@ +from .m1 import f +from p1.m1 import f +from m1 import f +from a import g, h + +__all__ = ['f', 'g'] diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/m1.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/m1.py new file mode 100644 index 000000000000..0bc52b1ebeb1 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/m1.py @@ -0,0 +1,2 @@ +def f(x): + pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index 21e7cfafe602..721e84436c9d 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -136,6 +136,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase { doMultiFileTest("a.py"); } + // PY-2668 + public void testUnusedImportsInPackage() { + doMultiFileTest("p1/__init__.py"); + } + private void doTest() { myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py"); myFixture.enableInspections(PyUnresolvedReferencesInspection.class); From 2f4bd0674e54fdeae887afccdc0e7b2ab3492a52 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 24 Jul 2012 14:01:33 +0400 Subject: [PATCH 8/8] Don't show warnings for unused imports listed in __all__ (PY-2668) --- .../inspections/PyUnresolvedReferencesInspection.java | 11 ++++++++++- .../UnusedImportsInPackage/p1/__init__.py | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java index 641deb5d0d13..b73e18e0641a 100644 --- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java @@ -715,9 +715,14 @@ public class PyUnresolvedReferencesInspection extends PyInspection { Set unusedStatements = new HashSet(); final PyUnresolvedReferencesInspection suppressableInspection = new PyUnresolvedReferencesInspection(); PyQualifiedName packageQName = null; + List dunderAll = null; + for (NameDefiner unusedImport : unusedImports) { if (packageQName == null) { final PsiFile file = unusedImport.getContainingFile(); + if (file instanceof PyFile) { + dunderAll = ((PyFile)file).getDunderAll(); + } if (file != null && PyUtil.isPackage(file)) { packageQName = ResolveImportUtil.findShortestImportableQName(file); } @@ -745,10 +750,14 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } PsiFileSystemItem importedElement; if (unusedImport instanceof PyImportElement) { - final PsiElement element = ResolveImportUtil.resolveImportElement((PyImportElement)unusedImport); + final PyImportElement importElement = (PyImportElement)unusedImport; + final PsiElement element = ResolveImportUtil.resolveImportElement(importElement); if (element == null) { continue; } + if (dunderAll != null && dunderAll.contains(importElement.getVisibleName())) { + continue; + } importedElement = element.getContainingFile(); } else { diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/__init__.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/__init__.py index 4de71c372110..b2d7ec0a430e 100644 --- a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/__init__.py +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/__init__.py @@ -1,6 +1,7 @@ from .m1 import f from p1.m1 import f from m1 import f -from a import g, h +from a import g +from a import h __all__ = ['f', 'g']