001 /* 002 * Copyright 2010-2013 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.jet.lang.psi; 018 019 import com.intellij.extapi.psi.PsiFileBase; 020 import com.intellij.lang.ASTNode; 021 import com.intellij.lang.FileASTNode; 022 import com.intellij.openapi.fileTypes.FileType; 023 import com.intellij.psi.FileViewProvider; 024 import com.intellij.psi.PsiClass; 025 import com.intellij.psi.PsiClassOwner; 026 import com.intellij.psi.PsiElementVisitor; 027 import com.intellij.psi.stubs.StubElement; 028 import com.intellij.psi.util.PsiTreeUtil; 029 import org.jetbrains.annotations.NotNull; 030 import org.jetbrains.annotations.Nullable; 031 import org.jetbrains.jet.JetNodeTypes; 032 import org.jetbrains.jet.lang.psi.stubs.KotlinFileStub; 033 import org.jetbrains.jet.lang.psi.stubs.elements.JetPlaceHolderStubElementType; 034 import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; 035 import org.jetbrains.jet.lang.resolve.name.FqName; 036 import org.jetbrains.jet.plugin.JetFileType; 037 import org.jetbrains.jet.plugin.JetLanguage; 038 039 import java.util.Arrays; 040 import java.util.Collections; 041 import java.util.List; 042 043 public class JetFile extends PsiFileBase implements JetDeclarationContainer, JetAnnotated, JetElement, PsiClassOwner { 044 045 private final boolean isCompiled; 046 047 public JetFile(FileViewProvider viewProvider, boolean compiled) { 048 super(viewProvider, JetLanguage.INSTANCE); 049 this.isCompiled = compiled; 050 } 051 052 @Override 053 public FileASTNode getNode() { 054 return super.getNode(); 055 } 056 057 public boolean isCompiled() { 058 return isCompiled; 059 } 060 061 @Override 062 @NotNull 063 public FileType getFileType() { 064 return JetFileType.INSTANCE; 065 } 066 067 @Override 068 public String toString() { 069 return "JetFile: " + getName(); 070 } 071 072 @NotNull 073 @Override 074 public List<JetDeclaration> getDeclarations() { 075 KotlinFileStub stub = getStub(); 076 if (stub != null) { 077 return Arrays.asList(stub.getChildrenByType(JetStubElementTypes.DECLARATION_TYPES, JetDeclaration.ARRAY_FACTORY)); 078 } 079 return PsiTreeUtil.getChildrenOfTypeAsList(this, JetDeclaration.class); 080 } 081 082 @Nullable 083 public JetImportList getImportList() { 084 return findChildByTypeOrClass(JetStubElementTypes.IMPORT_LIST, JetImportList.class); 085 } 086 087 @Nullable 088 public JetFileAnnotationList getFileAnnotationList() { 089 return findChildByTypeOrClass(JetStubElementTypes.FILE_ANNOTATION_LIST, JetFileAnnotationList.class); 090 } 091 092 @Nullable 093 public <T extends JetElementImplStub<? extends StubElement<?>>> T findChildByTypeOrClass( 094 @NotNull JetPlaceHolderStubElementType<T> elementType, 095 @NotNull Class<T> elementClass 096 ) { 097 KotlinFileStub stub = getStub(); 098 if (stub != null) { 099 StubElement<T> importListStub = stub.findChildStubByType(elementType); 100 return importListStub != null ? importListStub.getPsi() : null; 101 } 102 return findChildByClass(elementClass); 103 } 104 105 @NotNull 106 public List<JetImportDirective> getImportDirectives() { 107 JetImportList importList = getImportList(); 108 return importList != null ? importList.getImports() : Collections.<JetImportDirective>emptyList(); 109 } 110 111 @Nullable 112 public JetImportDirective findImportByAlias(@NotNull String name) { 113 for (JetImportDirective directive : getImportDirectives()) { 114 if (name.equals(directive.getAliasName())) { 115 return directive; 116 } 117 } 118 return null; 119 } 120 121 // scripts have no package directive, all other files must have package directives 122 @Nullable 123 public JetPackageDirective getPackageDirective() { 124 KotlinFileStub stub = getStub(); 125 if (stub != null) { 126 StubElement<JetPackageDirective> packageDirectiveStub = stub.findChildStubByType(JetStubElementTypes.PACKAGE_DIRECTIVE); 127 return packageDirectiveStub != null ? packageDirectiveStub.getPsi() : null; 128 } 129 ASTNode ast = getNode().findChildByType(JetNodeTypes.PACKAGE_DIRECTIVE); 130 return ast != null ? (JetPackageDirective) ast.getPsi() : null; 131 } 132 133 @Deprecated // getPackageFqName should be used instead 134 @Override 135 @NotNull 136 public String getPackageName() { 137 return getPackageFqName().asString(); 138 } 139 140 @NotNull 141 public FqName getPackageFqName() { 142 KotlinFileStub stub = getStub(); 143 if (stub != null) { 144 return stub.getPackageFqName(); 145 } 146 return getPackageFqNameByTree(); 147 } 148 149 @NotNull 150 public FqName getPackageFqNameByTree() { 151 JetPackageDirective packageDirective = getPackageDirective(); 152 if (packageDirective == null) { 153 return FqName.ROOT; 154 } 155 return packageDirective.getFqName(); 156 } 157 158 @Override 159 @Nullable 160 public KotlinFileStub getStub() { 161 return (KotlinFileStub) super.getStub(); 162 } 163 164 @NotNull 165 @Override 166 public PsiClass[] getClasses() { 167 return PsiClass.EMPTY_ARRAY; 168 } 169 170 @Override 171 public void setPackageName(String packageName) { } 172 173 // SCRIPT: find script in file 174 @Nullable 175 public JetScript getScript() { 176 return PsiTreeUtil.getChildOfType(this, JetScript.class); 177 } 178 179 public boolean isScript() { 180 KotlinFileStub stub = getStub(); 181 if (stub != null) { 182 return stub.isScript(); 183 } 184 return isScriptByTree(); 185 } 186 187 public boolean isScriptByTree() { 188 return getScript() != null; 189 } 190 191 @NotNull 192 @Override 193 public String getName() { 194 return super.getName(); // TODO 195 } 196 197 @Override 198 public void accept(@NotNull PsiElementVisitor visitor) { 199 if (visitor instanceof JetVisitor) { 200 accept((JetVisitor) visitor, null); 201 } 202 else { 203 visitor.visitFile(this); 204 } 205 } 206 207 @NotNull 208 @Override 209 public JetFile getContainingJetFile() { 210 return this; 211 } 212 213 @Override 214 public <D> void acceptChildren(@NotNull JetTreeVisitor<D> visitor, D data) { 215 JetPsiUtil.visitChildren(this, visitor, data); 216 } 217 218 @Override 219 public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) { 220 return visitor.visitJetFile(this, data); 221 } 222 223 @NotNull 224 @Override 225 public List<JetAnnotation> getAnnotations() { 226 JetFileAnnotationList fileAnnotationList = getFileAnnotationList(); 227 if (fileAnnotationList == null) return Collections.emptyList(); 228 229 return fileAnnotationList.getAnnotations(); 230 } 231 232 @NotNull 233 @Override 234 public List<JetAnnotationEntry> getAnnotationEntries() { 235 JetFileAnnotationList fileAnnotationList = getFileAnnotationList(); 236 if (fileAnnotationList == null) return Collections.emptyList(); 237 238 return fileAnnotationList.getAnnotationEntries(); 239 } 240 }