mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Optional presence fact should also report non-null (IDEA-201584)
This commit is contained in:
@@ -149,9 +149,9 @@ public abstract class ContractValue {
|
||||
}
|
||||
};
|
||||
static final IndependentValue OPTIONAL_PRESENT =
|
||||
new IndependentValue(factory -> factory.getFactValue(DfaFactType.OPTIONAL_PRESENCE, true), "present");
|
||||
new IndependentValue(factory -> DfaOptionalSupport.getOptionalValue(factory, true), "present");
|
||||
static final IndependentValue OPTIONAL_ABSENT =
|
||||
new IndependentValue(factory -> factory.getFactValue(DfaFactType.OPTIONAL_PRESENCE, false), "empty");
|
||||
new IndependentValue(factory -> DfaOptionalSupport.getOptionalValue(factory, false), "empty");
|
||||
static final IndependentValue ZERO = new IndependentValue(factory -> factory.getInt(0), "0");
|
||||
|
||||
private final Function<? super DfaValueFactory, ? extends DfaValue> mySupplier;
|
||||
|
||||
+2
-2
@@ -199,10 +199,10 @@ class CustomMethodHandlers {
|
||||
|
||||
private static DfaValue ofNullable(DfaValue argument, DfaMemoryState state, DfaValueFactory factory) {
|
||||
if (state.isNull(argument)) {
|
||||
return factory.getFactValue(DfaFactType.OPTIONAL_PRESENCE, false);
|
||||
return DfaOptionalSupport.getOptionalValue(factory, false);
|
||||
}
|
||||
if (state.isNotNull(argument)) {
|
||||
return factory.getFactValue(DfaFactType.OPTIONAL_PRESENCE, true);
|
||||
return DfaOptionalSupport.getOptionalValue(factory, true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+14
@@ -17,6 +17,8 @@ package com.intellij.codeInspection.dataFlow;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValue;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -83,6 +85,18 @@ public class DfaOptionalSupport {
|
||||
return "get".equals(name) || "getAsDouble".equals(name) || "getAsInt".equals(name) || "getAsLong".equals(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DfaValue which represents present or absent optional (non-null)
|
||||
* @param factory a value factory to use
|
||||
* @param present whether the value should be present
|
||||
* @return a DfaValue representing an Optional
|
||||
*/
|
||||
@NotNull
|
||||
public static DfaValue getOptionalValue(DfaValueFactory factory, boolean present) {
|
||||
DfaFactMap facts = DfaFactMap.EMPTY.with(DfaFactType.OPTIONAL_PRESENCE, present).with(DfaFactType.NULLABILITY, DfaNullability.NOT_NULL);
|
||||
return factory.getFactFactory().createValue(facts);
|
||||
}
|
||||
|
||||
private static class ReplaceOptionalCallFix implements LocalQuickFix {
|
||||
private final String myTargetMethodName;
|
||||
private final boolean myClearArguments;
|
||||
|
||||
+8
-8
@@ -17,7 +17,7 @@ package com.intellij.codeInspection.dataFlow.inliner;
|
||||
|
||||
import com.intellij.codeInsight.Nullability;
|
||||
import com.intellij.codeInspection.dataFlow.CFGBuilder;
|
||||
import com.intellij.codeInspection.dataFlow.DfaFactType;
|
||||
import com.intellij.codeInspection.dataFlow.DfaOptionalSupport;
|
||||
import com.intellij.codeInspection.dataFlow.NullabilityProblemKind;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValue;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
|
||||
@@ -175,14 +175,14 @@ public class OptionalChainInliner implements CallInliner {
|
||||
DfaValueFactory factFactory = builder.getFactory();
|
||||
if (pushIntermediateOperationValue(builder, call)) {
|
||||
builder.ifNotNull()
|
||||
.push(factFactory.getFactValue(DfaFactType.OPTIONAL_PRESENCE, true))
|
||||
.push(DfaOptionalSupport.getOptionalValue(factFactory, true))
|
||||
.elseBranch()
|
||||
.push(factFactory.getFactValue(DfaFactType.OPTIONAL_PRESENCE, false))
|
||||
.push(DfaOptionalSupport.getOptionalValue(factFactory, false))
|
||||
.end();
|
||||
return true;
|
||||
}
|
||||
if (OPTIONAL_EMPTY.test(call)) {
|
||||
builder.push(factFactory.getFactValue(DfaFactType.OPTIONAL_PRESENCE, false));
|
||||
builder.push(DfaOptionalSupport.getOptionalValue(factFactory, false));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -224,7 +224,7 @@ public class OptionalChainInliner implements CallInliner {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
DfaValue presentOptional = builder.getFactory().getFactValue(DfaFactType.OPTIONAL_PRESENCE, true);
|
||||
DfaValue presentOptional = DfaOptionalSupport.getOptionalValue(builder.getFactory(), true);
|
||||
builder
|
||||
.pushExpression(expression)
|
||||
.checkNotNull(dereferenceContext, problem)
|
||||
@@ -294,16 +294,16 @@ public class OptionalChainInliner implements CallInliner {
|
||||
.boxUnbox(argument, optionalElementType);
|
||||
if ("of".equals(qualifierCall.getMethodExpression().getReferenceName())) {
|
||||
builder.checkNotNull(argument, NullabilityProblemKind.passingNullableToNotNullParameter)
|
||||
.push(builder.getFactory().getFactValue(DfaFactType.OPTIONAL_PRESENCE, true), qualifierCall)
|
||||
.push(DfaOptionalSupport.getOptionalValue(builder.getFactory(), true), qualifierCall)
|
||||
.pop();
|
||||
}
|
||||
else {
|
||||
builder
|
||||
.dup()
|
||||
.ifNull()
|
||||
.push(builder.getFactory().getFactValue(DfaFactType.OPTIONAL_PRESENCE, false), qualifierCall)
|
||||
.push(DfaOptionalSupport.getOptionalValue(builder.getFactory(), false), qualifierCall)
|
||||
.elseBranch()
|
||||
.push(builder.getFactory().getFactValue(DfaFactType.OPTIONAL_PRESENCE, true), qualifierCall)
|
||||
.push(DfaOptionalSupport.getOptionalValue(builder.getFactory(), true), qualifierCall)
|
||||
.end()
|
||||
.pop();
|
||||
}
|
||||
|
||||
+4
-4
@@ -262,12 +262,12 @@ public class StreamChainInliner implements CallInliner {
|
||||
|
||||
@Override
|
||||
protected void pushInitialValue(CFGBuilder builder) {
|
||||
builder.push(builder.getFactory().getFactValue(DfaFactType.OPTIONAL_PRESENCE, false));
|
||||
builder.push(DfaOptionalSupport.getOptionalValue(builder.getFactory(), false));
|
||||
}
|
||||
|
||||
@Override
|
||||
void iteration(CFGBuilder builder) {
|
||||
DfaValue presentOptional = builder.getFactory().getFactValue(DfaFactType.OPTIONAL_PRESENCE, true);
|
||||
DfaValue presentOptional = DfaOptionalSupport.getOptionalValue(builder.getFactory(), true);
|
||||
if (myFunction != null) {
|
||||
builder.push(myResult)
|
||||
.push(presentOptional)
|
||||
@@ -291,7 +291,7 @@ public class StreamChainInliner implements CallInliner {
|
||||
|
||||
@Override
|
||||
protected void pushInitialValue(CFGBuilder builder) {
|
||||
builder.push(builder.getFactory().getFactValue(DfaFactType.OPTIONAL_PRESENCE, false));
|
||||
builder.push(DfaOptionalSupport.getOptionalValue(builder.getFactory(), false));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -303,7 +303,7 @@ public class StreamChainInliner implements CallInliner {
|
||||
@Override
|
||||
void iteration(CFGBuilder builder) {
|
||||
myComparatorModel.invoke(builder);
|
||||
builder.assignAndPop(myResult, builder.getFactory().getFactValue(DfaFactType.OPTIONAL_PRESENCE, true));
|
||||
builder.assignAndPop(myResult, DfaOptionalSupport.getOptionalValue(builder.getFactory(), true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -250,4 +250,11 @@ public class StreamInlining {
|
||||
public static void testBoxingExplicit2() {
|
||||
double s = Stream.of(1).mapToDouble(x -> x * x).sum();
|
||||
}
|
||||
|
||||
void testOptionalNullity(List<Integer> groups) {
|
||||
Optional<Integer> optional = groups.stream().findFirst();
|
||||
if (<warning descr="Condition 'optional != null' is always 'true'">optional != null</warning> && optional.isPresent()) {
|
||||
System.out.println("found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user