[java-inspections] IDEA-376166 return null inspection should consider contract as well as @Nullable

GitOrigin-RevId: 2fb103a97887bd068454702b520f86e83aa38a36
This commit is contained in:
Tagir Valeev
2025-07-21 12:07:39 +00:00
committed by intellij-monorepo-bot
parent a66f4da609
commit dcee4fbc13
2 changed files with 21 additions and 2 deletions
@@ -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<StandardMethodContract> 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();
@@ -55,4 +55,16 @@ class Test {
void foo() {
Function<String, @Nullable String> 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 <warning descr="Return of 'null'">null</warning>;
return s.trim();
}
}