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.PsiElement;
021    import com.intellij.util.containers.ContainerUtil;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
025    import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub;
026    import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes;
027    import org.jetbrains.kotlin.name.FqName;
028    import org.jetbrains.kotlin.name.Name;
029    import org.jetbrains.kotlin.name.SpecialNames;
030    
031    import java.util.Collections;
032    import java.util.List;
033    
034    public class JetPackageDirective extends JetModifierListOwnerStub<KotlinPlaceHolderStub<JetPackageDirective>> implements JetReferenceExpression {
035        private String qualifiedNameCache = null;
036    
037        public JetPackageDirective(@NotNull ASTNode node) {
038            super(node);
039        }
040    
041        public JetPackageDirective(@NotNull KotlinPlaceHolderStub<JetPackageDirective> stub) {
042            super(stub, JetStubElementTypes.PACKAGE_DIRECTIVE);
043        }
044    
045        // This should be either JetSimpleNameExpression, or JetDotQualifiedExpression
046        @Nullable
047        public JetExpression getPackageNameExpression() {
048            return JetStubbedPsiUtil.getStubOrPsiChild(this, JetStubElementTypes.INSIDE_DIRECTIVE_EXPRESSIONS, JetExpression.ARRAY_FACTORY);
049        }
050    
051        @NotNull
052        public List<JetSimpleNameExpression> getPackageNames() {
053            JetExpression nameExpression = getPackageNameExpression();
054            if (nameExpression == null) return Collections.emptyList();
055    
056            List<JetSimpleNameExpression> packageNames = ContainerUtil.newArrayList();
057            while (nameExpression instanceof JetQualifiedExpression) {
058                JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) nameExpression;
059    
060                JetExpression selector = qualifiedExpression.getSelectorExpression();
061                if (selector instanceof JetSimpleNameExpression) {
062                    packageNames.add((JetSimpleNameExpression) selector);
063                }
064    
065                nameExpression = qualifiedExpression.getReceiverExpression();
066            }
067    
068            if (nameExpression instanceof JetSimpleNameExpression) {
069                packageNames.add((JetSimpleNameExpression) nameExpression);
070            }
071    
072            Collections.reverse(packageNames);
073    
074            return packageNames;
075        }
076    
077        @Nullable
078        public JetSimpleNameExpression getLastReferenceExpression() {
079            JetExpression nameExpression = getPackageNameExpression();
080            if (nameExpression == null) return null;
081    
082            return (JetSimpleNameExpression)PsiUtilPackage.getQualifiedElementSelector(nameExpression);
083        }
084    
085        @Nullable
086        public PsiElement getNameIdentifier() {
087            JetSimpleNameExpression lastPart = getLastReferenceExpression();
088            return lastPart != null ? lastPart.getIdentifier() : null;
089        }
090    
091        @Override
092        @NotNull
093        public String getName() {
094            PsiElement nameIdentifier = getNameIdentifier();
095            return nameIdentifier == null ? "" : nameIdentifier.getText();
096        }
097    
098        @NotNull
099        public Name getNameAsName() {
100            PsiElement nameIdentifier = getNameIdentifier();
101            return nameIdentifier == null ? SpecialNames.ROOT_PACKAGE : Name.identifier(nameIdentifier.getText());
102        }
103    
104        public boolean isRoot() {
105            return getName().length() == 0;
106        }
107    
108        @NotNull
109        public FqName getFqName() {
110            String qualifiedName = getQualifiedName();
111            return qualifiedName.isEmpty() ? FqName.ROOT : new FqName(qualifiedName);
112        }
113    
114        @NotNull
115        public FqName getFqName(JetSimpleNameExpression nameExpression) {
116            return new FqName(getQualifiedNameOf(nameExpression));
117        }
118    
119        @NotNull
120        public String getQualifiedName() {
121            if (qualifiedNameCache == null) {
122                qualifiedNameCache = getQualifiedNameOf(null);
123            }
124    
125            return qualifiedNameCache;
126        }
127    
128        @NotNull
129        private String getQualifiedNameOf(@Nullable JetSimpleNameExpression nameExpression) {
130            StringBuilder builder = new StringBuilder();
131            for (JetSimpleNameExpression e : getPackageNames()) {
132                if (builder.length() > 0) {
133                    builder.append(".");
134                }
135                builder.append(e.getReferencedName());
136    
137                if (e == nameExpression) break;
138            }
139            return builder.toString();
140        }
141    
142        @Override
143        public void subtreeChanged() {
144            qualifiedNameCache = null;
145        }
146    
147        @Override
148        public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
149            return visitor.visitPackageDirective(this, data);
150        }
151    }
152