IG: introduce isAutoBoxed() utility method

This commit is contained in:
Bas Leijdekkers
2016-09-29 16:50:34 +02:00
parent 92ea85e4f7
commit b5cc1cd4ea
2 changed files with 64 additions and 52 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2016 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.
@@ -15,7 +15,6 @@
*/
package com.siyeh.ig.jdk;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.openapi.project.Project;
@@ -56,14 +55,6 @@ public class AutoBoxingInspection extends BaseInspection {
s_boxingClasses.put("char", CommonClassNames.JAVA_LANG_CHARACTER);
}
@NonNls static final Set<String> convertableBoxedClassNames = new HashSet<>();
static {
convertableBoxedClassNames.add(CommonClassNames.JAVA_LANG_BYTE);
convertableBoxedClassNames.add(CommonClassNames.JAVA_LANG_CHARACTER);
convertableBoxedClassNames.add(CommonClassNames.JAVA_LANG_SHORT);
}
@Override
@NotNull
public String getDisplayName() {
@@ -323,50 +314,9 @@ public class AutoBoxingInspection extends BaseInspection {
}
private void checkExpression(@NotNull PsiExpression expression) {
final PsiElement parent = expression.getParent();
if (parent instanceof PsiParenthesizedExpression) {
if (!ExpressionUtils.isAutoBoxed(expression)) {
return;
}
if (parent instanceof PsiExpressionList) {
final PsiElement grandParent = parent.getParent();
if (grandParent instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)grandParent;
final PsiMethod method = methodCallExpression.resolveMethod();
if (method != null &&
AnnotationUtil.isAnnotated(method, Collections.singletonList("java.lang.invoke.MethodHandle.PolymorphicSignature"))) {
return;
}
}
}
final PsiType expressionType = expression.getType();
if (expressionType == null || expressionType.equals(PsiType.VOID) || !TypeConversionUtil.isPrimitiveAndNotNull(expressionType)) {
return;
}
final PsiPrimitiveType primitiveType = (PsiPrimitiveType)expressionType;
final PsiClassType boxedType = primitiveType.getBoxedType(expression);
if (boxedType == null) {
return;
}
final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, false, true);
if (expectedType == null || ClassUtils.isPrimitive(expectedType)) {
return;
}
if (!expectedType.isAssignableFrom(boxedType)) {
// JLS 5.2 Assignment Conversion
// check if a narrowing primitive conversion is applicable
if (!(expectedType instanceof PsiClassType) || !PsiUtil.isConstantExpression(expression)) {
return;
}
final PsiClassType classType = (PsiClassType)expectedType;
final String className = classType.getCanonicalText();
if (!convertableBoxedClassNames.contains(className)) {
return;
}
if (!PsiType.BYTE.equals(expressionType) && !PsiType.CHAR.equals(expressionType) &&
!PsiType.SHORT.equals(expressionType) && !PsiType.INT.equals(expressionType)) {
return;
}
}
if (ignoreAddedToCollection && isAddedToCollection(expression)) {
return;
}
@@ -15,20 +15,34 @@
*/
package com.siyeh.ig.psiutils;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.ConstantExpressionUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class ExpressionUtils {
@NonNls static final Set<String> convertableBoxedClassNames = new HashSet<>(3);
static {
convertableBoxedClassNames.add(CommonClassNames.JAVA_LANG_BYTE);
convertableBoxedClassNames.add(CommonClassNames.JAVA_LANG_CHARACTER);
convertableBoxedClassNames.add(CommonClassNames.JAVA_LANG_SHORT);
}
private ExpressionUtils() {}
@Nullable
@@ -723,4 +737,52 @@ public class ExpressionUtils {
public static boolean isLiteral(PsiElement element, Object value) {
return element instanceof PsiLiteralExpression && value.equals(((PsiLiteralExpression)element).getValue());
}
public static boolean isAutoBoxed(@NotNull PsiExpression expression) {
final PsiElement parent = expression.getParent();
if (parent instanceof PsiParenthesizedExpression) {
return false;
}
if (parent instanceof PsiExpressionList) {
final PsiElement grandParent = parent.getParent();
if (grandParent instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)grandParent;
final PsiMethod method = methodCallExpression.resolveMethod();
if (method != null &&
AnnotationUtil.isAnnotated(method, Collections.singletonList("java.lang.invoke.MethodHandle.PolymorphicSignature"))) {
return false;
}
}
}
final PsiType expressionType = expression.getType();
if (expressionType == null || expressionType.equals(PsiType.VOID) || !TypeConversionUtil.isPrimitiveAndNotNull(expressionType)) {
return false;
}
final PsiPrimitiveType primitiveType = (PsiPrimitiveType)expressionType;
final PsiClassType boxedType = primitiveType.getBoxedType(expression);
if (boxedType == null) {
return false;
}
final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, false, true);
if (expectedType == null || ClassUtils.isPrimitive(expectedType)) {
return false;
}
if (!expectedType.isAssignableFrom(boxedType)) {
// JLS 5.2 Assignment Conversion
// check if a narrowing primitive conversion is applicable
if (!(expectedType instanceof PsiClassType) || !PsiUtil.isConstantExpression(expression)) {
return false;
}
final PsiClassType classType = (PsiClassType)expectedType;
final String className = classType.getCanonicalText();
if (!convertableBoxedClassNames.contains(className)) {
return false;
}
if (!PsiType.BYTE.equals(expressionType) && !PsiType.CHAR.equals(expressionType) &&
!PsiType.SHORT.equals(expressionType) && !PsiType.INT.equals(expressionType)) {
return false;
}
}
return true;
}
}