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
.usages
.impl
.rules
;
18 import com
.intellij
.openapi
.actionSystem
.DataKey
;
19 import com
.intellij
.openapi
.actionSystem
.DataSink
;
20 import com
.intellij
.openapi
.actionSystem
.LangDataKeys
;
21 import com
.intellij
.openapi
.actionSystem
.TypeSafeDataProvider
;
22 import com
.intellij
.openapi
.util
.Iconable
;
23 import com
.intellij
.openapi
.vcs
.FileStatus
;
24 import com
.intellij
.openapi
.vfs
.VirtualFile
;
25 import com
.intellij
.psi
.*;
26 import com
.intellij
.psi
.jsp
.JspFile
;
27 import com
.intellij
.psi
.util
.PsiTreeUtil
;
28 import com
.intellij
.usageView
.UsageInfo
;
29 import com
.intellij
.usages
.Usage
;
30 import com
.intellij
.usages
.UsageGroup
;
31 import com
.intellij
.usages
.UsageView
;
32 import com
.intellij
.usages
.rules
.PsiElementUsage
;
33 import com
.intellij
.usages
.rules
.UsageGroupingRule
;
34 import org
.jetbrains
.annotations
.NotNull
;
41 public class ClassGroupingRule
implements UsageGroupingRule
{
42 public UsageGroup
groupUsage(Usage usage
) {
43 if (!(usage
instanceof PsiElementUsage
)) {
46 final PsiElement psiElement
= ((PsiElementUsage
)usage
).getElement();
47 final PsiFile containingFile
= psiElement
.getContainingFile();
49 if (!(containingFile
instanceof PsiJavaFile
) || containingFile
instanceof JspFile
) {
52 PsiElement containingClass
= psiElement
;
54 containingClass
= PsiTreeUtil
.getParentOfType(containingClass
, PsiClass
.class, true);
55 if (containingClass
== null || ((PsiClass
)containingClass
).getQualifiedName() != null) break;
59 if (containingClass
== null) {
60 // check whether the element is in the import list
61 PsiImportList importList
= PsiTreeUtil
.getParentOfType(psiElement
, PsiImportList
.class, true);
62 if (importList
!= null) {
63 final String fileName
= getFileNameWithoutExtension(containingFile
);
64 final PsiClass
[] classes
= ((PsiJavaFile
)containingFile
).getClasses();
65 for (final PsiClass aClass
: classes
) {
66 if (fileName
.equals(aClass
.getName())) {
67 containingClass
= aClass
;
74 // skip JspClass synthetic classes.
75 if (containingClass
.getParent() instanceof PsiFile
&& JspPsiUtil
.isInJspFile(containingClass
)) {
76 containingClass
= null;
80 if (containingClass
!= null) {
81 return new ClassUsageGroup((PsiClass
)containingClass
);
84 final VirtualFile virtualFile
= containingFile
.getVirtualFile();
85 if (virtualFile
!= null) {
86 return new FileGroupingRule
.FileUsageGroup(containingFile
.getProject(), virtualFile
);
91 private static String
getFileNameWithoutExtension(final PsiFile file
) {
92 final String name
= file
.getName();
93 final int index
= name
.lastIndexOf('.');
94 return index
< 0? name
: name
.substring(0, index
);
97 private static class ClassUsageGroup
implements UsageGroup
, TypeSafeDataProvider
{
98 private final SmartPsiElementPointer myClassPointer
;
99 private final String myText
;
100 private final String myQName
;
103 public ClassUsageGroup(PsiClass aClass
) {
104 myQName
= aClass
.getQualifiedName();
105 myText
= createText(aClass
);
106 myClassPointer
= SmartPointerManager
.getInstance(aClass
.getProject()).createLazyPointer(aClass
);
110 public void update() {
112 myIcon
= getPsiClass().getIcon(Iconable
.ICON_FLAG_VISIBILITY
| Iconable
.ICON_FLAG_READ_STATUS
);
116 private static String
createText(PsiClass aClass
) {
117 String text
= aClass
.getName();
118 PsiClass containingClass
= aClass
.getContainingClass();
119 while (containingClass
!= null) {
120 text
= containingClass
.getName() + '.' + text
;
121 containingClass
= containingClass
.getContainingClass();
126 public Icon
getIcon(boolean isOpen
) {
131 public String
getText(UsageView view
) {
135 public FileStatus
getFileStatus() {
136 return isValid() ?
getPsiClass().getFileStatus() : null;
139 private PsiClass
getPsiClass() {
140 return (PsiClass
)myClassPointer
.getElement();
143 public boolean isValid() {
144 PsiClass psiClass
= getPsiClass();
145 return psiClass
!= null && psiClass
.isValid();
148 public int hashCode() {
149 return myQName
.hashCode();
152 public boolean equals(Object object
) {
153 return object
instanceof ClassUsageGroup
&& myQName
.equals(((ClassUsageGroup
)object
).myQName
);
156 public void navigate(boolean focus
) throws UnsupportedOperationException
{
158 getPsiClass().navigate(focus
);
162 public boolean canNavigate() {
166 public boolean canNavigateToSource() {
167 return canNavigate();
170 public int compareTo(UsageGroup usageGroup
) {
171 return getText(null).compareTo(usageGroup
.getText(null));
174 public void calcData(final DataKey key
, final DataSink sink
) {
175 if (!isValid()) return;
176 if (LangDataKeys
.PSI_ELEMENT
== key
) {
177 sink
.put(LangDataKeys
.PSI_ELEMENT
, getPsiClass());
179 if (UsageView
.USAGE_INFO_KEY
== key
) {
180 PsiClass psiClass
= getPsiClass();
181 if (psiClass
!= null) {
182 sink
.put(UsageView
.USAGE_INFO_KEY
, new UsageInfo(psiClass
));