| /* |
| * 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; |
| } |
| } |