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