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