com.jetbrains.python.psi.resolve.CompletionVariantsProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of python-community Show documentation
Show all versions of python-community Show documentation
A packaging of the IntelliJ Community Edition python-community library.
This is release number 1 of trunk branch 142.
The newest version!
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.psi.resolve;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Function;
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.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
/**
* @author yole
*/
public class CompletionVariantsProcessor extends VariantsProcessor {
private final Map myVariants = new HashMap();
private boolean mySuppressParentheses = false;
public CompletionVariantsProcessor(PsiElement context) {
super(context);
}
public CompletionVariantsProcessor(PsiElement context,
@Nullable Condition nodeFilter,
@Nullable Condition nameFilter) {
super(context, nodeFilter, nameFilter);
}
public void suppressParentheses() {
mySuppressParentheses = true;
}
protected LookupElementBuilder setupItem(LookupElementBuilder item) {
final Object object = item.getObject();
if (!myPlainNamesOnly) {
if (!mySuppressParentheses &&
object instanceof PyFunction && ((PyFunction)object).getProperty() == null &&
!PyUtil.hasCustomDecorators((PyFunction)object) &&
!isSingleArgDecoratorCall(myContext, (PyFunction)object)) {
final Project project = ((PyFunction)object).getProject();
item = item.withInsertHandler(PyFunctionInsertHandler.INSTANCE);
final TypeEvalContext context = TypeEvalContext.codeCompletion(project, myContext != null ? myContext.getContainingFile() : null);
final List parameters = PyUtil.getParameters((PyFunction)object, context);
final String params = StringUtil.join(parameters, new Function() {
@Override
public String fun(PyParameter pyParameter) {
return pyParameter.getName();
}
}, ", ");
item = item.withTailText("(" + params + ")");
}
else if (object instanceof PyClass) {
item = item.withInsertHandler(PyClassInsertHandler.INSTANCE);
}
}
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.isQualified() || 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)) {
QualifiedName path = QualifiedNameFinder.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;
}
private static boolean isSingleArgDecoratorCall(PsiElement elementInCall, PyFunction callee) {
// special case hack to avoid the need of patching generator3.py
PyClass containingClass = callee.getContainingClass();
if (containingClass != null && PyNames.PROPERTY.equals(containingClass.getName()) &&
PyBuiltinCache.getInstance(elementInCall).isBuiltin(containingClass)) {
return true;
}
if (callee.getParameterList().getParameters().length > 1) {
return false;
}
PyDecorator decorator = PsiTreeUtil.getParentOfType(elementInCall, PyDecorator.class);
if (decorator == null) {
return false;
}
return PsiTreeUtil.isAncestor(decorator.getCallee(), elementInCall, false);
}
protected static LookupElementBuilder setItemNotice(final LookupElementBuilder item, String notice) {
return item.withTypeText(notice);
}
public LookupElement[] getResult() {
final Collection variants = myVariants.values();
return variants.toArray(new LookupElement[variants.size()]);
}
public List getResultList() {
return new ArrayList(myVariants.values());
}
@Override
protected void addElement(String name, PsiElement element) {
if (PyUtil.isClassPrivateName(name) && !PyUtil.inSameFile(element, myContext)) {
return;
}
myVariants.put(name, setupItem(LookupElementBuilder.create(element, name).withIcon(element.getIcon(0))));
}
protected void addImportedElement(String referencedName, NameDefiner definer, PyElement expr) {
Icon icon = expr.getIcon(0);
// 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));
myVariants.put(referencedName, lookupItem);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy