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 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/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/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; + } } } } 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/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java index a51d12ec7e3d..b73e18e0641a 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; } @@ -715,7 +714,19 @@ 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); + } + } PyImportStatementBase importStatement = PsiTreeUtil.getParentOfType(unusedImport, PyImportStatementBase.class); if (importStatement != null && !unusedStatements.contains(importStatement) && !myUsedImports.contains(importStatement)) { if (suppressableInspection.isSuppressedFor(importStatement)) { @@ -737,14 +748,28 @@ public class PyUnresolvedReferencesInspection extends PyInspection { continue; } } + PsiFileSystemItem importedElement; if (unusedImport instanceof PyImportElement) { - if (ResolveImportUtil.resolveImportElement((PyImportElement)unusedImport) == null) { + 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 { 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/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/PyQualifiedReference.java b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java index 824a4f7f8f6e..dccce365d14b 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; @@ -85,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); } @@ -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/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 1998b6bd11a4..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, @@ -112,26 +113,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/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"); 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/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/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/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..b2d7ec0a430e --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportsInPackage/p1/__init__.py @@ -0,0 +1,7 @@ +from .m1 import f +from p1.m1 import f +from m1 import f +from a import g +from a import 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/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/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, ""); 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"); + } } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index 30564a9e5020..721e84436c9d 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -131,6 +131,16 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase { doMultiFileTest("a.py"); } + // PY-7022 + public void testReturnedQualifiedReferenceUnionType() { + 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);