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 }