method reference: check NPE unboxing (IDEA-133714)

This commit is contained in:
Anna Kozlova
2014-12-02 14:01:10 +01:00
parent a18e9031bf
commit e17a949a6e
5 changed files with 39 additions and 1 deletions
@@ -44,6 +44,7 @@ import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.extractMethod.ExtractMethodUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ArrayUtilRt;
@@ -107,6 +108,21 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
analyzeCodeBlock(initializer.getBody(), holder, isOnTheFly);
}
@Override
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
super.visitMethodReferenceExpression(expression);
final PsiElement resolve = expression.resolve();
if (resolve instanceof PsiMethod) {
final PsiType methodReturnType = ((PsiMethod)resolve).getReturnType();
if (TypeConversionUtil.isPrimitiveWrapper(methodReturnType) && NullableNotNullManager.isNullable((PsiMethod)resolve)) {
final PsiType returnType = LambdaUtil.getFunctionalInterfaceReturnType(expression);
if (TypeConversionUtil.isPrimitiveAndNotNull(returnType)) {
holder.registerProblem(expression, InspectionsBundle.message("dataflow.message.unboxing.method.reference"));
}
}
}
}
@Override
public void visitIfStatement(PsiIfStatement statement) {
PsiExpression condition = statement.getCondition();
@@ -38,7 +38,7 @@ public class LambdaUtil {
private static final Logger LOG = Logger.getInstance("#" + LambdaUtil.class.getName());
@Nullable
public static PsiType getFunctionalInterfaceReturnType(PsiLambdaExpression expr) {
public static PsiType getFunctionalInterfaceReturnType(PsiFunctionalExpression expr) {
return getFunctionalInterfaceReturnType(expr.getFunctionalInterfaceType());
}
@@ -0,0 +1,17 @@
class X {
interface I {
int get();
}
interface J {
Integer get();
}
I is = <warning descr="Use of 'X::m' would need unboxing which may produce 'java.lang.NullPointerException'">X::m</warning>;
J j = X::m;
@org.jetbrains.annotations.Nullable
static Integer m() {
return null;
}
}
@@ -57,6 +57,10 @@ public class DataFlowInspection8Test extends LightCodeInsightFixtureTestCase {
doTest();
}
public void testUnboxingInMethodReferences() throws Exception {
doTest();
}
private void setupCustomAnnotations() {
myFixture.addClass("package foo;\n\nimport java.lang.annotation.*;\n\n@Target({ElementType.TYPE_USE}) public @interface Nullable { }");
myFixture.addClass("package foo;\n\nimport java.lang.annotation.*;\n\n@Target({ElementType.TYPE_USE}) public @interface NotNull { }");
@@ -89,6 +89,7 @@ dataflow.message.return.nullable.from.notnull=Expression <code>#ref</code> might
dataflow.message.return.null.from.notnullable=<code>null</code> is returned by the method which is not declared as @{0}
dataflow.message.return.nullable.from.notnullable=Expression <code>#ref</code> might evaluate to null but is returned by the method which is not declared as @{0}
dataflow.message.unboxing=Unboxing of <code>#ref</code> #loc may produce <code>java.lang.NullPointerException</code>
dataflow.message.unboxing.method.reference=Use of <code>#ref</code> #loc would need unboxing which may produce <code>java.lang.NullPointerException</code>
dataflow.too.complex=Method <code>#ref</code> is too complex to analyze by data flow algorithm
#deprecated