blob: de8b51734a1339babcddfd1e1c44fb4f4f06032e [file] [log] [blame]
/*
* Copyright 2000-2013 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;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.containers.EmptyIterable;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PythonDialectsTokenSetProvider;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.ResolveImportUtil;
import com.jetbrains.python.psi.stubs.PyImportElementStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collections;
/**
* The "import foo" or "import foo as bar" parts.
*
* @author yole
*/
public class PyImportElementImpl extends PyBaseElementImpl<PyImportElementStub> implements PyImportElement {
public PyImportElementImpl(ASTNode astNode) {
super(astNode);
}
public PyImportElementImpl(PyImportElementStub stub) {
this(stub, PyElementTypes.IMPORT_ELEMENT);
}
public PyImportElementImpl(PyImportElementStub stub, IStubElementType nodeType) {
super(stub, nodeType);
}
@Nullable
public PyReferenceExpression getImportReferenceExpression() {
final ASTNode node = getNode().findChildByType(PythonDialectsTokenSetProvider.INSTANCE.getReferenceExpressionTokens());
return node == null ? null : (PyReferenceExpression) node.getPsi();
}
public QualifiedName getImportedQName() {
final PyImportElementStub stub = getStub();
if (stub != null) {
return stub.getImportedQName();
}
final PyReferenceExpression importReference = getImportReferenceExpression();
return importReference != null ? importReference.asQualifiedName() : null;
}
public PyTargetExpression getAsNameElement() {
return getStubOrPsiChild(PyElementTypes.TARGET_EXPRESSION);
}
public String getAsName() {
final PyImportElementStub stub = getStub();
if (stub != null) {
final String asName = stub.getAsName();
return StringUtil.isEmpty(asName) ? null : asName;
}
final PyTargetExpression element = getAsNameElement();
return element != null ? element.getName() : null;
}
@Override
@Nullable
public String getVisibleName() {
final PyImportElementStub stub = getStub();
if (stub != null) {
final String asName = stub.getAsName();
if (!StringUtil.isEmpty(asName)) {
return asName;
}
final QualifiedName importedName = stub.getImportedQName();
if (importedName != null && importedName.getComponentCount() > 0) {
return importedName.getComponents().get(0);
}
}
else {
PyTargetExpression asNameElement = getAsNameElement();
if (asNameElement != null) {
return asNameElement.getName();
}
final QualifiedName importedName = getImportedQName();
if (importedName != null && importedName.getComponentCount() > 0) {
return importedName.getComponents().get(0);
}
}
return null; // we might have not found any names
}
@Nullable
public PyStatement getContainingImportStatement() {
final PyImportElementStub stub = getStub();
PsiElement parent;
if (stub != null) {
parent = stub.getParentStub().getPsi();
}
else {
parent = getParent();
}
return parent instanceof PyStatement ? (PyStatement)parent : null;
}
@Override
public ItemPresentation getPresentation() {
return new ItemPresentation() {
@NotNull
private String getRefName(String default_name) {
PyReferenceExpression ref = getImportReferenceExpression();
if (ref != null) {
String refName = ref.getName();
if (refName != null) return refName;
}
return default_name;
}
public String getPresentableText() {
return getRefName("<none>");
}
public String getLocationString() {
PyElement elt = PsiTreeUtil.getParentOfType(PyImportElementImpl.this, PyImportStatement.class, PyFromImportStatement.class);
final StringBuilder buf = new StringBuilder("| ");
if (elt != null) { // always? who knows :)
if (elt instanceof PyFromImportStatement) { // from ... import ...
buf.append("from ");
PyReferenceExpression imp_src = ((PyFromImportStatement)elt).getImportSource();
if (imp_src != null) {
buf.append(PyPsiUtils.toPath(imp_src));
}
else {
buf.append("<?>");
}
buf.append(" import ");
}
else { // "import ... "
buf.append("import ");
}
buf.append(getRefName("<?>"));
}
else {
buf.append("import?.. ");
}
// are we the name or the 'as'?
PyTargetExpression as_part = getAsNameElement();
if (as_part != null) {
buf.append(" as ").append(as_part.getName());
}
return buf.toString();
}
public Icon getIcon(final boolean open) {
return null;
}
};
}
@NotNull
public Iterable<PyElement> iterateNames() {
PyElement ret = getAsNameElement();
if (ret == null) {
final PyReferenceExpression importReference = getImportReferenceExpression();
if (importReference != null) {
ret = PyPsiUtils.getFirstQualifier(importReference);
}
}
if (ret == null) {
return EmptyIterable.getInstance();
}
return Collections.singleton(ret);
}
public PsiElement getElementNamed(final String name) {
return getElementNamed(name, true);
}
@Override
public PsiElement getElementNamed(String name, boolean resolveImportElement) {
String asName = getAsName();
if (asName != null) {
if (!Comparing.equal(name, asName)) return null;
return resolveImportElement ? resolve() : this;
}
else {
final QualifiedName qName = getImportedQName();
if (qName == null || qName.getComponentCount() == 0 || !qName.getComponents().get(0).equals(name)) {
return null;
}
if (qName.getComponentCount() == 1) {
if (resolveImportElement) {
return ResolveImportUtil.resolveImportElement(this, QualifiedName.fromComponents(name));
}
return this;
}
return createImportedModule(name);
}
}
@Nullable
@Override
public PsiElement resolve() {
QualifiedName qName = getImportedQName();
return qName == null ? null : ResolveImportUtil.resolveImportElement(this, qName);
}
public boolean mustResolveOutside() {
return true; // formally
}
@Override
protected void acceptPyVisitor(PyElementVisitor pyVisitor) {
pyVisitor.visitPyImportElement(this);
}
@Override
public String toString() {
final QualifiedName qName = getImportedQName();
return String.format("%s:%s", super.toString(), qName != null ? qName : "null");
}
@Nullable
private PsiElement createImportedModule(String name) {
final PsiFile file = getContainingFile();
if (file instanceof PyFile) {
return new PyImportedModule(this, (PyFile)file, QualifiedName.fromComponents(name));
}
return null;
}
}