support of spring beans in JSF EL
[fedora-idea.git] / source / com / intellij / psi / impl / ElementBase.java
blob6a9cba353f0c9d748d46b13bf2bdd1e41ce95ccf
1 package com.intellij.psi.impl;
3 import com.intellij.codeInsight.CodeInsightBundle;
4 import com.intellij.codeInsight.TestUtil;
5 import com.intellij.compiler.CompilerConfiguration;
6 import com.intellij.lang.ant.PsiAntElement;
7 import com.intellij.navigation.ItemPresentation;
8 import com.intellij.openapi.project.Project;
9 import com.intellij.openapi.roots.ProjectRootManager;
10 import com.intellij.openapi.util.IconLoader;
11 import com.intellij.openapi.util.Iconable;
12 import com.intellij.openapi.util.Key;
13 import com.intellij.openapi.util.UserDataHolderBase;
14 import com.intellij.openapi.util.text.StringUtil;
15 import com.intellij.openapi.vfs.VirtualFile;
16 import com.intellij.psi.*;
17 import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
18 import com.intellij.psi.util.*;
19 import com.intellij.psi.xml.XmlTag;
20 import com.intellij.ui.LayeredIcon;
21 import com.intellij.ui.RowIcon;
22 import com.intellij.util.IconUtil;
23 import com.intellij.util.Icons;
24 import com.intellij.util.SmartList;
25 import gnu.trove.TIntObjectHashMap;
26 import org.jetbrains.annotations.Nullable;
28 import javax.swing.*;
29 import java.util.List;
31 public abstract class ElementBase extends UserDataHolderBase implements Iconable {
32 private static final Icon STATIC_MARK_ICON = IconLoader.getIcon("/nodes/staticMark.png");
33 private static final Icon FINAL_MARK_ICON = IconLoader.getIcon("/nodes/finalMark.png");
34 private static final Icon JUNIT_TEST_MARK = IconLoader.getIcon("/nodes/junitTestMark.png");
35 private static final Icon RUNNABLE_MARK = IconLoader.getIcon("/nodes/runnableMark.png");
37 @Nullable
38 public Icon getIcon(int flags) {
39 if (!(this instanceof PsiElement)) return null;
41 final PsiElement element = (PsiElement)this;
43 final Icon providersIcon = IconUtil.getProvidersIcon(element, flags);
44 if (providersIcon != null) {
45 final RowIcon rowIcon = providersIcon instanceof RowIcon ? (RowIcon)providersIcon : createLayeredIcon(providersIcon, flags);
46 return addVisibilityIcon(element, flags, rowIcon);
49 boolean visibilityAdded = false;
50 RowIcon baseIcon;
51 final boolean isLocked = (flags & ICON_FLAG_READ_STATUS) != 0 && !element.isWritable();
52 int elementFlags = isLocked ? FLAGS_LOCKED : 0;
53 if (element instanceof ItemPresentation && ((ItemPresentation)element).getIcon(false) != null) {
54 baseIcon = createLayeredIcon(((ItemPresentation)element).getIcon(false), elementFlags);
55 } else if (element instanceof PsiDirectory) {
56 Icon symbolIcon;
57 final PsiDirectory psiDirectory = (PsiDirectory)element;
58 if (psiDirectory.getPackage() != null) {
59 symbolIcon = Icons.PACKAGE_ICON;
61 else {
62 symbolIcon = Icons.DIRECTORY_CLOSED_ICON;
64 final VirtualFile vFile = psiDirectory.getVirtualFile();
65 final Project project = psiDirectory.getProject();
66 boolean isExcluded = isExcluded(vFile, project);
67 baseIcon = createLayeredIcon(symbolIcon, elementFlags | (isExcluded ? FLAGS_EXCLUDED : 0));
69 else if (element instanceof PsiPackage) {
70 baseIcon = createLayeredIcon(Icons.PACKAGE_ICON, elementFlags);
72 else if (element instanceof PsiFile) {
73 PsiFile file = (PsiFile)element;
75 VirtualFile virtualFile = file.getVirtualFile();
76 final Icon fileTypeIcon;
77 if (virtualFile == null) {
78 fileTypeIcon = file.getFileType().getIcon();
80 else {
81 fileTypeIcon = IconUtil.getIcon(virtualFile, flags & ~ICON_FLAG_READ_STATUS, file.getProject());
82 if (fileTypeIcon instanceof RowIcon) {
83 visibilityAdded = true;
86 baseIcon = createLayeredIcon(fileTypeIcon, elementFlags);
88 else if (element instanceof PsiClass) {
89 final PsiClass aClass = (PsiClass)element;
90 Icon symbolIcon = getClassBaseIcon(aClass);
91 baseIcon = createLayeredIcon(symbolIcon, getFlags(aClass, isLocked));
93 else if (element instanceof PsiMethod) {
94 final PsiMethod method = (PsiMethod)element;
95 Icon methodIcon = method.hasModifierProperty(PsiModifier.ABSTRACT) ? Icons.ABSTRACT_METHOD_ICON : Icons.METHOD_ICON;
96 baseIcon = createLayeredIcon(methodIcon, getFlags(method, false));
98 else if (element instanceof PsiField) {
99 baseIcon = createLayeredIcon(Icons.FIELD_ICON, getFlags((PsiField)element, false));
101 else if (element instanceof PsiParameter) {
102 baseIcon = createLayeredIcon(Icons.PARAMETER_ICON, 0);
104 else if (element instanceof PsiVariable) {
105 baseIcon = createLayeredIcon(Icons.VARIABLE_ICON, getFlags((PsiVariable)element, false));
107 else if (element instanceof XmlTag) {
108 return Icons.XML_TAG_ICON;
110 else if (element instanceof PsiAntElement) {
111 return ((PsiAntElement)element).getRole().getIcon();
113 else if (element instanceof PsiClassObjectAccessExpression) {
114 final RowIcon rowIcon = createLayeredIcon(Icons.FIELD_ICON, 0);
115 rowIcon.setIcon(Icons.PUBLIC_ICON, 1);
116 return rowIcon;
118 else if (element instanceof PsiClassInitializer) {
119 return createLayeredIcon(Icons.CLASS_INITIALIZER, getFlags((PsiClassInitializer)element, false));
121 else {
122 return null;
124 return visibilityAdded ? baseIcon : addVisibilityIcon(element, flags, baseIcon);
127 private static Icon addVisibilityIcon(final PsiElement element, final int flags, final RowIcon baseIcon) {
128 if ((flags & ICON_FLAG_VISIBILITY) != 0) {
129 PsiModifierList modifierList = element instanceof PsiModifierListOwner ? ((PsiModifierListOwner)element).getModifierList() : null;
130 IconUtil.setVisibilityIcon(modifierList, baseIcon);
132 return baseIcon;
135 private static boolean isExcluded(final VirtualFile vFile, final Project project) {
136 return vFile != null
137 && ProjectRootManager.getInstance(project).getFileIndex().isInSource(vFile)
138 && CompilerConfiguration.getInstance(project).isExcludedFromCompilation(vFile);
141 public static int getFlags(PsiModifierListOwner element, final boolean isLocked) {
142 final PsiFile containingFile = element.getContainingFile();
143 final VirtualFile vFile = containingFile == null ? null : containingFile.getVirtualFile();
144 final boolean isEnum = element instanceof PsiClass && ((PsiClass)element).isEnum();
145 int flags = (element.hasModifierProperty(PsiModifier.FINAL) && !isEnum ? FLAGS_FINAL : 0)
146 | (element.hasModifierProperty(PsiModifier.STATIC) && !isEnum ? FLAGS_STATIC : 0)
147 | (isLocked ? FLAGS_LOCKED : 0)
148 | (isExcluded(vFile, element.getProject()) ? FLAGS_EXCLUDED : 0);
149 if (element instanceof PsiClass) {
150 final PsiClass aClass = (PsiClass)element;
151 if (element.hasModifierProperty(PsiModifier.ABSTRACT) && !((PsiClass)element).isInterface()) {
152 flags |= FLAGS_ABSTRACT;
154 int kind = getClassKind(aClass);
155 if (kind == CLASS_KIND_JUNIT_TEST) {
156 flags |= FLAGS_JUNIT_TEST;
158 else if (kind == CLASS_KIND_RUNNABLE) {
159 flags |= FLAGS_RUNNABLE;
162 return flags;
165 private static final Icon ABSTRACT_EXCEPTION_CLASS_ICON = IconLoader.getIcon("/nodes/abstractException.png");
167 private static final int CLASS_KIND_INTERFACE = 10;
168 private static final int CLASS_KIND_ANNOTATION = 20;
169 public static final int CLASS_KIND_CLASS = 30;
170 private static final int CLASS_KIND_ANONYMOUS = 40;
171 private static final int CLASS_KIND_ENUM = 50;
172 private static final int CLASS_KIND_ASPECT = 60;
173 private static final int CLASS_KIND_JSP = 70;
174 public static final int CLASS_KIND_EXCEPTION = 80;
175 private static final int CLASS_KIND_JUNIT_TEST = 90;
176 private static final int CLASS_KIND_RUNNABLE = 100;
178 private static final int FLAGS_ABSTRACT = 0x100;
179 private static final int FLAGS_STATIC = 0x200;
180 private static final int FLAGS_FINAL = 0x400;
181 private static final int FLAGS_LOCKED = 0x800;
182 private static final int FLAGS_EXCLUDED = 0x1000;
183 private static final int FLAGS_JUNIT_TEST = 0x2000;
184 private static final int FLAGS_RUNNABLE = 0x4000;
186 private static final Key<CachedValue<Integer>> CLASS_KIND_KEY = new Key<CachedValue<Integer>>("CLASS_KIND_KEY");
188 public static int getClassKind(final PsiClass aClass) {
189 if (!aClass.isValid()) {
190 aClass.putUserData(CLASS_KIND_KEY, null);
191 return CLASS_KIND_CLASS;
194 CachedValue<Integer> value = aClass.getUserData(CLASS_KIND_KEY);
195 if (value == null) {
196 value = aClass.getManager().getCachedValuesManager().createCachedValue(new CachedValueProvider<Integer>() {
197 public Result<Integer> compute() {
198 return Result.createSingleDependency(Integer.valueOf(getClassKindImpl(aClass)), aClass);
200 }, false);
201 aClass.putUserData(CLASS_KIND_KEY, value);
203 return value.getValue().intValue();
206 private static int getClassKindImpl(PsiClass aClass) {
207 if (!aClass.isValid()) return CLASS_KIND_CLASS;
209 if (aClass.isAnnotationType()) {
210 return CLASS_KIND_ANNOTATION;
212 if (aClass.isEnum()) {
213 return CLASS_KIND_ENUM;
215 if (aClass.isInterface()) {
216 return CLASS_KIND_INTERFACE;
218 if (aClass instanceof JspClass) {
219 return CLASS_KIND_JSP;
221 if (aClass instanceof PsiAnonymousClass) {
222 return CLASS_KIND_ANONYMOUS;
225 final PsiManager manager = aClass.getManager();
226 final PsiClass javaLangTrowable = manager.findClass("java.lang.Throwable", aClass.getResolveScope());
227 final boolean isException = javaLangTrowable != null && InheritanceUtil.isInheritorOrSelf(aClass, javaLangTrowable, true);
228 if (isException) {
229 return CLASS_KIND_EXCEPTION;
232 if (TestUtil.isTestClass(aClass)) {
233 return CLASS_KIND_JUNIT_TEST;
235 if (PsiClassUtil.isRunnableClass(aClass, false) && PsiMethodUtil.findMainMethod(aClass) != null) {
236 return CLASS_KIND_RUNNABLE;
238 return CLASS_KIND_CLASS;
241 private static final TIntObjectHashMap<Icon> BASE_ICON = new TIntObjectHashMap<Icon>(20);
242 static {
243 BASE_ICON.put(CLASS_KIND_CLASS, Icons.CLASS_ICON);
244 BASE_ICON.put(CLASS_KIND_CLASS | FLAGS_ABSTRACT, Icons.ABSTRACT_CLASS_ICON);
245 BASE_ICON.put(CLASS_KIND_ANNOTATION, Icons.ANNOTATION_TYPE_ICON);
246 BASE_ICON.put(CLASS_KIND_ANNOTATION | FLAGS_ABSTRACT, Icons.ANNOTATION_TYPE_ICON);
247 BASE_ICON.put(CLASS_KIND_ANONYMOUS, Icons.ANONYMOUS_CLASS_ICON);
248 BASE_ICON.put(CLASS_KIND_ANONYMOUS | FLAGS_ABSTRACT, Icons.ANONYMOUS_CLASS_ICON);
249 BASE_ICON.put(CLASS_KIND_ASPECT, Icons.ASPECT_ICON);
250 BASE_ICON.put(CLASS_KIND_ASPECT | FLAGS_ABSTRACT, Icons.ASPECT_ICON);
251 BASE_ICON.put(CLASS_KIND_ENUM, Icons.ENUM_ICON);
252 BASE_ICON.put(CLASS_KIND_ENUM | FLAGS_ABSTRACT, Icons.ENUM_ICON);
253 BASE_ICON.put(CLASS_KIND_EXCEPTION, Icons.EXCEPTION_CLASS_ICON);
254 BASE_ICON.put(CLASS_KIND_EXCEPTION | FLAGS_ABSTRACT, ABSTRACT_EXCEPTION_CLASS_ICON);
255 BASE_ICON.put(CLASS_KIND_INTERFACE, Icons.INTERFACE_ICON);
256 BASE_ICON.put(CLASS_KIND_INTERFACE | FLAGS_ABSTRACT, Icons.INTERFACE_ICON);
257 BASE_ICON.put(CLASS_KIND_JSP, Icons.JSP_ICON);
258 BASE_ICON.put(CLASS_KIND_JSP | FLAGS_ABSTRACT, Icons.JSP_ICON);
259 BASE_ICON.put(CLASS_KIND_JUNIT_TEST, Icons.CLASS_ICON);
260 BASE_ICON.put(CLASS_KIND_JUNIT_TEST | FLAGS_ABSTRACT, Icons.ABSTRACT_CLASS_ICON);
261 BASE_ICON.put(CLASS_KIND_RUNNABLE, Icons.CLASS_ICON);
264 private static Icon getClassBaseIcon(final PsiClass aClass) {
265 final int classKind = getClassKind(aClass);
266 final boolean isAbstract = aClass.hasModifierProperty(PsiModifier.ABSTRACT);
267 return BASE_ICON.get(classKind | (isAbstract ? FLAGS_ABSTRACT : 0));
270 public static String getDescription(PsiModifierListOwner member) {
271 String noun;
272 if (member instanceof PsiClass) noun = getClassNoun((PsiClass)member);
273 else if (member instanceof PsiMethod) noun = CodeInsightBundle.message("node.method.tooltip");
274 else if (member instanceof PsiField) noun = CodeInsightBundle.message("node.field.tooltip");
275 else return null;
276 String adj = getFlagsDescription(member);
277 return (adj + " " + noun).trim();
280 private static String getClassNoun(final PsiClass aClass) {
281 String noun;
282 int kind = getClassKind(aClass);
283 switch (kind) {
284 case CLASS_KIND_ANNOTATION: noun = CodeInsightBundle.message("node.annotation.tooltip"); break;
285 case CLASS_KIND_ANONYMOUS: noun = CodeInsightBundle.message("node.anonymous.class.tooltip"); break;
286 case CLASS_KIND_ENUM: noun = CodeInsightBundle.message("node.enum.tooltip"); break;
287 case CLASS_KIND_EXCEPTION: noun = CodeInsightBundle.message("node.exception.tooltip"); break;
288 case CLASS_KIND_INTERFACE: noun = CodeInsightBundle.message("node.interface.tooltip"); break;
289 case CLASS_KIND_JUNIT_TEST: noun = CodeInsightBundle.message("node.junit.test.tooltip"); break;
290 case CLASS_KIND_RUNNABLE: noun = CodeInsightBundle.message("node.runnable.class.tooltip"); break;
291 default:
292 case CLASS_KIND_CLASS: noun = CodeInsightBundle.message("node.class.tooltip"); break;
294 return noun;
297 private static String getFlagsDescription(final PsiModifierListOwner aClass) {
298 int flags = getFlags(aClass, false);
299 String adj = "";
300 if ((flags & FLAGS_EXCLUDED) != 0) adj += " " + CodeInsightBundle.message("node.excluded.flag.tooltip");
301 if ((flags & FLAGS_ABSTRACT) != 0) adj += " " + CodeInsightBundle.message("node.abstract.flag.tooltip");
302 if ((flags & FLAGS_FINAL) != 0) adj += " " + CodeInsightBundle.message("node.final.flag.tooltip");
303 if ((flags & FLAGS_STATIC) != 0) adj += " " + CodeInsightBundle.message("node.static.flag.tooltip");
304 PsiModifierList list = aClass.getModifierList();
305 if (list != null) {
306 int level = PsiUtil.getAccessLevel(list);
307 if (level != PsiUtil.ACCESS_LEVEL_PUBLIC) {
308 adj += " " + StringUtil.capitalize(PsiUtil.getAccessModifier(level));
311 return adj;
314 public static RowIcon createLayeredIcon(Icon icon, int flags) {
315 if (flags != 0) {
316 List<Icon> iconLayers = new SmartList<Icon>();
317 if ((flags & FLAGS_STATIC) != 0) {
318 iconLayers.add(STATIC_MARK_ICON);
320 if ((flags & FLAGS_LOCKED) != 0) {
321 iconLayers.add(Icons.LOCKED_ICON);
323 if ((flags & FLAGS_EXCLUDED) != 0) {
324 iconLayers.add(Icons.EXCLUDED_FROM_COMPILE_ICON);
326 final boolean isFinal = (flags & FLAGS_FINAL) != 0;
327 if (isFinal) {
328 iconLayers.add(FINAL_MARK_ICON);
330 if ((flags & FLAGS_JUNIT_TEST) != 0) {
331 iconLayers.add(JUNIT_TEST_MARK);
333 if ((flags & FLAGS_RUNNABLE) != 0) {
334 iconLayers.add(RUNNABLE_MARK);
336 LayeredIcon layeredIcon = new LayeredIcon(1 + iconLayers.size());
337 layeredIcon.setIcon(icon, 0);
338 for (int i = 0; i < iconLayers.size(); i++) {
339 Icon icon1 = iconLayers.get(i);
340 layeredIcon.setIcon(icon1, i+1);
342 icon = layeredIcon;
344 RowIcon baseIcon = new RowIcon(2);
345 baseIcon.setIcon(icon, 0);
346 return baseIcon;