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(); }