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