update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / psi / impl / compiled / ClsClassImpl.java
blob04e05f7b1cc81e0b019400cee79945835a1ef78a
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.psi.impl.compiled;
18 import com.intellij.navigation.ItemPresentation;
19 import com.intellij.openapi.diagnostic.Logger;
20 import com.intellij.openapi.util.Pair;
21 import com.intellij.psi.*;
22 import com.intellij.psi.impl.InheritanceImplUtil;
23 import com.intellij.psi.impl.PsiClassImplUtil;
24 import com.intellij.psi.impl.PsiImplUtil;
25 import com.intellij.psi.impl.PsiSuperMethodImplUtil;
26 import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
27 import com.intellij.psi.impl.java.stubs.PsiClassStub;
28 import com.intellij.psi.impl.source.ClassInnerStuffCache;
29 import com.intellij.psi.impl.source.Constants;
30 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
31 import com.intellij.psi.impl.source.tree.TreeElement;
32 import com.intellij.psi.javadoc.PsiDocComment;
33 import com.intellij.psi.presentation.java.ClassPresentationUtil;
34 import com.intellij.psi.scope.PsiScopeProcessor;
35 import com.intellij.psi.search.SearchScope;
36 import com.intellij.util.IncorrectOperationException;
37 import org.jetbrains.annotations.NonNls;
38 import org.jetbrains.annotations.NotNull;
40 import javax.swing.*;
41 import java.util.Collection;
42 import java.util.List;
44 public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> implements PsiClass, PsiQualifiedNamedElement {
45 private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClsClassImpl");
47 private final ClassInnerStuffCache innersCache = new ClassInnerStuffCache(this);
48 private final PsiIdentifier myNameIdentifier;
49 private final PsiDocComment myDocComment;
51 public ClsClassImpl(final PsiClassStub stub) {
52 super(stub);
53 myDocComment = isDeprecated() ? new ClsDocCommentImpl(this) : null;
54 myNameIdentifier = new ClsIdentifierImpl(this, getShortName());
57 @NotNull
58 public PsiElement[] getChildren() {
59 PsiIdentifier name = getNameIdentifier();
60 PsiDocComment docComment = getDocComment();
61 PsiModifierList modifierList = getModifierList();
62 PsiReferenceList extendsList = getExtendsList();
63 PsiReferenceList implementsList = getImplementsList();
64 PsiField[] fields = getFields();
65 PsiMethod[] methods = getMethods();
66 PsiClass[] classes = getInnerClasses();
68 int count =
69 (docComment != null ? 1 : 0)
70 + 1 // modifierList
71 + 1 // name
72 + 1 // extends list
73 + 1 // implementsList
74 + fields.length
75 + methods.length
76 + classes.length;
77 PsiElement[] children = new PsiElement[count];
79 int offset = 0;
80 if (docComment != null) {
81 children[offset++] = docComment;
84 children[offset++] = modifierList;
85 children[offset++] = name;
86 children[offset++] = extendsList;
87 children[offset++] = implementsList;
89 System.arraycopy(fields, 0, children, offset, fields.length);
90 offset += fields.length;
91 System.arraycopy(methods, 0, children, offset, methods.length);
92 offset += methods.length;
93 System.arraycopy(classes, 0, children, offset, classes.length);
94 /*offset += classes.length;*/
96 return children;
99 @NotNull
100 public PsiIdentifier getNameIdentifier() {
101 return myNameIdentifier;
104 private String getShortName() {
105 String qName = getQualifiedName();
106 String name = PsiNameHelper.getShortClassName(qName);
107 if (name.length() == 0) {
108 name = "_";
110 return name;
113 @NotNull
114 public String getName() {
115 return getStub().getName();
118 @NotNull
119 public PsiTypeParameterList getTypeParameterList() {
120 return getStub().findChildStubByType(JavaStubElementTypes.TYPE_PARAMETER_LIST).getPsi();
123 public boolean hasTypeParameters() {
124 return PsiImplUtil.hasTypeParameters(this);
127 public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
128 PsiImplUtil.setName(getNameIdentifier(), name);
129 return this;
132 @NotNull
133 public String getQualifiedName() {
134 return getStub().getQualifiedName();
137 @NotNull
138 public PsiModifierList getModifierList() {
139 return getStub().findChildStubByType(JavaStubElementTypes.MODIFIER_LIST).getPsi();
142 public boolean hasModifierProperty(@NotNull String name) {
143 return getModifierList().hasModifierProperty(name);
146 @NotNull
147 public PsiReferenceList getExtendsList() {
148 return getStub().findChildStubByType(JavaStubElementTypes.EXTENDS_LIST).getPsi();
152 @NotNull
153 public PsiReferenceList getImplementsList() {
154 return getStub().findChildStubByType(JavaStubElementTypes.IMPLEMENTS_LIST).getPsi();
157 @NotNull
158 public PsiClassType[] getExtendsListTypes() {
159 return PsiClassImplUtil.getExtendsListTypes(this);
162 @NotNull
163 public PsiClassType[] getImplementsListTypes() {
164 return PsiClassImplUtil.getImplementsListTypes(this);
167 public PsiClass getSuperClass() {
168 return PsiClassImplUtil.getSuperClass(this);
171 public PsiClass[] getInterfaces() {
172 return PsiClassImplUtil.getInterfaces(this);
175 @NotNull
176 public PsiClass[] getSupers() {
177 return PsiClassImplUtil.getSupers(this);
180 @NotNull
181 public PsiClassType[] getSuperTypes() {
182 return PsiClassImplUtil.getSuperTypes(this);
185 public PsiClass getContainingClass() {
186 PsiElement parent = getParent();
187 return parent instanceof PsiClass ? (PsiClass)parent : null;
190 @NotNull
191 public Collection<HierarchicalMethodSignature> getVisibleSignatures() {
192 return PsiSuperMethodImplUtil.getVisibleSignatures(this);
195 @NotNull
196 public PsiField[] getFields() {
197 return getStub().getChildrenByType(Constants.FIELD_BIT_SET, PsiField.ARRAY_FACTORY);
200 @NotNull
201 public PsiMethod[] getMethods() {
202 return getStub().getChildrenByType(Constants.METHOD_BIT_SET, PsiMethod.ARRAY_FACTORY);
205 @NotNull
206 public PsiMethod[] getConstructors() {
207 return PsiImplUtil.getConstructors(this);
210 @NotNull
211 public PsiClass[] getInnerClasses() {
212 return getStub().getChildrenByType(JavaStubElementTypes.CLASS, ARRAY_FACTORY);
215 @NotNull
216 public PsiClassInitializer[] getInitializers() {
217 return PsiClassInitializer.EMPTY_ARRAY;
220 @NotNull
221 public PsiTypeParameter[] getTypeParameters() {
222 return PsiImplUtil.getTypeParameters(this);
225 @NotNull
226 public PsiField[] getAllFields() {
227 return PsiClassImplUtil.getAllFields(this);
230 @NotNull
231 public PsiMethod[] getAllMethods() {
232 return PsiClassImplUtil.getAllMethods(this);
235 @NotNull
236 public PsiClass[] getAllInnerClasses() {
237 return PsiClassImplUtil.getAllInnerClasses(this);
240 public PsiField findFieldByName(String name, boolean checkBases) {
241 return innersCache.findFieldByName(name, checkBases);
244 public PsiMethod findMethodBySignature(PsiMethod patternMethod, boolean checkBases) {
245 return PsiClassImplUtil.findMethodBySignature(this, patternMethod, checkBases);
248 @NotNull
249 public PsiMethod[] findMethodsBySignature(PsiMethod patternMethod, boolean checkBases) {
250 return PsiClassImplUtil.findMethodsBySignature(this, patternMethod, checkBases);
253 @NotNull
254 public PsiMethod[] findMethodsByName(String name, boolean checkBases) {
255 return innersCache.findMethodsByName(name, checkBases);
258 @NotNull
259 public List<Pair<PsiMethod, PsiSubstitutor>> findMethodsAndTheirSubstitutorsByName(String name, boolean checkBases) {
260 return PsiClassImplUtil.findMethodsAndTheirSubstitutorsByName(this, name, checkBases);
263 @NotNull
264 public List<Pair<PsiMethod, PsiSubstitutor>> getAllMethodsAndTheirSubstitutors() {
265 return PsiClassImplUtil.getAllWithSubstitutorsByMap(this, PsiMethod.class);
268 public PsiClass findInnerClassByName(String name, boolean checkBases) {
269 return innersCache.findInnerClassByName(name, checkBases);
272 public boolean isDeprecated() {
273 return getStub().isDeprecated();
276 public String getSourceFileName() {
277 final String sfn = getStub().getSourceFileName();
278 return sfn != null ? sfn : obtainSourceFileNameFromClassFileName();
281 @NonNls
282 private String obtainSourceFileNameFromClassFileName() {
283 final String name = getContainingFile().getName();
284 int i = name.indexOf('$');
285 if (i < 0) {
286 i = name.indexOf('.');
287 if (i < 0) {
288 i = name.length();
291 return name.substring(0, i) + ".java";
294 public PsiDocComment getDocComment() {
295 return myDocComment;
298 public PsiJavaToken getLBrace() {
299 return null;
302 public PsiJavaToken getRBrace() {
303 return null;
306 public boolean isInterface() {
307 return getStub().isInterface();
310 public boolean isAnnotationType() {
311 return getStub().isAnnotationType();
314 public boolean isEnum() {
315 return getStub().isEnum();
318 public void appendMirrorText(final int indentLevel, @NonNls final StringBuffer buffer) {
319 ClsDocCommentImpl docComment = (ClsDocCommentImpl)getDocComment();
320 if (docComment != null) {
321 docComment.appendMirrorText(indentLevel, buffer);
322 goNextLine(indentLevel, buffer);
324 ((ClsElementImpl)getModifierList()).appendMirrorText(indentLevel, buffer);
325 buffer.append(isEnum() ? "enum " : isAnnotationType() ? "@interface " : isInterface() ? "interface " : "class ");
326 ((ClsElementImpl)getNameIdentifier()).appendMirrorText(indentLevel, buffer);
327 ((ClsElementImpl)getTypeParameterList()).appendMirrorText(indentLevel, buffer);
328 buffer.append(' ');
329 if (!isEnum() && !isAnnotationType()) {
330 ((ClsElementImpl)getExtendsList()).appendMirrorText(indentLevel, buffer);
331 buffer.append(' ');
333 if (!isInterface()) {
334 ((ClsElementImpl)getImplementsList()).appendMirrorText(indentLevel, buffer);
336 buffer.append('{');
337 final int newIndentLevel = indentLevel + getIndentSize();
338 PsiField[] fields = getFields();
339 if (fields.length > 0) {
340 goNextLine(newIndentLevel, buffer);
341 for (int i = 0; i < fields.length; i++) {
342 PsiField field = fields[i];
343 ((ClsElementImpl)field).appendMirrorText(newIndentLevel, buffer);
344 if (field instanceof ClsEnumConstantImpl) {
345 if (i < fields.length - 1 && fields[i + 1] instanceof ClsEnumConstantImpl) {
346 buffer.append(", ");
348 else {
349 buffer.append(";");
350 if (i < fields.length - 1) {
351 goNextLine(newIndentLevel, buffer);
354 } else if (i < fields.length - 1) {
355 goNextLine(newIndentLevel, buffer);
360 PsiMethod[] methods = getMethods();
361 if (methods.length > 0) {
362 goNextLine(newIndentLevel, buffer);
363 goNextLine(newIndentLevel, buffer);
364 for (int i = 0; i < methods.length; i++) {
365 PsiMethod method = methods[i];
366 ((ClsElementImpl)method).appendMirrorText(newIndentLevel, buffer);
367 if (i < methods.length - 1) {
368 goNextLine(newIndentLevel, buffer);
369 goNextLine(newIndentLevel, buffer);
374 PsiClass[] classes = getInnerClasses();
375 if (classes.length > 0) {
376 goNextLine(newIndentLevel, buffer);
377 goNextLine(newIndentLevel, buffer);
378 for (int i = 0; i < classes.length; i++) {
379 PsiClass aClass = classes[i];
380 ((ClsElementImpl)aClass).appendMirrorText(newIndentLevel, buffer);
381 if (i < classes.length - 1) {
382 goNextLine(newIndentLevel, buffer);
383 goNextLine(newIndentLevel, buffer);
387 goNextLine(indentLevel, buffer);
388 buffer.append('}');
391 public void setMirror(@NotNull TreeElement element) {
392 setMirrorCheckingType(element, null);
394 PsiClass mirror = (PsiClass)SourceTreeToPsiMap.treeElementToPsi(element);
396 final PsiDocComment docComment = getDocComment();
397 if (docComment != null) {
398 ((ClsElementImpl)docComment).setMirror((TreeElement)SourceTreeToPsiMap.psiElementToTree(mirror.getDocComment()));
400 ((ClsElementImpl)getModifierList()).setMirror((TreeElement)SourceTreeToPsiMap.psiElementToTree(mirror.getModifierList()));
401 ((ClsElementImpl)getNameIdentifier()).setMirror((TreeElement)SourceTreeToPsiMap.psiElementToTree(mirror.getNameIdentifier()));
402 if (!isAnnotationType() && !isEnum()) {
403 ((ClsElementImpl)getExtendsList()).setMirror((TreeElement)SourceTreeToPsiMap.psiElementToTree(mirror.getExtendsList()));
405 ((ClsElementImpl)getImplementsList()).setMirror((TreeElement)SourceTreeToPsiMap.psiElementToTree(mirror.getImplementsList()));
406 ((ClsElementImpl)getTypeParameterList()).setMirror((TreeElement)SourceTreeToPsiMap.psiElementToTree(mirror.getTypeParameterList()));
408 PsiField[] fields = getFields();
409 PsiField[] mirrorFields = mirror.getFields();
410 if (LOG.assertTrue(fields.length == mirrorFields.length)) {
411 for (int i = 0; i < fields.length; i++) {
412 ((ClsElementImpl)fields[i]).setMirror((TreeElement)SourceTreeToPsiMap.psiElementToTree(mirrorFields[i]));
416 PsiMethod[] methods = getMethods();
417 PsiMethod[] mirrorMethods = mirror.getMethods();
418 if (LOG.assertTrue(methods.length == mirrorMethods.length)) {
419 for (int i = 0; i < methods.length; i++) {
420 ((ClsElementImpl)methods[i]).setMirror((TreeElement)SourceTreeToPsiMap.psiElementToTree(mirrorMethods[i]));
424 PsiClass[] classes = getInnerClasses();
425 PsiClass[] mirrorClasses = mirror.getInnerClasses();
426 if (LOG.assertTrue(classes.length == mirrorClasses.length)) {
427 for (int i = 0; i < classes.length; i++) {
428 ((ClsElementImpl)classes[i]).setMirror((TreeElement)SourceTreeToPsiMap.psiElementToTree(mirrorClasses[i]));
433 public void accept(@NotNull PsiElementVisitor visitor) {
434 if (visitor instanceof JavaElementVisitor) {
435 ((JavaElementVisitor)visitor).visitClass(this);
437 else {
438 visitor.visitElement(this);
442 @NonNls
443 public String toString() {
444 return "PsiClass:" + getName();
447 public boolean processDeclarations(@NotNull PsiScopeProcessor processor,
448 @NotNull ResolveState state,
449 PsiElement lastParent,
450 @NotNull PsiElement place) {
451 return PsiClassImplUtil.processDeclarationsInClass(this, processor, state, null, lastParent, place, false);
454 public PsiElement getScope() {
455 return getParent();
458 public boolean isInheritorDeep(PsiClass baseClass, PsiClass classToByPass) {
459 return InheritanceImplUtil.isInheritorDeep(this, baseClass, classToByPass);
462 public boolean isInheritor(@NotNull PsiClass baseClass, boolean checkDeep) {
463 return InheritanceImplUtil.isInheritor(this, baseClass, checkDeep);
466 public PsiClass getSourceMirrorClass() {
467 PsiElement parent = getParent();
468 final String name = getName();
469 if (parent instanceof PsiFile) {
470 PsiClassOwner fileNavigationElement = (PsiClassOwner)parent.getNavigationElement();
471 for (PsiClass aClass : fileNavigationElement.getClasses()) {
472 if (name.equals(aClass.getName())) return aClass;
475 else if (parent != null) {
476 ClsClassImpl parentClass = (ClsClassImpl)parent;
477 PsiClass parentSourceMirror = parentClass.getSourceMirrorClass();
478 if (parentSourceMirror == null) return null;
479 PsiClass[] innerClasses = parentSourceMirror.getInnerClasses();
480 for (PsiClass innerClass : innerClasses) {
481 if (name.equals(innerClass.getName())) return innerClass;
484 else {
485 throw new PsiInvalidElementAccessException(this);
488 return null;
491 @NotNull
492 public PsiElement getNavigationElement() {
493 PsiClass aClass = getSourceMirrorClass();
494 return aClass != null ? aClass : this;
497 public ItemPresentation getPresentation() {
498 return ClassPresentationUtil.getPresentation(this);
501 public Icon getElementIcon(final int flags) {
502 return PsiClassImplUtil.getClassIcon(flags, this);
505 @Override
506 public boolean isEquivalentTo(final PsiElement another) {
507 return PsiClassImplUtil.isClassEquivalentTo(this, another);
510 @NotNull
511 public SearchScope getUseScope() {
512 return PsiClassImplUtil.getClassUseScope(this);
515 public PsiQualifiedNamedElement getContainer() {
516 final PsiFile file = getContainingFile();
517 final PsiDirectory dir;
518 return file == null ? null : (dir = file.getContainingDirectory()) == null
519 ? null : JavaDirectoryService.getInstance().getPackage(dir);