From 90cfb4693025a9701965a4850982bb67ee086030 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 2 Apr 2019 10:42:55 +0700 Subject: [PATCH] IDEA-209618 NotNull annotated method might result in null inspection disappears with pure Contract annotation set. --- .../dataFlow/StandardInstructionVisitor.java | 14 ++++++++++++-- .../dataFlow/fixture/NullableReturn.java | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java index eeaa9506626c..06c49c1d0ee0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java @@ -494,8 +494,18 @@ public class StandardInstructionVisitor extends InstructionVisitor { } @NotNull - private static PsiMethod findSpecificMethod(@NotNull PsiMethod method, @NotNull DfaMemoryState state, @Nullable DfaValue qualifier) { + private static PsiMethod findSpecificMethod(PsiElement context, + @NotNull PsiMethod method, + @NotNull DfaMemoryState state, + @Nullable DfaValue qualifier) { if (qualifier == null || !PsiUtil.canBeOverridden(method)) return method; + PsiExpression qualifierExpression = null; + if (context instanceof PsiMethodCallExpression) { + qualifierExpression = ((PsiMethodCallExpression)context).getMethodExpression().getQualifierExpression(); + } else if (context instanceof PsiMethodReferenceExpression) { + qualifierExpression = ((PsiMethodReferenceExpression)context).getQualifierExpression(); + } + if (qualifierExpression instanceof PsiSuperExpression) return method; // non-virtual call TypeConstraint constraint = state.getValueFact(qualifier, DfaFactType.TYPE_CONSTRAINT); PsiType type = constraint == null ? null : constraint.getPsiType(); return MethodUtils.findSpecificMethod(method, type); @@ -526,7 +536,7 @@ public class StandardInstructionVisitor extends InstructionVisitor { Mutability mutable = Mutability.UNKNOWN; if (targetMethod != null) { mutable = Mutability.getMutability(targetMethod); - PsiMethod realMethod = findSpecificMethod(targetMethod, state, qualifierValue); + PsiMethod realMethod = findSpecificMethod(instruction.getContext(), targetMethod, state, qualifierValue); if (realMethod != targetMethod) { nullability = DfaPsiUtil.getElementNullability(type, realMethod); mutable = Mutability.getMutability(realMethod); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NullableReturn.java b/java/java-tests/testData/inspection/dataFlow/fixture/NullableReturn.java index 1bba4661a267..58010c2bb7ab 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/NullableReturn.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/NullableReturn.java @@ -1,4 +1,5 @@ import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; class NullableReturn { @@ -7,4 +8,22 @@ class NullableReturn { // no nullable return from notnull method here return x == null ? o3 : x; } + + interface Context {} + + static class Foo { + @Nullable + protected Boolean executeImpl(@Nullable Context context) { + return null; + } + } + + static class Bar extends Foo { + @NotNull + @Contract(pure = true) + @Override + protected Boolean executeImpl(@Nullable Context context) { + return super.executeImpl(context); + } + } } \ No newline at end of file