blob: 4656d0c4610a43b078012ca385670baad9653ecd [file] [log] [blame]
/*
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.psiutils;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
public class ClassUtils {
/**
* @noinspection StaticCollection
*/
private static final Set<String> immutableTypes = new HashSet<String>(19);
/**
* @noinspection StaticCollection
*/
private static final Set<PsiType> primitiveNumericTypes = new HashSet<PsiType>(7);
/**
* @noinspection StaticCollection
*/
private static final Set<PsiType> integralTypes = new HashSet<PsiType>(5);
static {
integralTypes.add(PsiType.LONG);
integralTypes.add(PsiType.INT);
integralTypes.add(PsiType.SHORT);
integralTypes.add(PsiType.CHAR);
integralTypes.add(PsiType.BYTE);
primitiveNumericTypes.add(PsiType.BYTE);
primitiveNumericTypes.add(PsiType.CHAR);
primitiveNumericTypes.add(PsiType.SHORT);
primitiveNumericTypes.add(PsiType.INT);
primitiveNumericTypes.add(PsiType.LONG);
primitiveNumericTypes.add(PsiType.FLOAT);
primitiveNumericTypes.add(PsiType.DOUBLE);
immutableTypes.add(CommonClassNames.JAVA_LANG_BOOLEAN);
immutableTypes.add(CommonClassNames.JAVA_LANG_CHARACTER);
immutableTypes.add(CommonClassNames.JAVA_LANG_SHORT);
immutableTypes.add(CommonClassNames.JAVA_LANG_INTEGER);
immutableTypes.add(CommonClassNames.JAVA_LANG_LONG);
immutableTypes.add(CommonClassNames.JAVA_LANG_FLOAT);
immutableTypes.add(CommonClassNames.JAVA_LANG_DOUBLE);
immutableTypes.add(CommonClassNames.JAVA_LANG_BYTE);
immutableTypes.add(CommonClassNames.JAVA_LANG_STRING);
immutableTypes.add("java.awt.Font");
immutableTypes.add("java.awt.Color");
immutableTypes.add("java.math.BigDecimal");
immutableTypes.add("java.math.BigInteger");
immutableTypes.add("java.math.MathContext");
immutableTypes.add("java.nio.channels.FileLock");
immutableTypes.add("java.nio.charset.Charset");
immutableTypes.add("java.io.File");
immutableTypes.add("java.net.URI");
immutableTypes.add("java.util.regex.Pattern");
}
private ClassUtils() {}
@Nullable
public static PsiClass findClass(@NonNls String fqClassName, PsiElement context) {
return JavaPsiFacade.getInstance(context.getProject()).findClass(fqClassName, context.getResolveScope());
}
@Nullable
public static PsiClass findObjectClass(PsiElement context) {
return findClass(CommonClassNames.JAVA_LANG_OBJECT, context);
}
public static boolean isPrimitive(PsiType type) {
return TypeConversionUtil.isPrimitiveAndNotNull(type);
}
public static boolean isIntegral(PsiType type) {
return integralTypes.contains(type);
}
public static boolean isImmutable(PsiType type) {
if (TypeConversionUtil.isPrimitiveAndNotNull(type)) {
return true;
}
if (!(type instanceof PsiClassType)) {
return false;
}
final PsiClassType classType = (PsiClassType)type;
final String className = classType.getCanonicalText();
return immutableTypes.contains(className);
}
public static boolean inSamePackage(@Nullable PsiElement element1,
@Nullable PsiElement element2) {
if (element1 == null || element2 == null) {
return false;
}
final PsiFile containingFile1 = element1.getContainingFile();
if (!(containingFile1 instanceof PsiClassOwner)) {
return false;
}
final PsiClassOwner containingJavaFile1 =
(PsiClassOwner)containingFile1;
final String packageName1 = containingJavaFile1.getPackageName();
final PsiFile containingFile2 = element2.getContainingFile();
if (!(containingFile2 instanceof PsiClassOwner)) {
return false;
}
final PsiClassOwner containingJavaFile2 =
(PsiClassOwner)containingFile2;
final String packageName2 = containingJavaFile2.getPackageName();
return packageName1.equals(packageName2);
}
public static boolean isFieldVisible(PsiField field, PsiClass fromClass) {
final PsiClass fieldClass = field.getContainingClass();
if (fieldClass == null) {
return false;
}
if (fieldClass.equals(fromClass)) {
return true;
}
if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
return false;
}
if (field.hasModifierProperty(PsiModifier.PUBLIC) ||
field.hasModifierProperty(PsiModifier.PROTECTED)) {
return true;
}
return inSamePackage(fieldClass, fromClass);
}
@Contract("null -> false")
public static boolean isPrimitiveNumericType(@Nullable PsiType type) {
return primitiveNumericTypes.contains(type);
}
public static boolean isInnerClass(PsiClass aClass) {
final PsiClass parentClass = getContainingClass(aClass);
return parentClass != null;
}
@Nullable
public static PsiClass getContainingClass(PsiElement element) {
return PsiTreeUtil.getParentOfType(element, PsiClass.class);
}
public static PsiClass getOutermostContainingClass(PsiClass aClass) {
PsiClass outerClass = aClass;
while (true) {
final PsiClass containingClass = getContainingClass(outerClass);
if (containingClass != null) {
outerClass = containingClass;
}
else {
return outerClass;
}
}
}
@Nullable
public static PsiClass getContainingStaticClass(PsiElement element) {
PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, false, PsiFile.class);
while (isNonStaticClass(aClass)) {
aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true, PsiFile.class);
}
return aClass;
}
public static boolean isNonStaticClass(@Nullable PsiClass aClass) {
if (aClass == null) {
return false;
}
if (aClass.hasModifierProperty(PsiModifier.STATIC) || aClass.isInterface() || aClass.isEnum()) {
return false;
}
if (aClass instanceof PsiAnonymousClass) {
return true;
}
final PsiElement parent = aClass.getParent();
if (parent == null || parent instanceof PsiFile) {
return false;
}
if (!(parent instanceof PsiClass)) {
return true;
}
final PsiClass parentClass = (PsiClass)parent;
return !parentClass.isInterface();
}
}