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.JetTokens;
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.JetStubElementTypes;
029    import org.jetbrains.kotlin.resolve.ImportPath;
030    
031    public class JetImportDirective extends JetElementImplStub<KotlinImportDirectiveStub> {
032    
033        public JetImportDirective(@NotNull ASTNode node) {
034            super(node);
035        }
036    
037        public JetImportDirective(@NotNull KotlinImportDirectiveStub stub) {
038            super(stub, JetStubElementTypes.IMPORT_DIRECTIVE);
039        }
040    
041        @Override
042        public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
043            return visitor.visitImportDirective(this, data);
044        }
045    
046        public boolean isAbsoluteInRootPackage() {
047            KotlinImportDirectiveStub stub = getStub();
048            if (stub != null) {
049                return stub.isAbsoluteInRootPackage();
050            }
051            return findChildByType(JetTokens.PACKAGE_KEYWORD) != null;
052        }
053    
054        @Nullable @IfNotParsed
055        public JetExpression getImportedReference() {
056            JetExpression[] references = getStubOrPsiChildren(JetStubElementTypes.INSIDE_DIRECTIVE_EXPRESSIONS, JetExpression.ARRAY_FACTORY);
057            if (references.length > 0) {
058                return references[0];
059            }
060            return null;
061        }
062    
063        @Nullable
064        public ASTNode getAliasNameNode() {
065            boolean asPassed = false;
066            ASTNode childNode = getNode().getFirstChildNode();
067            while (childNode != null) {
068                IElementType tt = childNode.getElementType();
069                if (tt == JetTokens.AS_KEYWORD) asPassed = true;
070                if (asPassed && tt == JetTokens.IDENTIFIER) {
071                    return childNode;
072                }
073    
074                childNode = childNode.getTreeNext();
075            }
076            return null;
077        }
078    
079        @Nullable
080        public String getAliasName() {
081            KotlinImportDirectiveStub stub = getStub();
082            if (stub != null) {
083                return stub.getAliasName();
084            }
085            ASTNode aliasNameNode = getAliasNameNode();
086            if (aliasNameNode == null) {
087                return null;
088            }
089            return aliasNameNode.getText();
090        }
091    
092        public boolean isAllUnder() {
093            KotlinImportDirectiveStub stub = getStub();
094            if (stub != null) {
095                return stub.isAllUnder();
096            }
097            return getNode().findChildByType(JetTokens.MUL) != null;
098        }
099    
100        @Nullable
101        @IfNotParsed
102        public FqName getImportedFqName() {
103            KotlinImportDirectiveStub stub = getStub();
104            if (stub != null) {
105                return stub.getImportedFqName();
106            }
107            return fqNameFromExpression(getImportedReference());
108        }
109    
110        @Nullable
111        @IfNotParsed
112        public ImportPath getImportPath() {
113            FqName importFqn = getImportedFqName();
114            if (importFqn == null) {
115                return null;
116            }
117    
118            Name alias = null;
119            String aliasName = getAliasName();
120            if (aliasName != null) {
121                alias = Name.identifier(aliasName);
122            }
123    
124            return new ImportPath(importFqn, isAllUnder(), alias);
125        }
126    
127        public boolean isValidImport() {
128            KotlinImportDirectiveStub stub = getStub();
129            if (stub != null) {
130                return stub.isValid();
131            }
132            return !PsiTreeUtil.hasErrorElements(this);
133        }
134    
135        @Nullable
136        private static FqName fqNameFromExpression(@Nullable JetExpression expression) {
137            if (expression == null) {
138                return null;
139            }
140    
141            if (expression instanceof JetDotQualifiedExpression) {
142                JetDotQualifiedExpression dotQualifiedExpression = (JetDotQualifiedExpression) expression;
143                FqName parentFqn = fqNameFromExpression(dotQualifiedExpression.getReceiverExpression());
144                Name child = nameFromExpression(dotQualifiedExpression.getSelectorExpression());
145                if (child == null) {
146                    return parentFqn;
147                }
148                if (parentFqn != null) {
149                    return parentFqn.child(child);
150                }
151                return null;
152            }
153            else if (expression instanceof JetSimpleNameExpression) {
154                JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
155                return FqName.topLevel(simpleNameExpression.getReferencedNameAsName());
156            }
157            else {
158                throw new IllegalArgumentException("Can't construct fqn for: " + expression.getClass().toString());
159            }
160        }
161    
162        @Nullable
163        private static Name nameFromExpression(@Nullable JetExpression expression) {
164            if (expression == null) {
165                return null;
166            }
167    
168            if (expression instanceof JetSimpleNameExpression) {
169                return ((JetSimpleNameExpression) expression).getReferencedNameAsName();
170            }
171            else {
172                throw new IllegalArgumentException("Can't construct name for: " + expression.getClass().toString());
173            }
174        }
175    }