From 68608222e9b0bd7d03c51c9dcab76531b9e84d1e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 5 Jun 2012 18:43:27 +0400 Subject: [PATCH 01/13] notnull --- .../jetbrains/python/codeInsight/PyDunderAllReference.java | 4 ++-- python/src/com/jetbrains/python/psi/impl/PyClassImpl.java | 4 ++-- python/src/com/jetbrains/python/psi/impl/PyFileImpl.java | 4 ++-- .../python/psi/resolve/AssignmentCollectProcessor.java | 4 ++-- .../com/jetbrains/python/psi/resolve/CollectProcessor.java | 4 ++-- .../com/jetbrains/python/psi/resolve/ResolveProcessor.java | 4 ++-- .../com/jetbrains/python/psi/resolve/VariantsProcessor.java | 5 +++-- python/src/com/jetbrains/python/psi/types/PyModuleType.java | 4 ++-- 8 files changed, 17 insertions(+), 16 deletions(-) diff --git a/python/src/com/jetbrains/python/codeInsight/PyDunderAllReference.java b/python/src/com/jetbrains/python/codeInsight/PyDunderAllReference.java index 3e8937006fa1..ce3b41999065 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyDunderAllReference.java +++ b/python/src/com/jetbrains/python/codeInsight/PyDunderAllReference.java @@ -50,7 +50,7 @@ public class PyDunderAllReference extends PsiReferenceBase dunderAll = containingFile.getDunderAll(); containingFile.processDeclarations(new PsiScopeProcessor() { @Override - public boolean execute(PsiElement element, ResolveState state) { + public boolean execute(@NotNull PsiElement element, ResolveState state) { if (element instanceof PsiNamedElement && !(element instanceof LightNamedElement)) { final String name = ((PsiNamedElement)element).getName(); if (name != null && PyUtil.getInitialUnderscores(name) == 0 && (dunderAll == null || !dunderAll.contains(name))) { @@ -67,7 +67,7 @@ public class PyDunderAllReference extends PsiReferenceBase T getHint(Key hintKey) { + public T getHint(@NotNull Key hintKey) { return null; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 83a6bb7ff367..e67f44c05c4e 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -898,7 +898,7 @@ public class PyClassImpl extends PyPresentableElementImpl implement else if (anchor != null) { PyResolveUtil.scopeCrawlUp(new PsiScopeProcessor() { @Override - public boolean execute(PsiElement element, ResolveState state) { + public boolean execute(@NotNull PsiElement element, ResolveState state) { if (element instanceof PyAssignmentStatement) { collectNewTargets(result, (PyAssignmentStatement)element); } @@ -907,7 +907,7 @@ public class PyClassImpl extends PyPresentableElementImpl implement @Nullable @Override - public T getHint(Key hintKey) { + public T getHint(@NotNull Key hintKey) { return null; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java index 35512c774fac..c4cb65183383 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java @@ -326,7 +326,7 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { final List remainingDunderAll = dunderAll == null ? null : new ArrayList(dunderAll); PsiScopeProcessor wrapper = new PsiScopeProcessor() { @Override - public boolean execute(PsiElement element, ResolveState state) { + public boolean execute(@NotNull PsiElement element, ResolveState state) { if (!processor.execute(element, state)) return false; if (remainingDunderAll != null && element instanceof PyElement) { remainingDunderAll.remove(((PyElement) element).getName()); @@ -335,7 +335,7 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { } @Override - public T getHint(Key hintKey) { + public T getHint(@NotNull Key hintKey) { return processor.getHint(hintKey); } diff --git a/python/src/com/jetbrains/python/psi/resolve/AssignmentCollectProcessor.java b/python/src/com/jetbrains/python/psi/resolve/AssignmentCollectProcessor.java index b7f374c84a6b..ff01a27fb339 100644 --- a/python/src/com/jetbrains/python/psi/resolve/AssignmentCollectProcessor.java +++ b/python/src/com/jetbrains/python/psi/resolve/AssignmentCollectProcessor.java @@ -34,7 +34,7 @@ public class AssignmentCollectProcessor implements PsiScopeProcessor { mySeenNames = new HashSet(); } - public boolean execute(final PsiElement element, final ResolveState state) { + public boolean execute(@NotNull final PsiElement element, final ResolveState state) { if (element instanceof PyAssignmentStatement) { final PyAssignmentStatement assignment = (PyAssignmentStatement)element; for (PyExpression ex : assignment.getTargets()) { @@ -69,7 +69,7 @@ public class AssignmentCollectProcessor implements PsiScopeProcessor { return myResult; } - public T getHint(final Key hintKey) { + public T getHint(@NotNull final Key hintKey) { return null; } diff --git a/python/src/com/jetbrains/python/psi/resolve/CollectProcessor.java b/python/src/com/jetbrains/python/psi/resolve/CollectProcessor.java index 368dbff72957..8ff69dfcad6d 100644 --- a/python/src/com/jetbrains/python/psi/resolve/CollectProcessor.java +++ b/python/src/com/jetbrains/python/psi/resolve/CollectProcessor.java @@ -18,14 +18,14 @@ public class CollectProcessor implements PyClassScopeProcessor { myResult = new ArrayList(); } - public boolean execute(final PsiElement element, final ResolveState state) { + public boolean execute(@NotNull final PsiElement element, final ResolveState state) { if (myTargetTokenSet.contains(element.getNode().getElementType())) { myResult.add(element); } return true; // collect till we drop } - public T getHint(final Key hintKey) { + public T getHint(@NotNull final Key hintKey) { return null; } diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveProcessor.java b/python/src/com/jetbrains/python/psi/resolve/ResolveProcessor.java index c2ec399ef351..ff96a2e379a9 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveProcessor.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveProcessor.java @@ -48,7 +48,7 @@ public class ResolveProcessor implements PsiScopeProcessor { return PyUtil.nvl(myName) + ", " + PyUtil.nvl(myResult); } - public boolean execute(PsiElement element, ResolveState substitutor) { + public boolean execute(@NotNull PsiElement element, ResolveState substitutor) { if (element instanceof PyFile) { final VirtualFile file = ((PyFile)element).getVirtualFile(); if (file != null) { @@ -139,7 +139,7 @@ public class ResolveProcessor implements PsiScopeProcessor { } @Nullable - public T getHint(Key hintKey) { + public T getHint(@NotNull Key hintKey) { return null; } diff --git a/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java b/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java index 4246bd0aaa4f..6c737bee2b75 100644 --- a/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java +++ b/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java @@ -9,6 +9,7 @@ import com.intellij.psi.ResolveState; import com.intellij.psi.scope.PsiScopeProcessor; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyQualifiedName; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -48,7 +49,7 @@ public abstract class VariantsProcessor implements PsiScopeProcessor { } - public boolean execute(PsiElement element, ResolveState substitutor) { + public boolean execute(@NotNull PsiElement element, ResolveState substitutor) { if (myNodeFilter != null && !myNodeFilter.value(element)) return true; // skip whatever the filter rejects // TODO: refactor to look saner; much code duplication if (element instanceof PsiNamedElement) { @@ -129,7 +130,7 @@ public abstract class VariantsProcessor implements PsiScopeProcessor { } @Nullable - public T getHint(Key hintKey) { + public T getHint(@NotNull Key hintKey) { return null; } diff --git a/python/src/com/jetbrains/python/psi/types/PyModuleType.java b/python/src/com/jetbrains/python/psi/types/PyModuleType.java index 74e75957e946..53b65d57de0a 100644 --- a/python/src/com/jetbrains/python/psi/types/PyModuleType.java +++ b/python/src/com/jetbrains/python/psi/types/PyModuleType.java @@ -167,7 +167,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje final List visibleImports = new ArrayList(); PyResolveUtil.scopeCrawlUp(new PsiScopeProcessor() { @Override - public boolean execute(PsiElement element, ResolveState state) { + public boolean execute(@NotNull PsiElement element, ResolveState state) { if (element instanceof PyImportElement) { visibleImports.add((PyImportElement)element); } @@ -176,7 +176,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje @Nullable @Override - public T getHint(Key hintKey) { + public T getHint(@NotNull Key hintKey) { return null; } From 928fea491fbf3bad5261cd78c173ccc764725858 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Sat, 9 Jun 2012 21:07:09 +0400 Subject: [PATCH 02/13] mouseClicked() mostly replaced with ClickListener and DoubleClickListener, since original mouseClicked doesn't respect minor movements between press and release. --- .../python/packaging/ui/PyPackagesPanel.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java b/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java index 0336c9c7a968..c56dd4fe5b9d 100644 --- a/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java +++ b/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java @@ -8,6 +8,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.ui.Messages; +import com.intellij.ui.DoubleClickListener; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.table.JBTable; import com.intellij.util.Consumer; @@ -28,7 +29,6 @@ import javax.swing.table.TableCellRenderer; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import java.net.URL; @@ -122,25 +122,26 @@ public class PyPackagesPanel extends JPanel { } }); - myPackagesTable.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - if (mySelectedSdk != null && myInstallButton.isEnabled()) { - ManagePackagesDialog dialog = new ManagePackagesDialog(myProject, mySelectedSdk, PyPackagesPanel.this); - Point p = e.getPoint(); - int row = myPackagesTable.rowAtPoint(p); - int column = myPackagesTable.columnAtPoint(p); - if (row >= 0 && column >= 0) { - Object pyPackage = myPackagesTable.getValueAt(row, 0); - if (pyPackage instanceof PyPackage) { - dialog.setSelected(((PyPackage)pyPackage).getName()); - } + new DoubleClickListener() { + @Override + protected boolean onDoubleClick(MouseEvent e) { + if (mySelectedSdk != null && myInstallButton.isEnabled()) { + ManagePackagesDialog dialog = new ManagePackagesDialog(myProject, mySelectedSdk, PyPackagesPanel.this); + Point p = e.getPoint(); + int row = myPackagesTable.rowAtPoint(p); + int column = myPackagesTable.columnAtPoint(p); + if (row >= 0 && column >= 0) { + Object pyPackage = myPackagesTable.getValueAt(row, 0); + if (pyPackage instanceof PyPackage) { + dialog.setSelected(((PyPackage)pyPackage).getName()); } - dialog.show(); } + dialog.show(); + return true; } + return false; } - }); + }.installOn(myPackagesTable); myNotificationArea.addLinkHandler(INSTALL_DISTRIBUTE, new Runnable() { @Override From 093274e2287f2248f62aaa0e129df7c8f6e83e16 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 11 Jun 2012 09:19:17 +0200 Subject: [PATCH 03/13] delete old-style resolve of exported names and some other code which isn't used any more --- .../jetbrains/python/psi/impl/PyFileImpl.java | 157 +----------------- 1 file changed, 5 insertions(+), 152 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java index c4cb65183383..4f817901fcc5 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java @@ -3,17 +3,12 @@ package com.jetbrains.python.psi.impl; import com.intellij.extapi.psi.PsiFileBase; import com.intellij.lang.Language; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider; -import com.intellij.psi.util.CachedValue; -import com.intellij.psi.util.CachedValueProvider; -import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; @@ -33,20 +28,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.lang.ref.SoftReference; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { protected PyType myType; private ThreadLocal> myFindExportedNameStack = new ArrayListThreadLocal(); - private final CachedValue> myImportTargetsTransitive; //private volatile Boolean myAbsoluteImportEnabled; private final Map myFutureFeatures; private List myDunderAll; private boolean myDunderAllCalculated; - private final Map> myExportedNames = new ConcurrentHashMap>(); private volatile ExportedNameCache myExportedNameCache; private final PsiModificationTracker myModificationTracker; @@ -231,12 +222,6 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { public PyFileImpl(FileViewProvider viewProvider, Language language) { super(viewProvider, language); - myImportTargetsTransitive = CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider>() { - @Override - public Result> compute() { - return new Result>(calculateImportTargetsTransitive(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); - } - }, false); myFutureFeatures = new HashMap(); myModificationTracker = PsiModificationTracker.SERVICE.getInstance(getProject()); } @@ -411,36 +396,18 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { @Nullable public PsiElement findExportedName(String name) { - if (!Registry.is("python.exported.names.local.cache")) { - final SoftReference ref = myExportedNames.get(name); - if (ref != null) { - final PsiElement result = ref.get(); - if (result != null) { - return result; - } - } - } - final List stack = myFindExportedNameStack.get(); if (stack.contains(name)) { return null; } stack.add(name); try { - if (Registry.is("python.exported.names.local.cache")) { - if (myExportedNameCache == null) { - myExportedNameCache = new ExportedNameCache(); - } - PsiElement result = myExportedNameCache.resolve(name); - if (result != null) { - return result; - } + if (myExportedNameCache == null) { + myExportedNameCache = new ExportedNameCache(); } - else { - final PsiElement result = findExportedNameOldStyle(name); - if (result != null) { - return result; - } + PsiElement result = myExportedNameCache.resolve(name); + if (result != null) { + return result; } List allNames = getDunderAll(); if (allNames != null && allNames.contains(name)) { @@ -453,81 +420,6 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { } } - private PsiElement findExportedNameOldStyle(String name) { - final List children = PyPsiUtils.collectAllStubChildren(this, getStub()); - final List exceptParts = new ArrayList(); - for (int i=children.size()-1; i >= 0; i--) { - ProgressManager.checkCanceled(); - PsiElement child = children.get(i); - if (child instanceof PyExceptPart) { - exceptParts.add((PyExceptPart) child); - } - else { - PsiElement element = findNameInStub(child, name); - if (element != null) { - myExportedNames.put(name, new SoftReference(element)); - return element; - } - } - } - for (int i = exceptParts.size() - 1; i >= 0; i--) { - ProgressManager.checkCanceled(); - PyExceptPart part = exceptParts.get(i); - final List exceptChildren = PyPsiUtils.collectAllStubChildren(part, part.getStub()); - for (int j = exceptChildren.size() - 1; j >= 0; j--) { - PsiElement child = exceptChildren.get(j); - PsiElement element = findNameInStub(child, name); - if (element != null) { - myExportedNames.put(name, new SoftReference(element)); - return element; - } - } - } - return null; - } - - @Nullable - private PsiElement findNameInStub(PsiElement child, String name) { - if (child instanceof PsiNamedElement && name.equals(((PsiNamedElement)child).getName())) { - return child; - } - else if (child instanceof PyFromImportStatement) { - return findNameInFromImportStatement(name, (PyFromImportStatement)child); - } - else if (child instanceof PyImportStatement) { - return findNameInImportStatement(name, (PyImportStatement)child); - } - return null; - } - - @Nullable - private PsiElement findNameInFromImportStatement(String name, PyFromImportStatement statement) { - if (statement.isStarImport()) { - return findNameInStarImport(name, statement); - } - else { - for (PyImportElement importElement : statement.getImportElements()) { - if (name.equals(importElement.getVisibleName())) { - final PsiElement resolved = importElement.getElementNamed(name); - if (resolved != null) { - return resolved; - } - } - } - } - // http://stackoverflow.com/questions/6048786/from-module-import-in-init-py-makes-module-name-visible - if (PyNames.INIT_DOT_PY.equals(getName())) { - final PyQualifiedName qName = statement.getImportSourceQName(); - if (qName != null && qName.endsWith(name)) { - final PsiElement element = PyUtil.turnInitIntoDir(statement.resolveImportSource()); - if (element != null && element.getParent() == getContainingDirectory()) { - return element; - } - } - } - return null; - } - @Nullable private PsiElement findNameInStarImport(String name, PyFromImportStatement statement) { if (PyUtil.isClassPrivateName(name)) { @@ -556,17 +448,6 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { return null; } - @Nullable - private PsiElement findNameInImportStatement(String name, PyImportStatement child) { - for (PyImportElement importElement: child.getImportElements()) { - final PsiElement result = findNameInImportElement(name, importElement, false); - if (result != null) { - return result; - } - } - return null; - } - @Nullable private PsiElement findNameInImportElement(String name, PyImportElement importElement, final boolean resolveImportElement) { final PsiElement result = importElement.getElementNamed(name, resolveImportElement); @@ -625,33 +506,6 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { return ret; } - public List getImportTargetsTransitive() { - return myImportTargetsTransitive.getValue(); - } - - private List calculateImportTargetsTransitive() { - Set visitedFiles = new HashSet(); - visitedFiles.add(this); - List result = new ArrayList(); - calculateImportTargetsRecursive(this, visitedFiles, result); - return result; - } - - private static void calculateImportTargetsRecursive(PyFileImpl pyFile, Set visitedFiles, List result) { - final List imports = pyFile.getImportTargets(); - for (PyImportElement anImport : imports) { - result.add(anImport); - final PsiElement resolveResult = ResolveImportUtil.resolveImportElement(anImport); - if (resolveResult instanceof PyFileImpl) { - PyFileImpl file = (PyFileImpl) resolveResult; - if (!visitedFiles.contains(file)) { - visitedFiles.add(file); - calculateImportTargetsRecursive((PyFileImpl) resolveResult, visitedFiles, result); - } - } - } - } - public List getFromImports() { return PyPsiUtils.collectStubChildren(this, getStub(), PyElementTypes.FROM_IMPORT_STATEMENT, PyFromImportStatement.class); } @@ -814,7 +668,6 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { ControlFlowCache.clear(this); myDunderAllCalculated = false; myFutureFeatures.clear(); // probably no need to synchronize - myExportedNames.clear(); myExportedNameCache = null; } From 4606d8466a4b1dbe910f6af0485675218b55ed40 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 11 Jun 2012 11:59:37 +0200 Subject: [PATCH 04/13] more assertions for EA-35463 - PIEAE: TypeEvalContext.getType --- .../src/com/jetbrains/python/psi/impl/PyBuiltinCache.java | 7 ++++--- .../src/com/jetbrains/python/psi/impl/PyFunctionImpl.java | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java index af06d7f8ba71..d379a505ecfa 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java +++ b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java @@ -197,9 +197,6 @@ public class PyBuiltinCache { private final Map> myStdlibTypeCache = new HashMap>(); private long myModStamp = -1; - /** - @return - */ @Nullable public PyClassType getObjectType(@NonNls String name) { PyClassType val; @@ -216,11 +213,15 @@ public class PyBuiltinCache { PyClass cls = getClass(name); if (cls != null) { // null may happen during testing val = new PyClassType(cls, false); + val.assertValid(name); synchronized (myTypeCache) { myTypeCache.put(name, val); } } } + else { + val.assertValid(name); + } return val; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 4f44de8b9a9e..89cdbd62caac 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -195,11 +195,13 @@ public class PyFunctionImpl extends PyPresentableElementImpl imp for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { final PyType returnType = typeProvider.getReturnType(this, callSite, typeEvalContext); if (returnType != null) { + returnType.assertValid(typeProvider.toString()); return returnType; } } final PyType docStringType = getReturnTypeFromDocString(); if (docStringType != null) { + docStringType.assertValid("from docstring"); return docStringType; } if (typeEvalContext.allowReturnTypes(this)) { From 7e31a87b53eb00b65f7c62ca933938959d42361e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 11 Jun 2012 14:02:59 +0200 Subject: [PATCH 05/13] diagnostics for EA-36209 --- .../com/jetbrains/python/psi/resolve/VariantsProcessor.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java b/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java index 6c737bee2b75..ff4339cd951b 100644 --- a/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java +++ b/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java @@ -4,6 +4,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiInvalidElementAccessException; import com.intellij.psi.PsiNamedElement; import com.intellij.psi.ResolveState; import com.intellij.psi.scope.PsiScopeProcessor; @@ -78,7 +79,10 @@ public abstract class VariantsProcessor implements PsiScopeProcessor { final NameDefiner definer = (NameDefiner)element; for (PyElement expr : definer.iterateNames()) { if (expr != null && expr != myContext) { // NOTE: maybe rather have SingleIterables skip nulls outright? - String referencedName = expr instanceof PyFile ? FileUtil.getNameWithoutExtension(((PyFile) expr).getName()) : expr.getName(); + if (!expr.isValid()) { + throw new PsiInvalidElementAccessException(expr, "Definer: " + definer); + } + String referencedName = expr instanceof PyFile ? FileUtil.getNameWithoutExtension(((PyFile)expr).getName()) : expr.getName(); if (referencedName != null && nameIsAcceptable(referencedName)) { addImportedElement(referencedName, definer, expr); } From 52def9db361a1b9188cc9dcde81ff9d7f0784d9f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 11 Jun 2012 14:15:28 +0200 Subject: [PATCH 06/13] don't return null from element generator on invalid text, throw detailed message instead (EA-33112 - CCE: IntroduceHandler.createDeclaration) --- .../python/psi/PyElementGenerator.java | 5 +++-- .../psi/impl/PyElementGeneratorImpl.java | 22 ++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/PyElementGenerator.java b/python/src/com/jetbrains/python/psi/PyElementGenerator.java index 28e8521e947d..009acc249478 100644 --- a/python/src/com/jetbrains/python/psi/PyElementGenerator.java +++ b/python/src/com/jetbrains/python/psi/PyElementGenerator.java @@ -53,13 +53,14 @@ public abstract class PyElementGenerator { public abstract PsiElement insertItemIntoList(PyElement list, @Nullable PyExpression afterThis, PyExpression toInsert) throws IncorrectOperationException; - @Nullable + @NotNull public abstract PyCallExpression createCallExpression(final LanguageLevel langLevel, String functionName); public abstract PyImportStatement createImportStatementFromText(String text); public abstract PyImportElement createImportElement(String name); + @NotNull public abstract T createFromText(LanguageLevel langLevel, Class aClass, final String text); /** @@ -71,7 +72,7 @@ public abstract class PyElementGenerator { * @param path a sequence of numbers, each telling which child to select at current tree level; 0 means first child, etc. * @return the newly created PSI element */ - @Nullable + @NotNull public abstract T createFromText(LanguageLevel langLevel, Class aClass, final String text, final int[] path); public abstract PyNamedParameter createParameter(@NotNull String name); diff --git a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java index a30ffb871c94..c5030321122e 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java @@ -19,6 +19,7 @@ import org.jetbrains.annotations.Nullable; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; +import java.util.Arrays; import java.util.Formatter; /** @@ -202,17 +203,17 @@ public class PyElementGeneratorImpl extends PyElementGenerator { throw new IncorrectOperationException("could not parse text as expression: " + text); } + @NotNull public PyCallExpression createCallExpression(final LanguageLevel langLevel, String functionName) { final PsiFile dummyFile = createDummyFile(langLevel, functionName + "()"); final PsiElement child = dummyFile.getFirstChild(); if (child != null) { final PsiElement element = child.getFirstChild(); - if (!(element instanceof PyCallExpression)) { - throw new IllegalArgumentException("Invalid call expression text " + functionName); + if (element instanceof PyCallExpression) { + return (PyCallExpression)element; } - return (PyCallExpression)element; } - return null; + throw new IllegalArgumentException("Invalid call expression text " + functionName); } public PyImportStatement createImportStatementFromText(final String text) { @@ -227,6 +228,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator { static final int[] FROM_ROOT = new int[]{0}; + @NotNull public T createFromText(LanguageLevel langLevel, Class aClass, final String text) { return createFromText(langLevel, aClass, text, FROM_ROOT); } @@ -237,7 +239,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator { return createFromText(LanguageLevel.getDefault(), PyNamedParameter.class, "def f(" + name + "): pass", PATH_PARAMETER); } - // TODO: use to generate most other things + @NotNull public T createFromText(LanguageLevel langLevel, Class aClass, final String text, final int[] path) { PsiElement ret = createDummyFile(langLevel, text); for (int skip : path) { @@ -248,20 +250,24 @@ public class PyElementGeneratorImpl extends PyElementGenerator { ret = ret.getNextSibling(); } else { - return null; + ret = null; + break; } } } else { - return null; + break; } } + if (ret == null) { + throw new IllegalArgumentException("Can't find element matching path " + Arrays.toString(path) + " in text '" + text + "'"); + } try { //noinspection unchecked return (T)ret; } catch (ClassCastException e) { - return null; + throw new IllegalArgumentException("Can't create an expression of type " + aClass + " from text '" + text + "'"); } } From 80842040ebe2b92c823e74fd4696330323b80d77 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Mon, 11 Jun 2012 14:47:52 +0200 Subject: [PATCH 07/13] Removed print-statements (PY-6675). --- python/helpers/pydev/pydevd_vars.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/python/helpers/pydev/pydevd_vars.py b/python/helpers/pydev/pydevd_vars.py index 94a679e4d12b..aa7439f9372f 100644 --- a/python/helpers/pydev/pydevd_vars.py +++ b/python/helpers/pydev/pydevd_vars.py @@ -183,8 +183,6 @@ def varToXML(val, name, doTrim=True): except: value = 'Unable to get repr for %s' % v.__class__ - print(name) - print(quote(name)) xml = '_= ')), makeValidXmlValue(typeName)) if value: @@ -208,9 +206,6 @@ def varToXML(val, name, doTrim=True): else: xmlValue = '' - print(value) - print(xmlValue) - if is_exception_on_eval: xmlCont = ' isErrorOnEval="True"' else: From 095d7d4e5614cc1d378c8947f8cc48044c819097 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 11 Jun 2012 14:58:01 +0200 Subject: [PATCH 08/13] allow selecting files with no extension in Python script run configuration (PY-6739) --- .../jetbrains/python/run/PythonRunConfigurationForm.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/python/src/com/jetbrains/python/run/PythonRunConfigurationForm.java b/python/src/com/jetbrains/python/run/PythonRunConfigurationForm.java index 684aab755a48..8064388b07eb 100644 --- a/python/src/com/jetbrains/python/run/PythonRunConfigurationForm.java +++ b/python/src/com/jetbrains/python/run/PythonRunConfigurationForm.java @@ -27,23 +27,22 @@ public class PythonRunConfigurationForm implements PythonRunConfigurationParams, private JCheckBox myAttachDebuggerToSubprocess; private final AbstractPyCommonOptionsForm myCommonOptionsForm; private JComponent anchor; - private final Project myProject; public PythonRunConfigurationForm(PythonRunConfiguration configuration) { myCommonOptionsForm = PyCommonOptionsFormFactory.getInstance().createForm(configuration.getCommonOptionsFormData()); myCommonOptionsPlaceholder.add(myCommonOptionsForm.getMainPanel(), BorderLayout.CENTER); - myProject = configuration.getProject(); + Project project = configuration.getProject(); FileChooserDescriptor chooserDescriptor = new FileChooserDescriptor(true, false, false, false, false, false) { public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) { - return file.isDirectory() || Comparing.equal(file.getExtension(), "py"); + return file.isDirectory() || file.getExtension() == null || Comparing.equal(file.getExtension(), "py"); } }; //chooserDescriptor.setRoot(s.getProject().getBaseDir()); ComponentWithBrowseButton.BrowseFolderActionListener listener = - new ComponentWithBrowseButton.BrowseFolderActionListener("Select Script", "", myScriptTextField, myProject, + new ComponentWithBrowseButton.BrowseFolderActionListener("Select Script", "", myScriptTextField, project, chooserDescriptor, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) { protected void onFileChoosen(VirtualFile chosenFile) { From 9639c3950ccb12225065e4dbf816fa2d687adafa Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 11 Jun 2012 15:30:01 +0200 Subject: [PATCH 09/13] no longer insert colon when completing keywords that require text before colon (PY-6709) --- .../PyKeywordCompletionContributor.java | 17 +++-------------- python/testData/completion/elif.after.py | 2 +- .../completion/elifNotIndented.after.py | 2 +- python/testData/completion/except.after.py | 2 +- .../completion/exceptNotIndented.after.py | 2 +- 5 files changed, 7 insertions(+), 18 deletions(-) diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java index 05b5f9715aa0..c9559e7923a4 100644 --- a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java +++ b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java @@ -5,7 +5,6 @@ import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.lookup.TailTypeDecorator; import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PsiElementPattern; import com.intellij.patterns.StandardPatterns; @@ -317,16 +316,6 @@ public class PyKeywordCompletionContributor extends CompletionContributor { private static final FilterPattern PY3K = new FilterPattern(new Py3kFilter()); - /** - * Tail type that adds a space and a colon and puts cursor before colon. Used in things like "if". - */ - public static final TailType PRE_COLON = new TailType() { - public int processTail(Editor editor, int tailOffset) { - tailOffset = insertChar(editor, insertChar(editor, tailOffset, ' '), ':'); - return moveCaret(editor, tailOffset, -1); // stand before ":" - } - }; - // ====== private static void putKeywords(final CompletionResultSet result, TailType tail, @NonNls @NotNull String... words) { @@ -362,7 +351,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { protected void addCompletions( @NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result ) { - putKeywords(result, PRE_COLON, "def", "class", "for", "if", "while", "with"); + putKeywords(result, TailType.NONE, "def", "class", "for", "if", "while", "with"); putKeywords(result, TailType.CASE_COLON, "try"); } } @@ -456,7 +445,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { //.andNot(RIGHT_AFTER_COLON) .andNot(AFTER_QUALIFIER).andNot(IN_STRING_LITERAL) , - new PyKeywordCompletionProvider(PRE_COLON, UnindentingInsertHandler.INSTANCE, "elif")); + new PyKeywordCompletionProvider(TailType.NONE, UnindentingInsertHandler.INSTANCE, "elif")); } private void addWithinTry() { @@ -472,7 +461,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { protected void addCompletions( @NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result ) { - putKeyword("except", UnindentingInsertHandler.INSTANCE, PRE_COLON, result); + putKeyword("except", UnindentingInsertHandler.INSTANCE, TailType.NONE, result); putKeyword("finally", UnindentingInsertHandler.INSTANCE, TailType.CASE_COLON, result); } } diff --git a/python/testData/completion/elif.after.py b/python/testData/completion/elif.after.py index 2be265063334..432aaceb5a03 100644 --- a/python/testData/completion/elif.after.py +++ b/python/testData/completion/elif.after.py @@ -1,3 +1,3 @@ if True: a = 1 -elif : \ No newline at end of file +elif \ No newline at end of file diff --git a/python/testData/completion/elifNotIndented.after.py b/python/testData/completion/elifNotIndented.after.py index 2be265063334..432aaceb5a03 100644 --- a/python/testData/completion/elifNotIndented.after.py +++ b/python/testData/completion/elifNotIndented.after.py @@ -1,3 +1,3 @@ if True: a = 1 -elif : \ No newline at end of file +elif \ No newline at end of file diff --git a/python/testData/completion/except.after.py b/python/testData/completion/except.after.py index a397d92696ac..c40febf7b710 100644 --- a/python/testData/completion/except.after.py +++ b/python/testData/completion/except.after.py @@ -1,3 +1,3 @@ try: a = 1 -except : \ No newline at end of file +except \ No newline at end of file diff --git a/python/testData/completion/exceptNotIndented.after.py b/python/testData/completion/exceptNotIndented.after.py index a397d92696ac..c40febf7b710 100644 --- a/python/testData/completion/exceptNotIndented.after.py +++ b/python/testData/completion/exceptNotIndented.after.py @@ -1,3 +1,3 @@ try: a = 1 -except : \ No newline at end of file +except \ No newline at end of file From 5eb27cd1e319b0e14497bd4b204e328d1b7942c4 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 11 Jun 2012 15:31:54 +0200 Subject: [PATCH 10/13] correct title for goto super popup (PY-6706) --- .../com/jetbrains/python/codeInsight/PyGotoSuperHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/codeInsight/PyGotoSuperHandler.java b/python/src/com/jetbrains/python/codeInsight/PyGotoSuperHandler.java index b36b44fae95f..02575d3d477e 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyGotoSuperHandler.java +++ b/python/src/com/jetbrains/python/codeInsight/PyGotoSuperHandler.java @@ -51,7 +51,7 @@ public class PyGotoSuperHandler implements CodeInsightActionHandler { superClasses.get(0).navigate(true); } else { - NavigationUtil.getPsiElementPopup(superClasses.toArray(new PyClass[superClasses.size()]), CodeInsightBundle.message("goto.super.class.chooser.title")) + NavigationUtil.getPsiElementPopup(superClasses.toArray(new PyClass[superClasses.size()]), "Choose superclass") .showInBestPositionFor(editor); } } From 782847f7ac66090df44948cb364f586c5f5b108e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 11 Jun 2012 18:10:42 +0200 Subject: [PATCH 11/13] trunk is PyCharm 2.6 --- python/resources/idea/PythonApplicationInfo.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/resources/idea/PythonApplicationInfo.xml b/python/resources/idea/PythonApplicationInfo.xml index 650c43cfad4b..adcc754cbabd 100644 --- a/python/resources/idea/PythonApplicationInfo.xml +++ b/python/resources/idea/PythonApplicationInfo.xml @@ -1,5 +1,5 @@ - + From 8427e5bc48521ce00afa4b3a80d2440176843367 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 12 Jun 2012 18:20:45 +0200 Subject: [PATCH 12/13] improve logic for following assignments in Ctrl-Q (PY-6502) --- .../documentation/DocumentationBuilder.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/python/src/com/jetbrains/python/documentation/DocumentationBuilder.java b/python/src/com/jetbrains/python/documentation/DocumentationBuilder.java index 1bce5f1f9c99..3be27d7d0ad6 100644 --- a/python/src/com/jetbrains/python/documentation/DocumentationBuilder.java +++ b/python/src/com/jetbrains/python/documentation/DocumentationBuilder.java @@ -200,13 +200,19 @@ class DocumentationBuilder { final String target_name = myElement.getText(); //prolog_cat.add(TagSmall.apply($("Assigned to ", element.getText(), BR))); prolog_cat.addWith(TagSmall, $(PyBundle.message("QDOC.assigned.to.$0", target_name)).addItem(BR)); - return ((PyTargetExpression)myElement).findAssignedValue(); + final PyExpression assignedValue = ((PyTargetExpression)myElement).findAssignedValue(); + if (assignedValue instanceof PyReferenceExpression) { + final PsiElement resolved = resolveWithoutImplicits((PyReferenceExpression) assignedValue); + if (resolved != null) { + return resolved; + } + } + return assignedValue; } if (myElement instanceof PyReferenceExpression) { //prolog_cat.add(TagSmall.apply($("Assigned to ", element.getText(), BR))); prolog_cat.addWith(TagSmall, $(PyBundle.message("QDOC.assigned.to.$0", myElement.getText())).addItem(BR)); - final QualifiedResolveResult resolveResult = ((PyReferenceExpression)myElement).followAssignmentsChain(PyResolveContext.noImplicits()); - return resolveResult.isImplicit() ? null : resolveResult.getElement(); + return resolveWithoutImplicits((PyReferenceExpression)myElement); } // it may be a call to a standard wrapper if (myElement instanceof PyCallExpression) { @@ -223,6 +229,11 @@ class DocumentationBuilder { return myElement; } + private static PsiElement resolveWithoutImplicits(final PyReferenceExpression element) { + final QualifiedResolveResult resolveResult = element.followAssignmentsChain(PyResolveContext.noImplicits()); + return resolveResult.isImplicit() ? null : resolveResult.getElement(); + } + private void addInheritedDocString(PyFunction fun, PyClass cls) { boolean not_found = true; String meth_name = fun.getName(); From 97f63607eaed7e7ae95209f3293a2c083f4c5314 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 13 Jun 2012 22:56:55 +0400 Subject: [PATCH 13/13] Show owners of variables and fields in completion pop-up (PY-6585) --- .../psi/impl/PyTargetExpressionImpl.java | 15 ++-- .../impl/references/PyQualifiedReference.java | 8 ++- .../psi/impl/references/PyReferenceImpl.java | 1 - .../resolve/CompletionVariantsProcessor.java | 68 ++++++++++++------- .../python/psi/resolve/VariantsProcessor.java | 5 -- .../python/psi/types/PyClassType.java | 3 +- 6 files changed, 58 insertions(+), 42 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java index 7297d3ce5627..2269f1e16ceb 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java @@ -474,15 +474,12 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl attrs = collectAssignedAttributes((PyQualifiedExpression)qualifier); - variants.addAll(attrs); for (PyExpression ex : attrs) { + if (ex instanceof PsiNamedElement && qualifierType instanceof PyClassType) { + variants.add(LookupElementBuilder.create((PsiNamedElement)ex) + .withTypeText(qualifierType.getName()) + .withIcon(PlatformIcons.FIELD_ICON)); + } if (ex instanceof PyReferenceExpression) { PyReferenceExpression refExpr = (PyReferenceExpression)ex; namesAlready.add(refExpr.getReferencedName()); 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 da07d32a06c2..05922e81ed67 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java @@ -518,7 +518,6 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference PythonDataflowUtil.collectFunctionArgNames(element, ret); // include builtin names - processor.setNotice("__builtin__"); final PyFile builtinsFile = PyBuiltinCache.getInstance(element).getBuiltinsFile(); if (builtinsFile != null) { PyResolveUtil.scopeCrawlUp(processor, builtinsFile, null); diff --git a/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java b/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java index 8836064543dc..8011eef745d2 100644 --- a/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java +++ b/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java @@ -11,10 +11,11 @@ import com.intellij.util.PlatformIcons; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.completion.PyClassInsertHandler; import com.jetbrains.python.codeInsight.completion.PyFunctionInsertHandler; +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.types.PyType; -import com.jetbrains.python.psi.types.TypeEvalContext; +import com.jetbrains.python.psi.impl.PyQualifiedName; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -42,12 +43,13 @@ public class CompletionVariantsProcessor extends VariantsProcessor { } protected LookupElementBuilder setupItem(LookupElementBuilder item) { + final Object object = item.getObject(); if (!myPlainNamesOnly) { if (!mySuppressParentheses && - item.getObject() instanceof PyFunction && ((PyFunction) item.getObject()).getProperty() == null && - !isSingleArgDecoratorCall(myContext, (PyFunction)item.getObject())) { + object instanceof PyFunction && ((PyFunction)object).getProperty() == null && + !isSingleArgDecoratorCall(myContext, (PyFunction)object)) { item = item.withInsertHandler(PyFunctionInsertHandler.INSTANCE); - final PyParameterList parameterList = ((PyFunction)item.getObject()).getParameterList(); + final PyParameterList parameterList = ((PyFunction)object).getParameterList(); final String params = StringUtil.join(parameterList.getParameters(), new Function() { @Override public String fun(PyParameter pyParameter) { @@ -56,12 +58,46 @@ public class CompletionVariantsProcessor extends VariantsProcessor { }, ", "); item = item.withTailText("(" + params + ")"); } - else if (item.getObject() instanceof PyClass) { + else if (object instanceof PyClass) { item = item.withInsertHandler(PyClassInsertHandler.INSTANCE); } } - if (myNotice != null) { - return setItemNotice(item, myNotice); + String source = null; + if (object instanceof PsiElement) { + final PsiElement element = (PsiElement)object; + PyClass cls = null; + + if (element instanceof PyFunction) { + cls = ((PyFunction)element).getContainingClass(); + } + else if (element instanceof PyTargetExpression) { + final PyTargetExpression expr = (PyTargetExpression)element; + if (expr.getQualifier() != null || ScopeUtil.getScopeOwner(expr) instanceof PyClass) { + cls = expr.getContainingClass(); + } + } + else if (element instanceof PyClass) { + final ScopeOwner owner = ScopeUtil.getScopeOwner(element); + if (owner instanceof PyClass) { + cls = (PyClass)owner; + } + } + + if (cls != null) { + source = cls.getName(); + } + else if (myContext == null || !PyUtil.inSameFile(myContext, element)) { + PyQualifiedName path = ResolveImportUtil.findCanonicalImportPath(element, null); + if (path != null) { + if (element instanceof PyFile) { + path = path.removeLastComponent(); + } + source = path.toString(); + } + } + } + if (source != null) { + item = item.withTypeText(source); } return item; } @@ -107,22 +143,6 @@ public class CompletionVariantsProcessor extends VariantsProcessor { // things like PyTargetExpression cannot have a general icon, but here we only have variables if (icon == null) icon = PlatformIcons.VARIABLE_ICON; LookupElementBuilder lookupItem = setupItem(LookupElementBuilder.create(expr, referencedName).withIcon(icon)); - if (definer instanceof PyImportElement) { // set notice to imported module name if needed - PsiElement maybeFromImport = definer.getParent(); - if (maybeFromImport instanceof PyFromImportStatement) { - final PyFromImportStatement fromImport = (PyFromImportStatement)maybeFromImport; - PyReferenceExpression src = fromImport.getImportSource(); - if (src != null) { - lookupItem = setItemNotice(lookupItem, src.getName()); - } - } - } - if (definer instanceof PyAssignmentStatement && expr instanceof PyExpression) { - PyType type = ((PyExpression) expr).getType(TypeEvalContext.fast()); - if (type != null) { - lookupItem = lookupItem.withTypeText(type.getName()); - } - } myVariants.put(referencedName, lookupItem); } } diff --git a/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java b/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java index 6c737bee2b75..d6f08efee904 100644 --- a/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java +++ b/python/src/com/jetbrains/python/psi/resolve/VariantsProcessor.java @@ -17,7 +17,6 @@ import java.util.List; public abstract class VariantsProcessor implements PsiScopeProcessor { protected final PsiElement myContext; - protected String myNotice; protected Condition myNodeFilter; protected Condition myNameFilter; @@ -36,10 +35,6 @@ public abstract class VariantsProcessor implements PsiScopeProcessor { myNameFilter = nameFilter; } - public void setNotice(@Nullable String notice) { - myNotice = notice; - } - public boolean isPlainNamesOnly() { return myPlainNamesOnly; } diff --git a/python/src/com/jetbrains/python/psi/types/PyClassType.java b/python/src/com/jetbrains/python/psi/types/PyClassType.java index 68d80309a2b0..be4f90269bc4 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassType.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassType.java @@ -270,7 +270,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType { for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { for (PyDynamicMember member : provider.getMembers(this)) { final String name = member.getName(); - ret.add(LookupElementBuilder.create(name).withIcon(member.getIcon()).withTypeText(member.getShortType())); + ret.add(LookupElementBuilder.create(name).withIcon(member.getIcon()).withTypeText(getName())); } } @@ -310,7 +310,6 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType { final CompletionVariantsProcessor processor = new CompletionVariantsProcessor( expressionHook, new PyResolveUtil.FilterNotInstance(myClass), null ); - processor.setNotice(myClass.getName()); if (suppressParentheses) { processor.suppressParentheses(); }