Show owners of variables and fields in completion pop-up (PY-6585)

This commit is contained in:
Andrey Vlasovskikh
2012-06-13 22:56:55 +04:00
parent 68608222e9
commit 97f63607ea
6 changed files with 58 additions and 42 deletions
@@ -474,15 +474,12 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
return null;
}
PsiElement parent = PsiTreeUtil.getParentOfType(this, PyStatementList.class);
if (parent != null) {
PsiElement pparent = parent.getParent();
if (pparent instanceof PyClass) {
return (PyClass)pparent;
}
if (pparent instanceof PyFunction) {
return ((PyFunction) pparent).getContainingClass();
}
final PsiElement parent = PsiTreeUtil.getParentOfType(this, PyFunction.class, PyClass.class);
if (parent instanceof PyClass) {
return (PyClass)parent;
}
if (parent instanceof PyFunction) {
return ((PyFunction)parent).getContainingClass();
}
return null;
}
@@ -11,11 +11,13 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.stubs.StubUpdatingIndex;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PlatformIcons;
import com.intellij.util.ProcessingContext;
import com.intellij.util.indexing.FileBasedIndex;
import com.jetbrains.cython.types.CythonStructType;
@@ -250,8 +252,12 @@ public class PyQualifiedReference extends PyReferenceImpl {
Collections.addAll(variants, getVariantFromHasAttr(qualifier));
if (qualifier instanceof PyQualifiedExpression) {
Collection<PyExpression> 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());
@@ -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);
@@ -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<PyParameter, String>() {
@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);
}
}
@@ -17,7 +17,6 @@ import java.util.List;
public abstract class VariantsProcessor implements PsiScopeProcessor {
protected final PsiElement myContext;
protected String myNotice;
protected Condition<PsiElement> myNodeFilter;
protected Condition<String> 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;
}
@@ -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();
}