/*
* Copyright 2010-2015 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 org.jetbrains.kotlin.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.name.SpecialNames;
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub;
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
import java.util.Collections;
import java.util.List;
public class KtPackageDirective extends KtModifierListOwnerStub<KotlinPlaceHolderStub<KtPackageDirective>> {
private String qualifiedNameCache = null;
public KtPackageDirective(@NotNull ASTNode node) {
super(node);
}
public KtPackageDirective(@NotNull KotlinPlaceHolderStub<KtPackageDirective> stub) {
super(stub, KtStubElementTypes.PACKAGE_DIRECTIVE);
}
// This should be either JetSimpleNameExpression, or JetDotQualifiedExpression
@Nullable
public KtExpression getPackageNameExpression() {
return KtStubbedPsiUtil.getStubOrPsiChild(this, KtStubElementTypes.INSIDE_DIRECTIVE_EXPRESSIONS, KtExpression.ARRAY_FACTORY);
}
@NotNull
public List<KtSimpleNameExpression> getPackageNames() {
KtExpression nameExpression = getPackageNameExpression();
if (nameExpression == null) return Collections.emptyList();
List<KtSimpleNameExpression> packageNames = ContainerUtil.newArrayList();
while (nameExpression instanceof KtQualifiedExpression) {
KtQualifiedExpression qualifiedExpression = (KtQualifiedExpression) nameExpression;
KtExpression selector = qualifiedExpression.getSelectorExpression();
if (selector instanceof KtSimpleNameExpression) {
packageNames.add((KtSimpleNameExpression) selector);
}
nameExpression = qualifiedExpression.getReceiverExpression();
}
if (nameExpression instanceof KtSimpleNameExpression) {
packageNames.add((KtSimpleNameExpression) nameExpression);
}
Collections.reverse(packageNames);
return packageNames;
}
@Nullable
public KtSimpleNameExpression getLastReferenceExpression() {
KtExpression nameExpression = getPackageNameExpression();
if (nameExpression == null) return null;
return (KtSimpleNameExpression) KtPsiUtilKt.getQualifiedElementSelector(nameExpression);
}
@Nullable
public PsiElement getNameIdentifier() {
KtSimpleNameExpression lastPart = getLastReferenceExpression();
return lastPart != null ? lastPart.getIdentifier() : null;
}
@Override
@NotNull
public String getName() {
PsiElement nameIdentifier = getNameIdentifier();
return nameIdentifier == null ? "" : nameIdentifier.getText();
}
@NotNull
public Name getNameAsName() {
PsiElement nameIdentifier = getNameIdentifier();
return nameIdentifier == null ? SpecialNames.ROOT_PACKAGE : Name.identifier(nameIdentifier.getText());
}
public boolean isRoot() {
return getName().length() == 0;
}
@NotNull
public FqName getFqName() {
String qualifiedName = getQualifiedName();
return qualifiedName.isEmpty() ? FqName.ROOT : new FqName(qualifiedName);
}
@NotNull
public FqName getFqName(KtSimpleNameExpression nameExpression) {
return new FqName(getQualifiedNameOf(nameExpression));
}
public void setFqName(@NotNull FqName fqName) {
if (fqName.isRoot()) {
delete();
return;
}
KtPsiFactory psiFactory = new KtPsiFactory(getProject());
PsiElement newExpression = psiFactory.createExpression(fqName.asString());
KtExpression currentExpression = getPackageNameExpression();
if (currentExpression != null) {
currentExpression.replace(newExpression);
return;
}
PsiElement keyword = getPackageKeyword();
if (keyword != null) {
addAfter(newExpression, keyword);
return;
}
replace(psiFactory.createPackageDirective(fqName));
}
@NotNull
public String getQualifiedName() {
if (qualifiedNameCache == null) {
qualifiedNameCache = getQualifiedNameOf(null);
}
return qualifiedNameCache;
}
@NotNull
private String getQualifiedNameOf(@Nullable KtSimpleNameExpression nameExpression) {
StringBuilder builder = new StringBuilder();
for (KtSimpleNameExpression e : getPackageNames()) {
if (builder.length() > 0) {
builder.append(".");
}
builder.append(e.getReferencedName());
if (e == nameExpression) break;
}
return builder.toString();
}
@Nullable
public PsiElement getPackageKeyword() {
return findChildByType(KtTokens.PACKAGE_KEYWORD);
}
@Override
public void subtreeChanged() {
qualifiedNameCache = null;
}
@Override
public <R, D> R accept(@NotNull KtVisitor<R, D> visitor, D data) {
return visitor.visitPackageDirective(this, data);
}
}