Java: Recognize Integer.TYPE (and similar) when checking reflective access to methods (IDEA-172744)

This commit is contained in:
Pavel Dolgov
2017-06-02 13:32:28 +03:00
parent fdd32a8322
commit f1757b0027
3 changed files with 35 additions and 0 deletions
@@ -91,6 +91,7 @@ public class JavaReflectionReferenceUtil {
public static final String LOAD_CLASS = "loadClass";
public static final String GET_CLASS = "getClass";
public static final String NEW_INSTANCE = "newInstance";
public static final String TYPE = "TYPE";
private static final RecursionGuard ourGuard = RecursionManager.createGuard("JavaLangClassMemberReference");
@@ -144,6 +145,19 @@ public class JavaReflectionReferenceUtil {
final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
final PsiClass resolvedElement = resolveResult.getElement();
if (!isJavaLangClass(resolvedElement)) return null;
if (context instanceof PsiReferenceExpression && TYPE.equals(((PsiReferenceExpression)context).getReferenceName())) {
final PsiElement resolved = ((PsiReferenceExpression)context).resolve();
if (resolved instanceof PsiField) {
final PsiField field = (PsiField)resolved;
if (field.hasModifierProperty(PsiModifier.FINAL) && field.hasModifierProperty(PsiModifier.STATIC)) {
final PsiPrimitiveType unboxedType = tryUnbox(field.getContainingClass(), (PsiClassType)type);
if (unboxedType != null) {
return ReflectiveType.create(unboxedType);
}
}
}
}
final PsiTypeParameter[] parameters = resolvedElement.getTypeParameters();
if (parameters.length == 1) {
final PsiType typeArgument = resolveResult.getSubstitutor().substitute(parameters[0]);
@@ -281,6 +295,19 @@ public class JavaReflectionReferenceUtil {
return assignment != null ? assignment.getRExpression() : null;
}
@Nullable
private static PsiPrimitiveType tryUnbox(@Nullable PsiClass psiClass, @NotNull PsiClassType originalType) {
if (psiClass != null && TypeConversionUtil.isPrimitiveWrapper(psiClass.getQualifiedName())) {
final PsiElementFactory factory = JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory();
final PsiClassType classType = factory.createType(psiClass, PsiSubstitutor.EMPTY, originalType.getLanguageLevel());
final PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(classType);
if (unboxedType != null) {
return unboxedType;
}
}
return null;
}
private static PsiClass findClass(@NotNull String qualifiedName, @NotNull PsiElement context) {
final Project project = context.getProject();
return JavaPsiFacade.getInstance(project).findClass(qualifiedName, GlobalSearchScope.allScope(project));
@@ -24,6 +24,10 @@ class ConstructorExists {
C.class.getConstructor(int.class);
C.class.getConstructor<warning descr="Cannot resolve constructor with specified argument types">(boolean.class)</warning>;
A.class.getConstructor(Integer.TYPE);
A.class.getConstructor<warning descr="Constructor is not public">(Boolean.TYPE)</warning>;
A.class.getConstructor<warning descr="Cannot resolve constructor with specified argument types">(Double.TYPE)</warning>;
}
static class A {
@@ -68,6 +68,10 @@ class MethodExists {
C.class.getMethod("c", int.class);
C.class.getMethod(<warning descr="Cannot resolve method 'c' with specified argument types">"c"</warning>, boolean.class);
C.class.getMethod(<warning descr="Cannot resolve method 'd'">"d"</warning>, int.class);
A.class.getMethod("a1", Integer.TYPE);
A.class.getMethod(<warning descr="Method 'a2' is not public">"a2"</warning>, Integer.TYPE);
A.class.getMethod(<warning descr="Cannot resolve method 'a1' with specified argument types">"a1"</warning>, Boolean.TYPE);
}
static class A {