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
;
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);
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
) {
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
)) {
109 if(!(type
instanceof PsiClassType
)) {
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) {
122 final PsiFile containingFile1
= element1
.getContainingFile();
123 if (!(containingFile1
instanceof PsiClassOwner
)) {
126 final PsiClassOwner containingJavaFile1
=
127 (PsiClassOwner
)containingFile1
;
128 final String packageName1
= containingJavaFile1
.getPackageName();
129 final PsiFile containingFile2
= element2
.getContainingFile();
130 if (!(containingFile2
instanceof PsiClassOwner
)) {
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) {
144 if (fieldClass
.equals(fromClass
)) {
147 if (field
.hasModifierProperty(PsiModifier
.PRIVATE
)) {
150 if (field
.hasModifierProperty(PsiModifier
.PUBLIC
) ||
151 field
.hasModifierProperty(PsiModifier
.PROTECTED
)) {
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;
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
;
174 final PsiClass containingClass
= getContainingClass(outerClass
);
175 if (containingClass
!= null) {
176 outerClass
= containingClass
;
183 public static boolean isClassVisibleFromClass(PsiClass baseClass
,
184 PsiClass referencedClass
) {
185 if (referencedClass
.hasModifierProperty(PsiModifier
.PUBLIC
)) {
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
) !=
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;