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
;
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
) {
53 myDocComment
= isDeprecated() ?
new ClsDocCommentImpl(this) : null;
54 myNameIdentifier
= new ClsIdentifierImpl(this, getShortName());
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();
69 (docComment
!= null ?
1 : 0)
77 PsiElement
[] children
= new PsiElement
[count
];
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;*/
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) {
114 public String
getName() {
115 return getStub().getName();
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
);
133 public String
getQualifiedName() {
134 return getStub().getQualifiedName();
138 public PsiModifierList
getModifierList() {
139 return getStub().findChildStubByType(JavaStubElementTypes
.MODIFIER_LIST
).getPsi();
142 public boolean hasModifierProperty(@NotNull String name
) {
143 return getModifierList().hasModifierProperty(name
);
147 public PsiReferenceList
getExtendsList() {
148 return getStub().findChildStubByType(JavaStubElementTypes
.EXTENDS_LIST
).getPsi();
153 public PsiReferenceList
getImplementsList() {
154 return getStub().findChildStubByType(JavaStubElementTypes
.IMPLEMENTS_LIST
).getPsi();
158 public PsiClassType
[] getExtendsListTypes() {
159 return PsiClassImplUtil
.getExtendsListTypes(this);
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);
176 public PsiClass
[] getSupers() {
177 return PsiClassImplUtil
.getSupers(this);
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;
191 public Collection
<HierarchicalMethodSignature
> getVisibleSignatures() {
192 return PsiSuperMethodImplUtil
.getVisibleSignatures(this);
196 public PsiField
[] getFields() {
197 return getStub().getChildrenByType(Constants
.FIELD_BIT_SET
, PsiField
.ARRAY_FACTORY
);
201 public PsiMethod
[] getMethods() {
202 return getStub().getChildrenByType(Constants
.METHOD_BIT_SET
, PsiMethod
.ARRAY_FACTORY
);
206 public PsiMethod
[] getConstructors() {
207 return PsiImplUtil
.getConstructors(this);
211 public PsiClass
[] getInnerClasses() {
212 return getStub().getChildrenByType(JavaStubElementTypes
.CLASS
, ARRAY_FACTORY
);
216 public PsiClassInitializer
[] getInitializers() {
217 return PsiClassInitializer
.EMPTY_ARRAY
;
221 public PsiTypeParameter
[] getTypeParameters() {
222 return PsiImplUtil
.getTypeParameters(this);
226 public PsiField
[] getAllFields() {
227 return PsiClassImplUtil
.getAllFields(this);
231 public PsiMethod
[] getAllMethods() {
232 return PsiClassImplUtil
.getAllMethods(this);
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
);
249 public PsiMethod
[] findMethodsBySignature(PsiMethod patternMethod
, boolean checkBases
) {
250 return PsiClassImplUtil
.findMethodsBySignature(this, patternMethod
, checkBases
);
254 public PsiMethod
[] findMethodsByName(String name
, boolean checkBases
) {
255 return innersCache
.findMethodsByName(name
, checkBases
);
259 public List
<Pair
<PsiMethod
, PsiSubstitutor
>> findMethodsAndTheirSubstitutorsByName(String name
, boolean checkBases
) {
260 return PsiClassImplUtil
.findMethodsAndTheirSubstitutorsByName(this, name
, checkBases
);
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();
282 private String
obtainSourceFileNameFromClassFileName() {
283 final String name
= getContainingFile().getName();
284 int i
= name
.indexOf('$');
286 i
= name
.indexOf('.');
291 return name
.substring(0, i
) + ".java";
294 public PsiDocComment
getDocComment() {
298 public PsiJavaToken
getLBrace() {
302 public PsiJavaToken
getRBrace() {
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
);
329 if (!isEnum() && !isAnnotationType()) {
330 ((ClsElementImpl
)getExtendsList()).appendMirrorText(indentLevel
, buffer
);
333 if (!isInterface()) {
334 ((ClsElementImpl
)getImplementsList()).appendMirrorText(indentLevel
, buffer
);
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
) {
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
);
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);
438 visitor
.visitElement(this);
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() {
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
;
485 throw new PsiInvalidElementAccessException(this);
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);
506 public boolean isEquivalentTo(final PsiElement another
) {
507 return PsiClassImplUtil
.isClassEquivalentTo(this, another
);
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
);