001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.psi;
018    
019    import com.intellij.lang.ASTNode;
020    import com.intellij.psi.tree.IElementType;
021    import com.intellij.psi.util.PsiTreeUtil;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.kotlin.lexer.KtTokens;
025    import org.jetbrains.kotlin.name.FqName;
026    import org.jetbrains.kotlin.name.Name;
027    import org.jetbrains.kotlin.psi.stubs.KotlinImportDirectiveStub;
028    import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
029    import org.jetbrains.kotlin.resolve.ImportPath;
030    
031    public class KtImportDirective extends KtElementImplStub<KotlinImportDirectiveStub> {
032    
033        public KtImportDirective(@NotNull ASTNode node) {
034            super(node);
035        }
036    
037        public KtImportDirective(@NotNull KotlinImportDirectiveStub stub) {
038            super(stub, KtStubElementTypes.IMPORT_DIRECTIVE);
039        }
040    
041        @Override
042        public <R, D> R accept(@NotNull KtVisitor<R, D> visitor, D data) {
043            return visitor.visitImportDirective(this, data);
044        }
045    
046        @Nullable
047        @IfNotParsed
048        public KtExpression getImportedReference() {
049            KtExpression[] references = getStubOrPsiChildren(KtStubElementTypes.INSIDE_DIRECTIVE_EXPRESSIONS, KtExpression.ARRAY_FACTORY);
050            if (references.length > 0) {
051                return references[0];
052            }
053            return null;
054        }
055    
056        @Nullable
057        public ASTNode getAliasNameNode() {
058            boolean asPassed = false;
059            ASTNode childNode = getNode().getFirstChildNode();
060            while (childNode != null) {
061                IElementType tt = childNode.getElementType();
062                if (tt == KtTokens.AS_KEYWORD) asPassed = true;
063                if (asPassed && tt == KtTokens.IDENTIFIER) {
064                    return childNode;
065                }
066    
067                childNode = childNode.getTreeNext();
068            }
069            return null;
070        }
071    
072        @Nullable
073        public String getAliasName() {
074            KotlinImportDirectiveStub stub = getStub();
075            if (stub != null) {
076                return stub.getAliasName();
077            }
078            ASTNode aliasNameNode = getAliasNameNode();
079            if (aliasNameNode == null) {
080                return null;
081            }
082            return aliasNameNode.getText();
083        }
084    
085        public boolean isAllUnder() {
086            KotlinImportDirectiveStub stub = getStub();
087            if (stub != null) {
088                return stub.isAllUnder();
089            }
090            return getNode().findChildByType(KtTokens.MUL) != null;
091        }
092    
093        @Nullable
094        @IfNotParsed
095        public FqName getImportedFqName() {
096            KotlinImportDirectiveStub stub = getStub();
097            if (stub != null) {
098                return stub.getImportedFqName();
099            }
100            return fqNameFromExpression(getImportedReference());
101        }
102    
103        @Nullable
104        @IfNotParsed
105        public ImportPath getImportPath() {
106            FqName importFqn = getImportedFqName();
107            if (importFqn == null) {
108                return null;
109            }
110    
111            Name alias = null;
112            String aliasName = getAliasName();
113            if (aliasName != null) {
114                alias = Name.identifier(aliasName);
115            }
116    
117            return new ImportPath(importFqn, isAllUnder(), alias);
118        }
119    
120        public boolean isValidImport() {
121            KotlinImportDirectiveStub stub = getStub();
122            if (stub != null) {
123                return stub.isValid();
124            }
125            return !PsiTreeUtil.hasErrorElements(this);
126        }
127    
128        @Nullable
129        private static FqName fqNameFromExpression(@Nullable KtExpression expression) {
130            if (expression == null) {
131                return null;
132            }
133    
134            if (expression instanceof KtDotQualifiedExpression) {
135                KtDotQualifiedExpression dotQualifiedExpression = (KtDotQualifiedExpression) expression;
136                FqName parentFqn = fqNameFromExpression(dotQualifiedExpression.getReceiverExpression());
137                Name child = nameFromExpression(dotQualifiedExpression.getSelectorExpression());
138                if (child == null) {
139                    return parentFqn;
140                }
141                if (parentFqn != null) {
142                    return parentFqn.child(child);
143                }
144                return null;
145            }
146            else if (expression instanceof KtSimpleNameExpression) {
147                KtSimpleNameExpression simpleNameExpression = (KtSimpleNameExpression) expression;
148                return FqName.topLevel(simpleNameExpression.getReferencedNameAsName());
149            }
150            else {
151                throw new IllegalArgumentException("Can't construct fqn for: " + expression.getClass().toString());
152            }
153        }
154    
155        @Nullable
156        private static Name nameFromExpression(@Nullable KtExpression expression) {
157            if (expression == null) {
158                return null;
159            }
160    
161            if (expression instanceof KtSimpleNameExpression) {
162                return ((KtSimpleNameExpression) expression).getReferencedNameAsName();
163            }
164            else {
165                throw new IllegalArgumentException("Can't construct name for: " + expression.getClass().toString());
166            }
167        }
168    }