com.jetbrains.python.psi.impl.references.PyImportReference 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.impl.references;
import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.*;
import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.impl.PyReferenceExpressionImpl;
import com.jetbrains.python.psi.resolve.*;
import com.jetbrains.python.psi.types.PyModuleType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* Reference in an import statement:
* import foo.name
*
* @author yole
*/
public class PyImportReference extends PyReferenceImpl {
protected final PyReferenceExpressionImpl myElement;
public PyImportReference(PyReferenceExpressionImpl element, PyResolveContext context) {
super(element, context);
myElement = element;
}
public static PyImportReference forElement(PyReferenceExpressionImpl expression, PsiElement importParent, PyResolveContext context) {
if (importParent instanceof PyImportElement) {
final PyImportStatementBase importStatement = PsiTreeUtil.getParentOfType(importParent, PyImportStatementBase.class);
if (importStatement instanceof PyFromImportStatement) {
return new PyFromImportNameReference(expression, context);
}
return new PyImportReference(expression, context);
}
return new PyFromImportSourceReference(expression, context);
}
@Override
public String getUnresolvedDescription() {
final PyImportStatement importStatement = PsiTreeUtil.getParentOfType(myElement, PyImportStatement.class);
if (importStatement != null) {
return "No module named " + myElement.getReferencedName();
}
return super.getUnresolvedDescription();
}
@NotNull
@Override
protected List resolveInner() {
final PyImportElement parent = PsiTreeUtil.getParentOfType(myElement, PyImportElement.class); //importRef.getParent();
final QualifiedName qname = myElement.asQualifiedName();
return qname == null ? Collections.emptyList() : ResolveImportUtil.resolveNameInImportStatement(parent, qname);
}
@NotNull
@Override
public Object[] getVariants() {
// no completion in invalid import statements
PyImportElement importElement = PsiTreeUtil.getParentOfType(myElement, PyImportElement.class);
if (importElement != null) {
PsiErrorElement prevError = PsiTreeUtil.getPrevSiblingOfType(importElement, PsiErrorElement.class);
if (prevError != null) {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
}
PyExpression qualifier = myElement.getQualifier();
final TypeEvalContext context = TypeEvalContext.codeCompletion(myElement.getProject(),
CompletionUtil.getOriginalOrSelf(myElement).getContainingFile());
if (qualifier != null) {
// qualifier's type must be module, it should know how to complete
PyType type = context.getType(qualifier);
if (type != null) {
Object[] variants = getTypeCompletionVariants(myElement, type);
if (!alreadyHasImportKeyword()) {
replaceInsertHandler(variants, ImportKeywordHandler.INSTANCE);
}
return variants;
}
else {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
}
else {
// complete to possible modules
return new ImportVariantCollector(context).execute();
}
}
private static void replaceInsertHandler(Object[] variants, final InsertHandler insertHandler) {
for (int i=0; i < variants.length; i+=1) {
Object item = variants[i];
if (hasChildPackages(item)) continue;
if (item instanceof LookupElementBuilder) {
variants[i] = ((LookupElementBuilder)item).withInsertHandler(insertHandler);
}
else if (item instanceof PsiNamedElement) {
final PsiNamedElement element = (PsiNamedElement)item;
final String name = element.getName();
assert name != null; // it can't really have null name
variants[i] = LookupElementBuilder
.create(name)
.withIcon(element.getIcon(0))
.withInsertHandler(insertHandler);
}
}
}
private static boolean hasChildPackages(Object item) {
PsiElement itemElement = null;
if (item instanceof PsiElement) {
itemElement = (PsiElement) item;
}
else if (item instanceof LookupElement) {
LookupElement lookupElement = (LookupElement) item;
if (lookupElement.getObject() instanceof PsiElement) {
itemElement = (PsiElement) lookupElement.getObject();
}
}
return !(itemElement instanceof PsiFile); // TODO deeper check?
}
private boolean alreadyHasImportKeyword() {
if (PsiTreeUtil.getParentOfType(myElement, PyImportStatement.class) != null) {
return true;
}
ASTNode node = myElement.getNode();
while (node != null) {
final IElementType nodeType = node.getElementType();
if (nodeType == PyTokenTypes.IMPORT_KEYWORD) {
return true;
}
node = node.getTreeNext();
}
return false;
}
class ImportVariantCollector {
private final PsiFile myCurrentFile;
private final Set myNamesAlready;
private final List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy