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
;
18 import com
.intellij
.codeInsight
.CodeInsightBundle
;
19 import com
.intellij
.codeInsight
.TestUtil
;
20 import com
.intellij
.compiler
.CompilerConfiguration
;
21 import com
.intellij
.openapi
.project
.DumbService
;
22 import com
.intellij
.openapi
.project
.Project
;
23 import com
.intellij
.openapi
.roots
.ProjectRootManager
;
24 import com
.intellij
.openapi
.util
.IconLoader
;
25 import com
.intellij
.openapi
.util
.Iconable
;
26 import com
.intellij
.openapi
.util
.Key
;
27 import com
.intellij
.openapi
.util
.text
.StringUtil
;
28 import com
.intellij
.openapi
.vfs
.VirtualFile
;
29 import com
.intellij
.psi
.*;
30 import com
.intellij
.psi
.impl
.source
.jsp
.jspJava
.JspClass
;
31 import com
.intellij
.psi
.util
.*;
32 import com
.intellij
.ui
.RowIcon
;
33 import com
.intellij
.util
.Icons
;
34 import com
.intellij
.util
.VisibilityIcons
;
35 import gnu
.trove
.TIntObjectHashMap
;
39 public class ElementPresentationUtil
{
40 private static final Icon STATIC_MARK_ICON
= IconLoader
.getIcon("/nodes/staticMark.png");
41 private static final Icon FINAL_MARK_ICON
= IconLoader
.getIcon("/nodes/finalMark.png");
42 public static final Icon JUNIT_TEST_MARK
= IconLoader
.getIcon("/nodes/junitTestMark.png");
43 private static final Icon RUNNABLE_MARK
= IconLoader
.getIcon("/nodes/runnableMark.png");
46 private ElementPresentationUtil() {
50 public static int getFlags(PsiModifierListOwner element
, final boolean isLocked
) {
51 final PsiFile containingFile
= element
.getContainingFile();
52 final VirtualFile vFile
= containingFile
== null ?
null : containingFile
.getVirtualFile();
53 final boolean isEnum
= element
instanceof PsiClass
&& ((PsiClass
)element
).isEnum();
54 int flags
= (element
.hasModifierProperty(PsiModifier
.FINAL
) && !isEnum ? FLAGS_FINAL
: 0)
55 | (element
.hasModifierProperty(PsiModifier
.STATIC
) && !isEnum ? FLAGS_STATIC
: 0)
56 | (isLocked ? ElementBase
.FLAGS_LOCKED
: 0)
57 | (isExcluded(vFile
, element
.getProject()) ? FLAGS_EXCLUDED
: 0);
58 if (element
instanceof PsiClass
) {
59 final PsiClass aClass
= (PsiClass
)element
;
60 if (element
.hasModifierProperty(PsiModifier
.ABSTRACT
) && !((PsiClass
)element
).isInterface()) {
61 flags
|= FLAGS_ABSTRACT
;
63 int kind
= getClassKind(aClass
);
64 if (kind
== CLASS_KIND_JUNIT_TEST
) {
65 flags
|= FLAGS_JUNIT_TEST
;
67 else if (kind
== CLASS_KIND_RUNNABLE
) {
68 flags
|= FLAGS_RUNNABLE
;
74 private static final Icon ABSTRACT_EXCEPTION_CLASS_ICON
= IconLoader
.getIcon("/nodes/abstractException.png");
76 private static final int CLASS_KIND_INTERFACE
= 10;
77 private static final int CLASS_KIND_ANNOTATION
= 20;
78 public static final int CLASS_KIND_CLASS
= 30;
79 private static final int CLASS_KIND_ANONYMOUS
= 40;
80 private static final int CLASS_KIND_ENUM
= 50;
81 private static final int CLASS_KIND_ASPECT
= 60;
82 private static final int CLASS_KIND_JSP
= 70;
83 public static final int CLASS_KIND_EXCEPTION
= 80;
84 private static final int CLASS_KIND_JUNIT_TEST
= 90;
85 private static final int CLASS_KIND_RUNNABLE
= 100;
87 private static final int FLAGS_ABSTRACT
= 0x100;
88 private static final int FLAGS_STATIC
= 0x200;
89 private static final int FLAGS_FINAL
= 0x400;
90 public static final int FLAGS_EXCLUDED
= 0x1000;
91 private static final int FLAGS_JUNIT_TEST
= 0x2000;
92 private static final int FLAGS_RUNNABLE
= 0x4000;
94 private static final Key
<CachedValue
<Integer
>> CLASS_KIND_KEY
= new Key
<CachedValue
<Integer
>>("CLASS_KIND_KEY");
96 public static boolean isExcluded(final VirtualFile vFile
, final Project project
) {
98 && ProjectRootManager
.getInstance(project
).getFileIndex().isInSource(vFile
)
99 && CompilerConfiguration
.getInstance(project
).isExcludedFromCompilation(vFile
);
102 public static int getBasicClassKind(PsiClass aClass
) {
103 if (!aClass
.isValid()) return CLASS_KIND_CLASS
;
105 if (aClass
.isAnnotationType()) return CLASS_KIND_ANNOTATION
;
106 if (aClass
.isEnum()) return CLASS_KIND_ENUM
;
107 if (aClass
.isInterface()) return CLASS_KIND_INTERFACE
;
108 if (aClass
instanceof JspClass
) return CLASS_KIND_JSP
;
109 if (aClass
instanceof PsiAnonymousClass
) return CLASS_KIND_ANONYMOUS
;
111 return CLASS_KIND_CLASS
;
114 public static int getClassKind(final PsiClass aClass
) {
115 if (!aClass
.isValid()) {
116 aClass
.putUserData(CLASS_KIND_KEY
, null);
117 return CLASS_KIND_CLASS
;
120 CachedValue
<Integer
> value
= aClass
.getUserData(CLASS_KIND_KEY
);
122 value
= aClass
.getManager().getCachedValuesManager().createCachedValue(new CachedValueProvider
<Integer
>() {
123 public Result
<Integer
> compute() {
124 return Result
.createSingleDependency(Integer
.valueOf(getClassKindImpl(aClass
)), aClass
);
127 aClass
.putUserData(CLASS_KIND_KEY
, value
);
129 return value
.getValue().intValue();
132 private static int getClassKindImpl(PsiClass aClass
) {
133 if (!aClass
.isValid()) return CLASS_KIND_CLASS
;
135 if (aClass
.isAnnotationType()) {
136 return CLASS_KIND_ANNOTATION
;
138 if (aClass
.isEnum()) {
139 return CLASS_KIND_ENUM
;
141 if (aClass
.isInterface()) {
142 return CLASS_KIND_INTERFACE
;
144 if (aClass
instanceof JspClass
) {
145 return CLASS_KIND_JSP
;
147 if (aClass
instanceof PsiAnonymousClass
) {
148 return CLASS_KIND_ANONYMOUS
;
151 if (!DumbService
.getInstance(aClass
.getProject()).isDumb()) {
152 final PsiManager manager
= aClass
.getManager();
153 final PsiClass javaLangTrowable
=
154 JavaPsiFacade
.getInstance(manager
.getProject()).findClass("java.lang.Throwable", aClass
.getResolveScope());
155 final boolean isException
= javaLangTrowable
!= null && InheritanceUtil
.isInheritorOrSelf(aClass
, javaLangTrowable
, true);
157 return CLASS_KIND_EXCEPTION
;
160 if (TestUtil
.isTestClass(aClass
)) {
161 return CLASS_KIND_JUNIT_TEST
;
164 if (PsiClassUtil
.isRunnableClass(aClass
, false) && PsiMethodUtil
.findMainMethod(aClass
) != null) {
165 return CLASS_KIND_RUNNABLE
;
167 return CLASS_KIND_CLASS
;
170 private static final TIntObjectHashMap
<Icon
> BASE_ICON
= new TIntObjectHashMap
<Icon
>(20);
172 BASE_ICON
.put(CLASS_KIND_CLASS
, Icons
.CLASS_ICON
);
173 BASE_ICON
.put(CLASS_KIND_CLASS
| FLAGS_ABSTRACT
, Icons
.ABSTRACT_CLASS_ICON
);
174 BASE_ICON
.put(CLASS_KIND_ANNOTATION
, Icons
.ANNOTATION_TYPE_ICON
);
175 BASE_ICON
.put(CLASS_KIND_ANNOTATION
| FLAGS_ABSTRACT
, Icons
.ANNOTATION_TYPE_ICON
);
176 BASE_ICON
.put(CLASS_KIND_ANONYMOUS
, Icons
.ANONYMOUS_CLASS_ICON
);
177 BASE_ICON
.put(CLASS_KIND_ANONYMOUS
| FLAGS_ABSTRACT
, Icons
.ANONYMOUS_CLASS_ICON
);
178 BASE_ICON
.put(CLASS_KIND_ASPECT
, Icons
.ASPECT_ICON
);
179 BASE_ICON
.put(CLASS_KIND_ASPECT
| FLAGS_ABSTRACT
, Icons
.ASPECT_ICON
);
180 BASE_ICON
.put(CLASS_KIND_ENUM
, Icons
.ENUM_ICON
);
181 BASE_ICON
.put(CLASS_KIND_ENUM
| FLAGS_ABSTRACT
, Icons
.ENUM_ICON
);
182 BASE_ICON
.put(CLASS_KIND_EXCEPTION
, Icons
.EXCEPTION_CLASS_ICON
);
183 BASE_ICON
.put(CLASS_KIND_EXCEPTION
| FLAGS_ABSTRACT
, ABSTRACT_EXCEPTION_CLASS_ICON
);
184 BASE_ICON
.put(CLASS_KIND_INTERFACE
, Icons
.INTERFACE_ICON
);
185 BASE_ICON
.put(CLASS_KIND_INTERFACE
| FLAGS_ABSTRACT
, Icons
.INTERFACE_ICON
);
186 BASE_ICON
.put(CLASS_KIND_JSP
, Icons
.JSP_ICON
);
187 BASE_ICON
.put(CLASS_KIND_JSP
| FLAGS_ABSTRACT
, Icons
.JSP_ICON
);
188 BASE_ICON
.put(CLASS_KIND_JUNIT_TEST
, Icons
.CLASS_ICON
);
189 BASE_ICON
.put(CLASS_KIND_JUNIT_TEST
| FLAGS_ABSTRACT
, Icons
.ABSTRACT_CLASS_ICON
);
190 BASE_ICON
.put(CLASS_KIND_RUNNABLE
, Icons
.CLASS_ICON
);
193 public static Icon
getClassIconOfKind(PsiClass aClass
, int classKind
) {
194 final boolean isAbstract
= aClass
.hasModifierProperty(PsiModifier
.ABSTRACT
);
195 return BASE_ICON
.get(classKind
| (isAbstract ? FLAGS_ABSTRACT
: 0));
198 public static String
getDescription(PsiModifierListOwner member
) {
200 if (member
instanceof PsiClass
) noun
= getClassNoun((PsiClass
)member
);
201 else if (member
instanceof PsiMethod
) noun
= CodeInsightBundle
.message("node.method.tooltip");
202 else if (member
instanceof PsiField
) noun
= CodeInsightBundle
.message("node.field.tooltip");
204 String adj
= getFlagsDescription(member
);
205 return (adj
+ " " + noun
).trim();
208 private static String
getClassNoun(final PsiClass aClass
) {
210 int kind
= getClassKind(aClass
);
212 case CLASS_KIND_ANNOTATION
: noun
= CodeInsightBundle
.message("node.annotation.tooltip"); break;
213 case CLASS_KIND_ANONYMOUS
: noun
= CodeInsightBundle
.message("node.anonymous.class.tooltip"); break;
214 case CLASS_KIND_ENUM
: noun
= CodeInsightBundle
.message("node.enum.tooltip"); break;
215 case CLASS_KIND_EXCEPTION
: noun
= CodeInsightBundle
.message("node.exception.tooltip"); break;
216 case CLASS_KIND_INTERFACE
: noun
= CodeInsightBundle
.message("node.interface.tooltip"); break;
217 case CLASS_KIND_JUNIT_TEST
: noun
= CodeInsightBundle
.message("node.junit.test.tooltip"); break;
218 case CLASS_KIND_RUNNABLE
: noun
= CodeInsightBundle
.message("node.runnable.class.tooltip"); break;
220 case CLASS_KIND_CLASS
: noun
= CodeInsightBundle
.message("node.class.tooltip"); break;
225 private static String
getFlagsDescription(final PsiModifierListOwner aClass
) {
226 int flags
= getFlags(aClass
, false);
228 if ((flags
& FLAGS_EXCLUDED
) != 0) adj
+= " " + CodeInsightBundle
.message("node.excluded.flag.tooltip");
229 if ((flags
& FLAGS_ABSTRACT
) != 0) adj
+= " " + CodeInsightBundle
.message("node.abstract.flag.tooltip");
230 if ((flags
& FLAGS_FINAL
) != 0) adj
+= " " + CodeInsightBundle
.message("node.final.flag.tooltip");
231 if ((flags
& FLAGS_STATIC
) != 0) adj
+= " " + CodeInsightBundle
.message("node.static.flag.tooltip");
232 PsiModifierList list
= aClass
.getModifierList();
234 int level
= PsiUtil
.getAccessLevel(list
);
235 if (level
!= PsiUtil
.ACCESS_LEVEL_PUBLIC
) {
236 adj
+= " " + StringUtil
.capitalize(PsiBundle
.visibilityPresentation(PsiUtil
.getAccessModifier(level
)));
244 ElementBase
.registerIconLayer(FLAGS_STATIC
, STATIC_MARK_ICON
);
245 ElementBase
.registerIconLayer(FLAGS_EXCLUDED
, Icons
.EXCLUDED_FROM_COMPILE_ICON
);
246 ElementBase
.registerIconLayer(FLAGS_FINAL
, FINAL_MARK_ICON
);
247 ElementBase
.registerIconLayer(FLAGS_JUNIT_TEST
, JUNIT_TEST_MARK
);
248 ElementBase
.registerIconLayer(FLAGS_RUNNABLE
, RUNNABLE_MARK
);
251 public static Icon
addVisibilityIcon(final PsiModifierListOwner element
, final int flags
, final RowIcon baseIcon
) {
252 if ((flags
& Iconable
.ICON_FLAG_VISIBILITY
) != 0) {
253 VisibilityIcons
.setVisibilityIcon(element
.getModifierList(), baseIcon
);