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.lang.ASTNode; 020 import com.intellij.navigation.ItemPresentation; 021 import com.intellij.navigation.ItemPresentationProviders; 022 import com.intellij.openapi.util.text.StringUtil; 023 import com.intellij.psi.PsiElement; 024 import com.intellij.psi.PsiFile; 025 import com.intellij.psi.stubs.IStubElementType; 026 import com.intellij.psi.util.PsiTreeUtil; 027 import com.intellij.util.IncorrectOperationException; 028 import org.jetbrains.annotations.NotNull; 029 import org.jetbrains.annotations.Nullable; 030 import org.jetbrains.jet.JetNodeTypes; 031 import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; 032 import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; 033 import org.jetbrains.jet.lang.resolve.name.FqName; 034 import org.jetbrains.jet.lexer.JetTokens; 035 036 import java.util.ArrayList; 037 import java.util.Collections; 038 import java.util.List; 039 040 public class JetClass extends JetTypeParameterListOwnerStub<PsiJetClassStub> implements JetClassOrObject { 041 042 public JetClass(@NotNull ASTNode node) { 043 super(node); 044 } 045 046 public JetClass(@NotNull PsiJetClassStub stub) { 047 super(stub, JetStubElementTypes.CLASS); 048 } 049 050 @NotNull 051 @Override 052 public List<JetDeclaration> getDeclarations() { 053 JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY); 054 if (body == null) return Collections.emptyList(); 055 056 return body.getDeclarations(); 057 } 058 059 @Override 060 public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) { 061 return visitor.visitClass(this, data); 062 } 063 064 @Nullable 065 public JetParameterList getPrimaryConstructorParameterList() { 066 return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST); 067 } 068 069 @NotNull 070 public List<JetParameter> getPrimaryConstructorParameters() { 071 JetParameterList list = getPrimaryConstructorParameterList(); 072 if (list == null) return Collections.emptyList(); 073 return list.getParameters(); 074 } 075 076 @Override 077 @Nullable 078 public JetDelegationSpecifierList getDelegationSpecifierList() { 079 return (JetDelegationSpecifierList) findChildByType(JetNodeTypes.DELEGATION_SPECIFIER_LIST); 080 } 081 082 @Override 083 @NotNull 084 public List<JetDelegationSpecifier> getDelegationSpecifiers() { 085 JetDelegationSpecifierList list = getDelegationSpecifierList(); 086 return list != null ? list.getDelegationSpecifiers() : Collections.<JetDelegationSpecifier>emptyList(); 087 } 088 089 @Nullable 090 public JetModifierList getPrimaryConstructorModifierList() { 091 return (JetModifierList) findChildByType(JetNodeTypes.PRIMARY_CONSTRUCTOR_MODIFIER_LIST); 092 } 093 094 @Override 095 @NotNull 096 public List<JetClassInitializer> getAnonymousInitializers() { 097 JetClassBody body = getBody(); 098 if (body == null) return Collections.emptyList(); 099 100 return body.getAnonymousInitializers(); 101 } 102 103 @Override 104 public boolean hasPrimaryConstructor() { 105 return getPrimaryConstructorParameterList() != null; 106 } 107 108 @Override 109 public JetObjectDeclarationName getNameAsDeclaration() { 110 return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME); 111 } 112 113 @Override 114 public JetClassBody getBody() { 115 return (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY); 116 } 117 118 @Nullable 119 public JetClassObject getClassObject() { 120 JetClassBody body = getBody(); 121 if (body == null) return null; 122 return body.getClassObject(); 123 } 124 125 public List<JetProperty> getProperties() { 126 JetClassBody body = getBody(); 127 if (body == null) return Collections.emptyList(); 128 129 return body.getProperties(); 130 } 131 132 public boolean isTrait() { 133 PsiJetClassStub stub = getStub(); 134 if (stub != null) { 135 return stub.isTrait(); 136 } 137 138 return findChildByType(JetTokens.TRAIT_KEYWORD) != null; 139 } 140 141 public boolean isEnum() { 142 PsiJetClassStub stub = getStub(); 143 if (stub != null) { 144 return stub.isEnumClass(); 145 } 146 147 return hasModifier(JetTokens.ENUM_KEYWORD); 148 } 149 150 public boolean isAnnotation() { 151 PsiJetClassStub stub = getStub(); 152 if (stub != null) { 153 return stub.isAnnotation(); 154 } 155 156 return hasModifier(JetTokens.ANNOTATION_KEYWORD); 157 } 158 159 public boolean isInner() { 160 PsiJetClassStub stub = getStub(); 161 if (stub != null) { 162 return stub.isInner(); 163 } 164 165 return hasModifier(JetTokens.INNER_KEYWORD); 166 } 167 168 @NotNull 169 @Override 170 public IStubElementType getElementType() { 171 return JetStubElementTypes.CLASS; 172 } 173 174 @Override 175 public void delete() throws IncorrectOperationException { 176 JetPsiUtil.deleteClass(this); 177 } 178 179 @Override 180 public boolean isEquivalentTo(PsiElement another) { 181 if (super.isEquivalentTo(another)) { 182 return true; 183 } 184 if (another instanceof JetClass) { 185 String fq1 = getQualifiedName(); 186 String fq2 = ((JetClass) another).getQualifiedName(); 187 return fq1 != null && fq2 != null && fq1.equals(fq2); 188 } 189 return false; 190 } 191 192 @Nullable 193 private String getQualifiedName() { 194 PsiJetClassStub stub = getStub(); 195 if (stub != null) { 196 FqName fqName = stub.getFqName(); 197 return fqName == null ? null : fqName.asString(); 198 } 199 200 List<String> parts = new ArrayList<String>(); 201 JetClassOrObject current = this; 202 while (current != null) { 203 parts.add(current.getName()); 204 current = PsiTreeUtil.getParentOfType(current, JetClassOrObject.class); 205 } 206 PsiFile file = getContainingFile(); 207 if (!(file instanceof JetFile)) return null; 208 String fileQualifiedName = ((JetFile) file).getPackageDirective().getQualifiedName(); 209 if (!fileQualifiedName.isEmpty()) { 210 parts.add(fileQualifiedName); 211 } 212 Collections.reverse(parts); 213 return StringUtil.join(parts, "."); 214 } 215 216 @Override 217 public ItemPresentation getPresentation() { 218 return ItemPresentationProviders.getItemPresentation(this); 219 } 220 }