mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
DFA: add missing box/unbox conversions
This commit is contained in:
@@ -358,7 +358,7 @@ public class CFGBuilder {
|
||||
*
|
||||
* @return this builder
|
||||
*/
|
||||
public CFGBuilder boxUnbox(PsiExpression expression, PsiType expectedType) {
|
||||
public CFGBuilder boxUnbox(@NotNull PsiExpression expression, PsiType expectedType) {
|
||||
myAnalyzer.generateBoxingUnboxingInstructionFor(expression, expectedType);
|
||||
return this;
|
||||
}
|
||||
|
||||
+2
@@ -11,6 +11,7 @@ import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiMethodCallExpression;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
@@ -67,6 +68,7 @@ public class MapUpdateInliner implements CallInliner {
|
||||
.pushExpression(key)
|
||||
.pop()
|
||||
.pushExpression(value)
|
||||
.boxUnbox(value, ExpectedTypeUtils.findExpectedType(value, false))
|
||||
.checkNotNull(value, NullabilityProblemKind.passingNullableToNotNullParameter)
|
||||
.evaluateFunction(function)
|
||||
.pushUnknown()
|
||||
|
||||
+27
-11
@@ -26,10 +26,7 @@ import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PropertyUtilBase;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
@@ -283,19 +280,19 @@ public class DfaExpressionFactory {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DfaValue getAdvancedExpressionDfaValue(@Nullable PsiExpression expression) {
|
||||
private DfaValue getAdvancedExpressionDfaValue(@Nullable PsiExpression expression, @Nullable PsiType targetType) {
|
||||
if (expression == null) return DfaUnknownValue.getInstance();
|
||||
DfaValue value = getExpressionDfaValue(expression);
|
||||
if (value != null) {
|
||||
return value;
|
||||
return boxUnbox(value, targetType);
|
||||
}
|
||||
if (expression instanceof PsiConditionalExpression) {
|
||||
return getAdvancedExpressionDfaValue(((PsiConditionalExpression)expression).getThenExpression()).union(
|
||||
getAdvancedExpressionDfaValue(((PsiConditionalExpression)expression).getElseExpression()));
|
||||
return getAdvancedExpressionDfaValue(((PsiConditionalExpression)expression).getThenExpression(), targetType).union(
|
||||
getAdvancedExpressionDfaValue(((PsiConditionalExpression)expression).getElseExpression(), targetType));
|
||||
}
|
||||
PsiType type = expression.getType();
|
||||
if (type instanceof PsiPrimitiveType) return DfaUnknownValue.getInstance();
|
||||
return myFactory.createTypeValue(type, NullabilityUtil.getExpressionNullability(expression));
|
||||
return boxUnbox(myFactory.createTypeValue(type, NullabilityUtil.getExpressionNullability(expression)), targetType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -311,18 +308,37 @@ public class DfaExpressionFactory {
|
||||
DfaVariableValue arrayDfaVar = (DfaVariableValue)array;
|
||||
PsiModifierListOwner arrayPsiVar = arrayDfaVar.getPsiVariable();
|
||||
if (!(arrayPsiVar instanceof PsiVariable)) return DfaUnknownValue.getInstance();
|
||||
PsiType arrayType = ((PsiVariable)arrayPsiVar).getType();
|
||||
PsiType targetType = arrayType instanceof PsiArrayType ? ((PsiArrayType)arrayType).getComponentType() : null;
|
||||
PsiExpression[] elements = ExpressionUtils.getConstantArrayElements((PsiVariable)arrayPsiVar);
|
||||
if (elements == null || elements.length == 0) return DfaUnknownValue.getInstance();
|
||||
indexSet = indexSet.intersect(LongRangeSet.range(0, elements.length - 1));
|
||||
if (indexSet.isEmpty() || indexSet.max() - indexSet.min() > 100) return DfaUnknownValue.getInstance();
|
||||
return LongStreamEx.of(indexSet.stream())
|
||||
.mapToObj(idx -> getAdvancedExpressionDfaValue(elements[(int)idx]))
|
||||
.mapToObj(idx -> getAdvancedExpressionDfaValue(elements[(int)idx], targetType))
|
||||
.prefix(DfaValue::union)
|
||||
.takeWhileInclusive(value -> value != DfaUnknownValue.getInstance())
|
||||
.reduce((a, b) -> b)
|
||||
.orElse(DfaUnknownValue.getInstance());
|
||||
}
|
||||
|
||||
private DfaValue boxUnbox(DfaValue value, PsiType type) {
|
||||
if (TypeConversionUtil.isPrimitiveWrapper(type)) {
|
||||
if (value instanceof DfaConstValue || value instanceof DfaUnboxedValue ||
|
||||
(value instanceof DfaVariableValue && TypeConversionUtil.isPrimitiveAndNotNull(((DfaVariableValue)value).getVariableType()))) {
|
||||
DfaValue boxed = myFactory.getBoxedFactory().createBoxed(value);
|
||||
return boxed == null ? DfaUnknownValue.getInstance() : boxed;
|
||||
}
|
||||
}
|
||||
if (TypeConversionUtil.isPrimitiveAndNotNull(type)) {
|
||||
if (value instanceof DfaBoxedValue ||
|
||||
(value instanceof DfaVariableValue && TypeConversionUtil.isPrimitiveWrapper(((DfaVariableValue)value).getVariableType()))) {
|
||||
return myFactory.getBoxedFactory().createUnboxed(value);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Contract("null, _ -> null")
|
||||
@Nullable
|
||||
public DfaValue getArrayElementValue(DfaValue array, int index) {
|
||||
@@ -335,7 +351,7 @@ public class DfaExpressionFactory {
|
||||
if (arrayPsiVar instanceof PsiVariable) {
|
||||
PsiExpression constantArrayElement = ExpressionUtils.getConstantArrayElement((PsiVariable)arrayPsiVar, index);
|
||||
if (constantArrayElement != null) {
|
||||
return getAdvancedExpressionDfaValue(constantArrayElement);
|
||||
return getAdvancedExpressionDfaValue(constantArrayElement, componentType);
|
||||
}
|
||||
}
|
||||
ArrayElementSource indexVariable = getArrayIndexVariable(index);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
class Test {
|
||||
private final static Integer[] DATA = {119, 7, 3};
|
||||
private final static int[] DATA2 = {119, 7, 3};
|
||||
|
||||
void test() {
|
||||
for(int i=0; i<DATA.length; i++) {
|
||||
Integer val = DATA[i];
|
||||
int val2 = DATA2[i];
|
||||
if (val != val2) {
|
||||
System.out.println("Trouble");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,4 +59,8 @@ class MapUpdateInlining {
|
||||
System.out.println("impossible");
|
||||
}
|
||||
}
|
||||
|
||||
void testBoxing(Map<String, Integer> map, String key) {
|
||||
map.merge(key, 1, (i1, i2) -> i1+1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,4 +620,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
|
||||
public void testNanComparisonWrong() { doTest(); }
|
||||
public void testConstantMethods() { doTest(); }
|
||||
public void testPolyadicEquality() { doTest(); }
|
||||
public void testBoxUnboxArrayElement() { doTest(); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user