IDEADEV-40452
[fedora-idea.git] / plugins / InspectionGadgets / src / com / siyeh / ig / psiutils / ClassUtils.java
blobfd4806b44657522da7eb66a0d71ae92c4dc5395d
1 /*
2 * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers
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.siyeh.ig.psiutils;
18 import com.intellij.openapi.project.Project;
19 import com.intellij.psi.*;
20 import com.intellij.psi.search.GlobalSearchScope;
21 import com.intellij.psi.search.searches.ClassInheritorsSearch;
22 import com.intellij.psi.util.InheritanceUtil;
23 import com.intellij.psi.util.PsiTreeUtil;
24 import com.intellij.psi.util.TypeConversionUtil;
25 import com.intellij.util.Query;
26 import org.jetbrains.annotations.NonNls;
27 import org.jetbrains.annotations.Nullable;
29 import java.util.HashSet;
30 import java.util.Set;
32 public class ClassUtils {
34 /** @noinspection StaticCollection*/
35 private static final Set<String> immutableTypes =
36 new HashSet<String>(19);
38 /** @noinspection StaticCollection*/
39 private static final Set<PsiType> primitiveNumericTypes =
40 new HashSet<PsiType>(7);
42 /** @noinspection StaticCollection*/
43 private static final Set<PsiType> integralTypes = new HashSet<PsiType>(5);
45 static {
46 integralTypes.add(PsiType.LONG);
47 integralTypes.add(PsiType.INT);
48 integralTypes.add(PsiType.SHORT);
49 integralTypes.add(PsiType.CHAR);
50 integralTypes.add(PsiType.BYTE);
52 primitiveNumericTypes.add(PsiType.BYTE);
53 primitiveNumericTypes.add(PsiType.CHAR);
54 primitiveNumericTypes.add(PsiType.SHORT);
55 primitiveNumericTypes.add(PsiType.INT);
56 primitiveNumericTypes.add(PsiType.LONG);
57 primitiveNumericTypes.add(PsiType.FLOAT);
58 primitiveNumericTypes.add(PsiType.DOUBLE);
60 immutableTypes.add("java.lang.Boolean");
61 immutableTypes.add("java.lang.Character");
62 immutableTypes.add("java.lang.Short");
63 immutableTypes.add("java.lang.Integer");
64 immutableTypes.add("java.lang.Long");
65 immutableTypes.add("java.lang.Float");
66 immutableTypes.add("java.lang.Double");
67 immutableTypes.add("java.lang.Byte");
68 immutableTypes.add("java.lang.String");
69 immutableTypes.add("java.awt.Font");
70 immutableTypes.add("java.awt.Color");
71 immutableTypes.add("java.math.BigDecimal");
72 immutableTypes.add("java.math.BigInteger");
73 immutableTypes.add("java.math.MathContext");
74 immutableTypes.add("java.nio.channels.FileLock");
75 immutableTypes.add("java.nio.charset.Charset");
76 immutableTypes.add("java.io.File");
77 immutableTypes.add("java.net.URI");
78 immutableTypes.add("java.util.regex.Pattern");
81 private ClassUtils() {
84 public static boolean isSubclass(@Nullable PsiClass aClass,
85 @NonNls String ancestorName) {
86 if (aClass == null) {
87 return false;
89 final PsiManager psiManager = aClass.getManager();
90 final Project project = psiManager.getProject();
91 final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
92 final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
93 final PsiClass ancestorClass = psiFacade.findClass(ancestorName, scope);
94 return InheritanceUtil.isCorrectDescendant(aClass, ancestorClass, true);
97 public static boolean isPrimitive(PsiType type) {
98 return TypeConversionUtil.isPrimitiveAndNotNull(type);
101 public static boolean isIntegral(PsiType type) {
102 return integralTypes.contains(type);
105 public static boolean isImmutable(PsiType type) {
106 if(TypeConversionUtil.isPrimitiveAndNotNull(type)) {
107 return true;
109 if(!(type instanceof PsiClassType)) {
110 return false;
112 final PsiClassType classType = (PsiClassType) type;
113 final String className = classType.getCanonicalText();
114 return immutableTypes.contains(className);
117 public static boolean inSamePackage(@Nullable PsiElement element1,
118 @Nullable PsiElement element2) {
119 if (element1 == null || element2==null) {
120 return false;
122 final PsiFile containingFile1 = element1.getContainingFile();
123 if (!(containingFile1 instanceof PsiClassOwner)) {
124 return false;
126 final PsiClassOwner containingJavaFile1 =
127 (PsiClassOwner)containingFile1;
128 final String packageName1 = containingJavaFile1.getPackageName();
129 final PsiFile containingFile2 = element2.getContainingFile();
130 if (!(containingFile2 instanceof PsiClassOwner)) {
131 return false;
133 final PsiClassOwner containingJavaFile2 =
134 (PsiClassOwner)containingFile2;
135 final String packageName2 = containingJavaFile2.getPackageName();
136 return packageName1.equals(packageName2);
139 public static boolean isFieldVisible(PsiField field, PsiClass fromClass) {
140 final PsiClass fieldClass = field.getContainingClass();
141 if (fieldClass == null) {
142 return false;
144 if (fieldClass.equals(fromClass)) {
145 return true;
147 if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
148 return false;
150 if (field.hasModifierProperty(PsiModifier.PUBLIC) ||
151 field.hasModifierProperty(PsiModifier.PROTECTED)) {
152 return true;
154 return inSamePackage(fieldClass, fromClass);
157 public static boolean isPrimitiveNumericType(PsiType type) {
158 return primitiveNumericTypes.contains(type);
161 public static boolean isInnerClass(PsiClass aClass) {
162 final PsiClass parentClass = getContainingClass(aClass);
163 return parentClass != null;
166 @Nullable
167 public static PsiClass getContainingClass(PsiElement element) {
168 return PsiTreeUtil.getParentOfType(element, PsiClass.class);
171 public static PsiClass getOutermostContainingClass(PsiClass aClass) {
172 PsiClass outerClass = aClass;
173 while (true) {
174 final PsiClass containingClass = getContainingClass(outerClass);
175 if (containingClass != null) {
176 outerClass = containingClass;
177 } else {
178 return outerClass;
183 public static boolean isClassVisibleFromClass(PsiClass baseClass,
184 PsiClass referencedClass) {
185 if (referencedClass.hasModifierProperty(PsiModifier.PUBLIC)) {
186 return true;
187 } else if (referencedClass.hasModifierProperty(PsiModifier.PROTECTED)) {
188 return inSamePackage(baseClass, referencedClass);
189 } else if (referencedClass.hasModifierProperty(PsiModifier.PRIVATE)) {
190 return PsiTreeUtil.findCommonParent(baseClass, referencedClass) !=
191 null;
192 } else {
193 return inSamePackage(baseClass, referencedClass);
197 public static boolean isOverridden(PsiClass aClass) {
198 final Query<PsiClass> query = ClassInheritorsSearch.search(aClass);
199 final PsiClass result = query.findFirst();
200 return result != null;