From dcee4fbc139763df06930591cc9a5dcc2025075f Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Mon, 21 Jul 2025 12:31:17 +0200 Subject: [PATCH] [java-inspections] IDEA-376166 return null inspection should consider contract as well as `@Nullable` GitOrigin-RevId: 2fb103a97887bd068454702b520f86e83aa38a36 --- .../src/com/siyeh/ig/bugs/ReturnNullInspection.java | 11 +++++++++-- .../siyeh/igtest/bugs/return_null/ReturnNull.java | 12 ++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/siyeh/ig/bugs/ReturnNullInspection.java b/java/java-impl/src/com/siyeh/ig/bugs/ReturnNullInspection.java index f47025c3ab5a..5bad38f68721 100644 --- a/java/java-impl/src/com/siyeh/ig/bugs/ReturnNullInspection.java +++ b/java/java-impl/src/com/siyeh/ig/bugs/ReturnNullInspection.java @@ -10,6 +10,8 @@ import com.intellij.codeInsight.options.JavaInspectionControls; import com.intellij.codeInspection.CommonQuickFixBundle; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.dataFlow.DfaPsiUtil; +import com.intellij.codeInspection.dataFlow.JavaMethodContractUtil; +import com.intellij.codeInspection.dataFlow.StandardMethodContract; import com.intellij.codeInspection.options.OptPane; import com.intellij.codeInspection.util.OptionalUtil; import com.intellij.java.syntax.parser.JavaKeywords; @@ -19,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.controlFlow.DefUseUtil; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.ContainerUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; @@ -33,7 +36,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; +import java.util.List; import static com.intellij.codeInspection.options.OptPane.checkbox; import static com.intellij.codeInspection.options.OptPane.pane; @@ -187,6 +190,10 @@ public final class ReturnNullInspection extends BaseInspection { if (DfaPsiUtil.getTypeNullability(returnType) == Nullability.NULLABLE) { return; } + if (!lambda && JavaMethodContractUtil.hasExplicitContractAnnotation(method)) { + List contracts = JavaMethodContractUtil.getMethodContracts(method); + if (ContainerUtil.exists(contracts, c -> c.getReturnValue().isNull())) return; + } if (CollectionUtils.isCollectionClassOrInterface(returnType)) { if (m_reportCollectionMethods) { @@ -213,7 +220,7 @@ public final class ReturnNullInspection extends BaseInspection { return false; } final PsiElement[] refs = DefUseUtil.getRefs(codeBlock, variable, element); - return Arrays.stream(refs).anyMatch(this::isInNullableContext); + return ContainerUtil.exists(refs, this::isInNullableContext); } else if (parent instanceof PsiExpressionList) { final PsiElement grandParent = parent.getParent(); diff --git a/java/java-tests/testData/ig/com/siyeh/igtest/bugs/return_null/ReturnNull.java b/java/java-tests/testData/ig/com/siyeh/igtest/bugs/return_null/ReturnNull.java index bf8334343290..dce705d9503b 100644 --- a/java/java-tests/testData/ig/com/siyeh/igtest/bugs/return_null/ReturnNull.java +++ b/java/java-tests/testData/ig/com/siyeh/igtest/bugs/return_null/ReturnNull.java @@ -55,4 +55,16 @@ class Test { void foo() { Function f = s -> null; } +} +class WithContract { + @org.jetbrains.annotations.Contract("!null -> !null; null -> null") + public static String maybeTrim(String s) { + if (s == null) return null; + return s.trim(); + } + + public static String maybeTrimNoContract(String s) { + if (s == null) return null; + return s.trim(); + } } \ No newline at end of file