From e7f37924037abd501db5ae770efabcd7ddfde5f7 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 1 Feb 2012 19:18:54 +0400 Subject: [PATCH 1/6] Fixed completion of classobj attributes for old-style classes (PY-5486) --- .../python/psi/impl/PyBuiltinCache.java | 3 ++- .../jetbrains/python/psi/types/PyClassType.java | 10 +++++++++- .../completion/oldStyleClassAttributes.after.py | 4 ++++ .../completion/oldStyleClassAttributes.py | 4 ++++ .../jetbrains/python/PythonCompletionTest.java | 16 ++++++++++------ 5 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 python/testData/completion/oldStyleClassAttributes.after.py create mode 100644 python/testData/completion/oldStyleClassAttributes.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java index 98db7048c33c..3433def0bb46 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java +++ b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java @@ -18,6 +18,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.PsiManager; +import com.jetbrains.python.PyNames; import com.jetbrains.python.psi.LanguageLevel; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFile; @@ -287,7 +288,7 @@ public class PyBuiltinCache { @Nullable public PyClassType getOldstyleClassobjType() { - return getObjectType("___Classobj"); + return getObjectType(PyNames.FAKE_OLD_BASE); } @Nullable diff --git a/python/src/com/jetbrains/python/psi/types/PyClassType.java b/python/src/com/jetbrains/python/psi/types/PyClassType.java index 66ce6d565a39..d69580233a08 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassType.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassType.java @@ -256,6 +256,14 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType { addInheritedMembers(prefix, location, context, ret); + if (!myClass.isNewStyleClass()) { + final PyBuiltinCache cache = PyBuiltinCache.getInstance(myClass); + final PyClassType classobjType = cache.getOldstyleClassobjType(); + if (classobjType != null) { + ret.addAll(Arrays.asList(classobjType.getCompletionVariants(prefix, location, context))); + } + } + if (isDefinition() && myClass.isNewStyleClass()) { PyClassType typeType = PyBuiltinCache.getInstance(myClass).getObjectType("type"); if (typeType != null) { @@ -385,7 +393,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType { public String toString() { return (isValid() ? "" : "[INVALID] ") + "PyClassType: " + getClassQName(); } - + public boolean isValid() { return myClass == null || myClass.isValid(); } diff --git a/python/testData/completion/oldStyleClassAttributes.after.py b/python/testData/completion/oldStyleClassAttributes.after.py new file mode 100644 index 000000000000..ba7b7954de5e --- /dev/null +++ b/python/testData/completion/oldStyleClassAttributes.after.py @@ -0,0 +1,4 @@ +class C: + pass +c = C() +c.__class__ diff --git a/python/testData/completion/oldStyleClassAttributes.py b/python/testData/completion/oldStyleClassAttributes.py new file mode 100644 index 000000000000..03fdd87b8815 --- /dev/null +++ b/python/testData/completion/oldStyleClassAttributes.py @@ -0,0 +1,4 @@ +class C: + pass +c = C() +c.__cla diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java index d11717b76b48..f43db36aac12 100644 --- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java @@ -487,23 +487,23 @@ public class PythonCompletionTest extends PyTestCase { public void testImportKeyword() { doTest(); } - + public void testAssignedNearby() { doTest(); } - + public void testDunderAll() { doMultiFileTest(); } - + public void testAsName() { doMultiFileTest(); } - + public void testKeywordArgumentsForImplicitCall() { doTest(); } - + public void testTypeMembers() { // PY-5311 myFixture.configureByText(PythonFileType.INSTANCE, "a = 'string'\n" + "a."); @@ -512,8 +512,12 @@ public class PythonCompletionTest extends PyTestCase { final List strings = myFixture.getLookupElementStrings(); assertFalse(strings.contains("mro")); } - + public void testDunderAllReference() { // PY-5502 doTest(); } + + public void testOldStyleClassAttributes() { + doTest(); + } } From eb008837dee58c6ad8a568830e6ace0e14ae362a Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 2 Feb 2012 21:36:01 +0400 Subject: [PATCH 2/6] Fixed resolving implicit submodules of imported modules defined in the current file (PY-5621) Implicit submodules defined in other submodules are not taken into account currenty. --- .../PyUnresolvedReferencesInspection.java | 12 ++- .../python/psi/impl/PyImportedModule.java | 11 +++ .../psi/types/PyImportedModuleType.java | 20 ++-- .../python/psi/types/PyModuleType.java | 91 +++++++++++++------ .../unusedSubmodule/p1/__init__.py | 0 .../unusedImport/unusedSubmodule/p1/m1.py | 1 + .../unusedImport/unusedSubmodule/p1/m2.py | 1 + .../unusedImport/unusedSubmodule/test1.py | 3 + .../python/PyMultiFileResolveTest.java | 4 +- .../inspections/PyUnusedImportTest.java | 7 ++ 10 files changed, 112 insertions(+), 38 deletions(-) create mode 100644 python/testData/inspections/unusedImport/unusedSubmodule/p1/__init__.py create mode 100644 python/testData/inspections/unusedImport/unusedSubmodule/p1/m1.py create mode 100644 python/testData/inspections/unusedImport/unusedSubmodule/p1/m2.py create mode 100644 python/testData/inspections/unusedImport/unusedSubmodule/test1.py diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java index d5091e89667a..ee3136263982 100644 --- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java @@ -40,8 +40,9 @@ import com.jetbrains.python.console.PydevConsoleRunner; import com.jetbrains.python.documentation.DocStringParameterReference; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyBuiltinCache; -import com.jetbrains.python.psi.impl.references.PyImportReference; import com.jetbrains.python.psi.impl.PyImportStatementNavigator; +import com.jetbrains.python.psi.impl.PyImportedModule; +import com.jetbrains.python.psi.impl.references.PyImportReference; import com.jetbrains.python.psi.impl.references.PyOperatorReference; import com.jetbrains.python.psi.resolve.ImportedResolveResult; import com.jetbrains.python.psi.resolve.PyResolveContext; @@ -452,11 +453,16 @@ public class PyUnresolvedReferencesInspection extends PyInspection { private static boolean ignoreUnresolvedMemberForType(PyType qtype, PsiReference reference, String refText) { if (qtype instanceof PyNoneType || qtype instanceof PyTypeReference || - (qtype instanceof PyUnionType && ((PyUnionType)qtype).isWeak()) || - (qtype instanceof PyImportedModuleType)) { + (qtype instanceof PyUnionType && ((PyUnionType)qtype).isWeak())) { // this almost always means that we don't know the type, so don't show an error in this case return true; } + if (qtype instanceof PyImportedModuleType) { + PyImportedModule module = ((PyImportedModuleType)qtype).getImportedModule(); + if (module.resolve() == null) { + return true; + } + } if (qtype instanceof PyClassType) { PyClass cls = ((PyClassType)qtype).getPyClass(); if (cls != null) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyImportedModule.java b/python/src/com/jetbrains/python/psi/impl/PyImportedModule.java index 28fbeb3b8db7..3f03829cf0ba 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyImportedModule.java +++ b/python/src/com/jetbrains/python/psi/impl/PyImportedModule.java @@ -108,6 +108,17 @@ public class PyImportedModule extends LightElement implements NameDefiner { return super.getNavigationElement(); } + @Nullable + public PyFile resolve() { + if (myImportElement != null) { + final PsiElement result = PyUtil.turnDirIntoInit(ResolveImportUtil.resolveImportElement(myImportElement, myImportedPrefix)); + if (result instanceof PyFile) { + return (PyFile)result; + } + } + return null; + } + @Nullable private static PsiElement resolve(PyImportElement importElement, final PyQualifiedName prefix) { return PyUtil.turnDirIntoInit(ResolveImportUtil.resolveImportElement(importElement, prefix)); diff --git a/python/src/com/jetbrains/python/psi/types/PyImportedModuleType.java b/python/src/com/jetbrains/python/psi/types/PyImportedModuleType.java index 39ea6f0d148b..db94253afd46 100644 --- a/python/src/com/jetbrains/python/psi/types/PyImportedModuleType.java +++ b/python/src/com/jetbrains/python/psi/types/PyImportedModuleType.java @@ -2,18 +2,17 @@ package com.jetbrains.python.psi.types; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.psi.PsiElement; import com.intellij.util.ProcessingContext; import com.jetbrains.python.psi.AccessDirection; import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyImportElement; -import com.jetbrains.python.psi.impl.PyFileImpl; import com.jetbrains.python.psi.impl.PyImportedModule; import com.jetbrains.python.psi.impl.PyQualifiedName; -import com.jetbrains.python.psi.impl.ResolveResultList; import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.resolve.RatedResolveResult; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -22,19 +21,23 @@ import java.util.List; * @author yole */ public class PyImportedModuleType implements PyType { - private PyImportedModule myImportedModule; + @NotNull private PyImportedModule myImportedModule; - public PyImportedModuleType(PyImportedModule importedModule) { + public PyImportedModuleType(@NotNull PyImportedModule importedModule) { myImportedModule = importedModule; } - @NotNull + @Nullable + @Override public List resolveMember(String name, PyExpression location, AccessDirection direction, PyResolveContext resolveContext) { - final PsiElement element = myImportedModule.getElementNamed(name); - return ResolveResultList.to(element); + final PyFile file = myImportedModule.resolve(); + if (file != null) { + return new PyModuleType(file).resolveMember(name, location, direction, resolveContext); + } + return null; } public Object[] getCompletionVariants(String completionPrefix, PyExpression location, ProcessingContext context) { @@ -63,6 +66,7 @@ public class PyImportedModuleType implements PyType { return false; // no module can be imported from builtins } + @NotNull public PyImportedModule getImportedModule() { return myImportedModule; } diff --git a/python/src/com/jetbrains/python/psi/types/PyModuleType.java b/python/src/com/jetbrains/python/psi/types/PyModuleType.java index 50a264d063e8..da0742d244c4 100644 --- a/python/src/com/jetbrains/python/psi/types/PyModuleType.java +++ b/python/src/com/jetbrains/python/psi/types/PyModuleType.java @@ -5,13 +5,17 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.*; +import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ProcessingContext; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.PyDynamicMember; +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.PyQualifiedName; import com.jetbrains.python.psi.impl.ResolveResultList; @@ -42,6 +46,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje } @Nullable + @Override public List resolveMember(final String name, @Nullable PyExpression location, AccessDirection direction, @@ -57,36 +62,70 @@ public class PyModuleType implements PyType { // Modules don't descend from obje return ResolveResultList.to(attribute); } if (location != null && isPackage(myModule)) { - final PsiFile file = location.getContainingFile(); - if (file instanceof PyFile) { - final PyQualifiedName packageQName = ResolveImportUtil.findCanonicalImportPath(myModule, location); - if (packageQName != null) { - final List imports = ((PyFile)file).getImportTargets(); - for (PyImportElement importElement : imports) { - final PyStatement stmt = importElement.getContainingImportStatement(); - PyQualifiedName importedQName = null; - if (stmt instanceof PyFromImportStatement) { - importedQName = ((PyFromImportStatement)stmt).getImportSourceQName(); - } - else if (stmt instanceof PyImportStatement) { - importedQName = importElement.getImportedQName(); - } - final PyQualifiedName submoduleQName = packageQName.append(name); - if (importedQName != null && importedQName.matchesPrefix(submoduleQName)) { - final PsiElement submodule = ResolveImportUtil.resolveChild(myModule, name, myModule, null, null, false, true); - if (submodule != null) { - final ResolveResultList results = new ResolveResultList(); - results.poke(submodule, RatedResolveResult.RATE_NORMAL); - results.add(new ImportedResolveResult(submodule, RatedResolveResult.RATE_LOW, - Collections.singletonList(importElement))); - return results; - } - } + return resolveImplicitPackageMember(name, location); + } + return null; + } + + @Nullable + private List resolveImplicitPackageMember(@NotNull String name, @NotNull PyExpression location) { + final ScopeOwner owner = ScopeUtil.getScopeOwner(location); + final PyQualifiedName packageQName = ResolveImportUtil.findCanonicalImportPath(myModule, location); + if (owner != null && packageQName != null) { + for (PyImportElement importElement : getVisibleImports(owner)) { + final PyStatement stmt = importElement.getContainingImportStatement(); + PyQualifiedName importedQName = null; + PyQualifiedName implicitSubmoduleQName = null; + if (stmt instanceof PyFromImportStatement) { + final PyFromImportStatement fromImportStatement = (PyFromImportStatement)stmt; + importedQName = fromImportStatement.getImportSourceQName(); + final String visibleName = importElement.getVisibleName(); + if (importedQName != null) { + implicitSubmoduleQName = importedQName.append(visibleName); + } + } + else if (stmt instanceof PyImportStatement) { + importedQName = importElement.getImportedQName(); + } + final PyQualifiedName resolvedQName = packageQName.append(name); + if ((importedQName != null && importedQName.matchesPrefix(resolvedQName)) || + (implicitSubmoduleQName != null && implicitSubmoduleQName.equals(resolvedQName))) { + final PsiElement submodule = ResolveImportUtil.resolveChild(myModule, name, myModule, null, null, false, true); + if (submodule != null) { + final ResolveResultList results = new ResolveResultList(); + results.add(new ImportedResolveResult(submodule, RatedResolveResult.RATE_NORMAL, + Collections.singletonList(importElement))); + return results; } } } } - return Collections.emptyList(); + return null; + } + + @NotNull + private static List getVisibleImports(@NotNull ScopeOwner owner) { + final List visibleImports = new ArrayList(); + PyResolveUtil.scopeCrawlUp(new PsiScopeProcessor() { + @Override + public boolean execute(PsiElement element, ResolveState state) { + if (element instanceof PyImportElement) { + visibleImports.add((PyImportElement)element); + } + return true; + } + + @Nullable + @Override + public T getHint(Key hintKey) { + return null; + } + + @Override + public void handleEvent(Event event, @Nullable Object associated) { + } + }, owner, null); + return visibleImports; } private static boolean isPackage(@NotNull PyFile file) { diff --git a/python/testData/inspections/unusedImport/unusedSubmodule/p1/__init__.py b/python/testData/inspections/unusedImport/unusedSubmodule/p1/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/inspections/unusedImport/unusedSubmodule/p1/m1.py b/python/testData/inspections/unusedImport/unusedSubmodule/p1/m1.py new file mode 100644 index 000000000000..a43e3eb876c1 --- /dev/null +++ b/python/testData/inspections/unusedImport/unusedSubmodule/p1/m1.py @@ -0,0 +1 @@ +a1 = 42 \ No newline at end of file diff --git a/python/testData/inspections/unusedImport/unusedSubmodule/p1/m2.py b/python/testData/inspections/unusedImport/unusedSubmodule/p1/m2.py new file mode 100644 index 000000000000..97f0eb4ade34 --- /dev/null +++ b/python/testData/inspections/unusedImport/unusedSubmodule/p1/m2.py @@ -0,0 +1 @@ +a2 = -1 \ No newline at end of file diff --git a/python/testData/inspections/unusedImport/unusedSubmodule/test1.py b/python/testData/inspections/unusedImport/unusedSubmodule/test1.py new file mode 100644 index 000000000000..40e9e79d3ac1 --- /dev/null +++ b/python/testData/inspections/unusedImport/unusedSubmodule/test1.py @@ -0,0 +1,3 @@ +import p1.m1 + +print(p1.m2.a2) diff --git a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java index 033161b369f4..70d073855f2a 100644 --- a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java @@ -189,7 +189,9 @@ public class PyMultiFileResolveTest extends PyResolveTestCase { assertResolvesTo(PyFunction.class, "do_stuff"); } - public void testReimportExported() { + // PY-1153 + // TODO: This case requires collecting transitive imports in all imported submodules + public void _testReimportExported() { assertResolvesTo(PyFunction.class, "dostuff"); } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnusedImportTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnusedImportTest.java index 66772bb03d55..820e18277352 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnusedImportTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnusedImportTest.java @@ -24,4 +24,11 @@ public class PyUnusedImportTest extends PyTestCase { myFixture.enableInspections(PyUnresolvedReferencesInspection.class); myFixture.testHighlighting(true, false, false, "test1.py"); } + + // PY-5621 + public void testUnusedSubmodule() { + myFixture.copyDirectoryToProject("inspections/unusedImport/unusedSubmodule", ""); + myFixture.enableInspections(PyUnresolvedReferencesInspection.class); + myFixture.testHighlighting(true, false, false, "test1.py"); + } } From 483ca465b0ba26bf5f4fe5486ff8b0a83dc3c2f1 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 3 Feb 2012 16:11:41 +0400 Subject: [PATCH 3/6] Fixed PIEAE in PsiElementBase.getContainingFile (EA-32594) --- .../python/codeInsight/stdlib/PyStdlibTypeProvider.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java index 3c11a9623403..ea3108fbdda9 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java @@ -197,6 +197,9 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase { @Nullable private static String getQualifiedName(@NotNull PyFunction f, @Nullable PsiElement callSite) { + if (!f.isValid()) { + return null; + } String result = f.getName(); final PyClass c = f.getContainingClass(); final VirtualFile vfile = f.getContainingFile().getVirtualFile(); From 524695f05bcdc96d27471d1c79b98225916fbb6c Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 3 Feb 2012 16:19:35 +0400 Subject: [PATCH 4/6] Fixed Fixed PIEAE in PsiElementBase.getContainingFile (EA-33461) --- .../python/psi/impl/PyClassImpl.java | 3 +++ .../python/psi/impl/PyFunctionImpl.java | 24 ++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 549b33f0b92e..04479f6d8b64 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -638,6 +638,9 @@ public class PyClassImpl extends PyPresentableElementImpl implement @Nullable private Property scanProperties(@Nullable String name, @Nullable Processor filter, boolean inherited) { + if (!isValid()) { + return null; + } LanguageLevel level = LanguageLevel.getDefault(); // EA-32381: A tree-based instance may not have a parent element somehow, so getContainingFile() may be not appropriate final PsiFile file = getParentByStub() != null ? getContainingFile() : null; diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 3bb8bd41b4e9..399b4d82d2d6 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -83,18 +83,20 @@ public class PyFunctionImpl extends PyPresentableElementImpl imp @Override public Icon getIcon(int flags) { - final Property property = getProperty(); - if (property != null) { - if (property.getGetter().valueOrNull() == this) { - return PROPERTY_GETTER; + if (isValid()) { + final Property property = getProperty(); + if (property != null) { + if (property.getGetter().valueOrNull() == this) { + return PROPERTY_GETTER; + } + if (property.getSetter().valueOrNull() == this) { + return PROPERTY_SETTER; + } + if (property.getDeleter().valueOrNull() == this) { + return PROPERTY_DELETER; + } + return PlatformIcons.PROPERTY_ICON; } - if (property.getSetter().valueOrNull() == this) { - return PROPERTY_SETTER; - } - if (property.getDeleter().valueOrNull() == this) { - return PROPERTY_DELETER; - } - return PlatformIcons.PROPERTY_ICON; } return PlatformIcons.METHOD_ICON; } From 97119b358e9e9bd24321f04089a4da0bceb16045 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 3 Feb 2012 16:26:30 +0400 Subject: [PATCH 5/6] Fixed PIEAE in PyTargetExpressionImpl.findAssignedValue (EA-32560) --- .../python/psi/impl/PyTargetExpressionImpl.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java index 278ab870efdb..a46630218648 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java @@ -335,12 +335,14 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl> mapping = assignment.getTargetsToValuesMapping(); - for (Pair pair : mapping) { - PyExpression assigned_to = pair.getFirst(); - if (assigned_to == this) return pair.getSecond(); + if (isValid()) { + PyAssignmentStatement assignment = PsiTreeUtil.getParentOfType(this, PyAssignmentStatement.class); + if (assignment != null) { + List> mapping = assignment.getTargetsToValuesMapping(); + for (Pair pair : mapping) { + PyExpression assigned_to = pair.getFirst(); + if (assigned_to == this) return pair.getSecond(); + } } } return null; From 240f28f0fe0338138bbdc50c51e84460c9b56ccf Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 3 Feb 2012 16:33:56 +0400 Subject: [PATCH 6/6] Additional diagnostics for determining Python's sys.path errors (EA-32393) --- .../jetbrains/python/sdk/PythonSdkType.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index d4b4333f1953..aaf0e52805cf 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -495,7 +495,7 @@ public class PythonSdkType extends SdkType { } // Add folders from sys.path final List paths = getSysPath(bin_path); - if ((paths != null) && paths.size() > 0) { + if (paths.size() > 0) { // add every path as root. for (String path : paths) { if (!path.contains(sep)) continue; // TODO: interpret possible 'special' paths reasonably @@ -575,14 +575,12 @@ public class PythonSdkType extends SdkType { return PathManager.getSystemPath() + File.separator + SKELETON_DIR_NAME; } - @Nullable + @NotNull public static List getSysPath(String bin_path) { String working_dir = new File(bin_path).getParent(); Application application = ApplicationManager.getApplication(); if (application != null && !application.isUnitTestMode()) { - final List paths = getSysPathsFromScript(bin_path); - if (paths == null) throw new InvalidSdkException("Failed to determine Python's sys.path value"); - return paths; + return getSysPathsFromScript(bin_path); } else { // mock sdk List ret = new ArrayList(1); @@ -591,8 +589,7 @@ public class PythonSdkType extends SdkType { } } - - @Nullable + @NotNull protected static List getSysPathsFromScript(String bin_path) { String scriptFile = PythonHelpersLocator.getHelperPath("syspath.py"); // to handle the situation when PYTHONPATH contains ., we need to run the syspath script in the @@ -603,7 +600,12 @@ public class PythonSdkType extends SdkType { new String[]{bin_path, scriptFile}, add_environment, MINUTE ); - return run_result.checkSuccess(LOG) ? run_result.getStdoutLines() : null; + if (!run_result.checkSuccess(LOG)) { + throw new InvalidSdkException(String.format("Failed to determine Python's sys.path value:\nSTDOUT: %s\nSTDERR: %s", + run_result.getStdout(), + run_result.getStderr())); + } + return run_result.getStdoutLines(); } // Returns a piece of env good as additional env for getProcessOutput.