[java-inspections] ObviousNullCheckInspection: disable for methods that don't return the parameter

Even if the return value is not used, it's subject for IgnoreResultOfCallInspection to report it (as we consider only pure methods). It could sometimes be suppressed (e.g., inside assertThrows), in which case it's desired not to report anything.
Fixes IDEA-368213 False positive and code-breaking autofix for ObviousNullCheck


(cherry picked from commit 0ab2fd64b8a8f8599920cffad76fc830790f8269)

IJ-CR-156868

GitOrigin-RevId: cda30602e0c2af93f21a33501f7ad855b89fda1c
This commit is contained in:
Tagir Valeev
2025-03-05 13:54:07 +01:00
committed by intellij-monorepo-bot
parent 88a29d6af1
commit f2cfc536e6
2 changed files with 11 additions and 15 deletions

View File

@@ -53,17 +53,7 @@ public final class ObviousNullCheckInspection extends AbstractBaseJavaLocalInspe
};
}
static class NullCheckParameter {
int myIndex;
boolean myNull;
boolean myReturnsParameter;
NullCheckParameter(int index, boolean aNull, boolean returnsParameter) {
myIndex = index;
myNull = aNull;
myReturnsParameter = returnsParameter;
}
record NullCheckParameter(int myIndex, boolean myNull, boolean myReturnsParameter) {
static @Nullable NullCheckParameter fromCall(PsiMethodCallExpression call) {
PsiMethod method = call.resolveMethod();
if (method == null || method.isConstructor()) return null;
@@ -75,9 +65,9 @@ public final class ObviousNullCheckInspection extends AbstractBaseJavaLocalInspe
ContractReturnValue firstReturn = contract.getReturnValue();
ContractValue condition = ContainerUtil.getOnlyItem(contract.getConditions());
if (condition == null) return null;
if (firstReturn instanceof ParameterReturnValue) {
if (firstReturn instanceof ParameterReturnValue parameterReturnValue) {
// first contract is like "!null -> param1"; ignore other contracts
int index = ((ParameterReturnValue)firstReturn).getParameterNumber();
int index = parameterReturnValue.getParameterNumber();
int nullIndex = condition.getNullCheckedArgument(false).orElse(-1);
if (nullIndex != index) return null;
return new NullCheckParameter(nullIndex, false, true);
@@ -96,12 +86,18 @@ public final class ObviousNullCheckInspection extends AbstractBaseJavaLocalInspe
boolean returnsParameter = false;
if (contracts.size() == 2) {
ContractReturnValue returnValue = JavaMethodContractUtil.getNonFailingReturnValue(contracts);
if (returnValue instanceof ParameterReturnValue && ((ParameterReturnValue)returnValue).getParameterNumber() == nullIndex) {
if (returnValue instanceof ParameterReturnValue result && result.getParameterNumber() == nullIndex) {
returnsParameter = true;
} else {
return null;
}
}
if (!returnsParameter && !PsiTypes.voidType().equals(method.getReturnType())) {
// Method returns something that differs from the parameter: it's not a simple null-check method.
// If its result is nevertheless not used, then it's a job of IgnoreResultOfCallInspection to
// report it.
return null;
}
return new NullCheckParameter(nullIndex, isNull, returnsParameter);
}
}

View File

@@ -30,7 +30,7 @@ abstract class ObviousNullCheck {
}
void testStrings(List<String> list) {
list.forEach(s -> concat(<warning descr="Redundant null-check: literal is never null">"Not null!"</warning>, s));
list.forEach(s -> concat("Not null!", s));
list.stream().map(s -> concat("Not null!", s)).forEach(System.out::println);
}