update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / psi / impl / ElementPresentationUtil.java
blobc6df423c7ca75192c9c4188cbbb4d32489a6daf4
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;
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;
37 import javax.swing.*;
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;
71 return flags;
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) {
97 return vFile != null
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);
121 if (value == null) {
122 value = aClass.getManager().getCachedValuesManager().createCachedValue(new CachedValueProvider<Integer>() {
123 public Result<Integer> compute() {
124 return Result.createSingleDependency(Integer.valueOf(getClassKindImpl(aClass)), aClass);
126 }, false);
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);
156 if (isException) {
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);
171 static {
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) {
199 String noun;
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");
203 else return null;
204 String adj = getFlagsDescription(member);
205 return (adj + " " + noun).trim();
208 private static String getClassNoun(final PsiClass aClass) {
209 String noun;
210 int kind = getClassKind(aClass);
211 switch (kind) {
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;
219 default:
220 case CLASS_KIND_CLASS: noun = CodeInsightBundle.message("node.class.tooltip"); break;
222 return noun;
225 private static String getFlagsDescription(final PsiModifierListOwner aClass) {
226 int flags = getFlags(aClass, false);
227 String adj = "";
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();
233 if (list != null) {
234 int level = PsiUtil.getAccessLevel(list);
235 if (level != PsiUtil.ACCESS_LEVEL_PUBLIC) {
236 adj += " " + StringUtil.capitalize(PsiBundle.visibilityPresentation(PsiUtil.getAccessModifier(level)));
239 return adj;
243 static {
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);
255 return baseIcon;