mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Show owners of variables and fields in completion pop-up (PY-6585)
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user